OpenCV minMaxLoc()函数找出图像中最小值最大值

  行业动态     |      2024-01-15 16:03

文章目录

OpenCV 找出图像中最小值最大值函数minMaxLoc的使用
功能:从一个矩阵中找出全局的最大值和最小值。

函数cv::minMaxLoc找出最大和最小元素的值和他们的位置。极值是遍历整个矩阵找到,或者当掩码不是一个空矩阵时,是通过遍历指定矩阵区域找到。

函数不适用于多通道矩阵,如果需要遍历所有的通道来找到最大和最小值,首先使用函数Mat::reshape转换为单通道矩阵。或者你可以使用函数 extractImageCOI ,mixChannels , or split 来提取特定通道。

1 函数解析

1.1 函数原型1

CV_EXPORTS_W void minMaxLoc(InputArray src, CV_OUT double* minVal,
                             CV_OUT double* maxVal = 0, CV_OUT Point* minLoc = 0,
                             CV_OUT Point* maxLoc = 0, InputArray mask = noArray());

参数说明:

参数1:InputArray类型的src,输入单通道数组(图像)。
参数2double*类型的minVal,返回最小值的指针。若无须返回,此值置为NULL。
参数3double*类型的maxVal,返回最大值的指针。若无须返回,此值置为NULL。
参数4:Point*类型的minLoc,返回最小位置的指针(二维情况下)。若无须返回,此值置为NULL。
参数5:Point*类型的maxLoc,返回最大位置的指针(二维情况下)。若无须返回,此值置为NULL。
参数6:InputArray类型的mask,用于选择子阵列的可选掩膜。

1.2 函数原型2

 CV_EXPORTS void minMaxIdx(InputArray src, double* minVal, double* maxVal = 0,
                           int* minIdx = 0, int* maxIdx = 0, InputArray mask = noArray());

参数说明:

参数1 src 输入单通道矩阵.

参数1 minVal 返回最小值的指针; 如果不需要输入NULL.

参数 maxVal 返回最大值的指针; 如果不需要输入NULL.

参数 minIdx 返回最小值位置的指针 ((n维情况下); 如果不需要输入NULL. 否则,它必须指向src.dims元素的一个矩阵, 每个维度里最小元素的坐标按顺序存储.

参数 maxIdx 返回最大值位置的指针 ((n维情况下); 如果不需要输入NULL.

参数 mask 指定矩阵区域.

注意:
在稀疏矩阵中,最小值是只能在非零元素中找到。

当minIdx 不是NULL的时候,他必须有至少两个元素(同maxIdx),即使src是一个单行或者单列矩阵。在OpenCV (跟随MATLAB)中每个矩阵至少要有两个维度。单列矩阵是Mx1 矩阵(因此 minIdx/maxIdx将是(i1,0)/(i2,0)),单行矩阵是 1xN矩阵(因此minIdx/maxIdx 将是(0,j1)/(0,j2))。

1.2 函数原型3

 CV_EXPORTS void minMaxLoc(const SparseMat& a, double* minVal,
                           double* maxVal, int* minIdx = 0, int* maxIdx = 0);

参数说明:

参数1 a 输入单通道矩阵.

参数2 minVal 返回最小值的指针; 如果不需要输入NULL.

参数3 maxVal 返回最大值的指针; 如果不需要输入NULL.

参数4 minIdx 返回最小值位置的指针 ((n维情况下); 如果不需要输入NULL. 否则,它必须指向src.dims元素的一个矩阵, 每个维度里最小元素的坐标按顺序存储.

参数5 maxIdx 返回最大值位置的指针 ((n维情况下); 如果不需要输入NULL.

2 示例

对"lena.png"图像进行三通道分离,
找出每个通道颜色的最小值和最大值

#include
#include
#include
using namespace std;
using namespace cv;
int main() {
    Mat src = imread("lena.png");
    imshow("src", src);

    //通道分离
    vector<Mat>images;
    split(src, images);

    //计算各通道直方图,并进行统计
    //https://www.cnblogs.com/bjxqmy/p/12378312.html
    vector<Mat>bgr(3);
    int channels[] = { 0,1,2 };
    int histsize[] = { 10,10,10 };
    float r[] = { 0,255 };
    const float* ranges[] = { r,r,r };
    Scalar colors[] = { Scalar(255,0,0),Scalar(0,255,0),Scalar(0,0,255) };
    string names[] = { "蓝色通道","绿色通道","红色通道" };
    for (int i = 0; i < 3; i++) {
        calcHist(&src, 3, &channels[i], Mat(), bgr[i], 1, &histsize[i], &ranges[i], true);
        normalize(bgr[i], bgr[i], 1, 0, NORM_L1);//https://www.cnblogs.com/bjxqmy/p/12292421.html
        double mx, mn; Point pmx, pmn;
        minMaxLoc(bgr[i], &mn, &mx, &pmn, &pmx);

        double width = 255.0 / histsize[i];
        cout << names[i] << endl;
        cout << "数量最少的颜色范围:[" << pmn.y * width << "," << (pmn.y + 1) * width << "] 占比:" << mn * 100 << "%" << endl;
        cout << "数量最多的颜色范围:[" << pmx.y * width << "," << (pmx.y + 1) * width << "] 占比:" << mx * 100 << "%" << endl;
        cout << endl;

        imshow(names[i], images[i]);
    }
    waitKey(0);
}