OpenCV是一个开源的计算机视觉库,提供了许多图像处理和计算机视觉方面的功能。其中,minMaxLoc函数是OpenCV中非常重要的一个函数,用于查找图像中的最大值和最小值及其位置。本文将介绍minMaxLoc函数的相关知识,包括函数的介绍、函数原型和参数说明、函数使用的场景、完整代码实例以及总结等。
一、函数的介绍
minMaxLoc
函数用于在一幅图像中查找最大值和最小值及其位置。该函数可以应用于灰度图像和彩色图像,支持多通道图像。使用该函数可以方便地进行图像分割、特征提取等任务。
二、函数原型和参数说明
下面是minMaxLoc
函数的原型和参数说明:
double cv::minMaxLoc(InputArray src, OutputArray minVal, OutputArray maxVal, OutputArray minLoc, OutputArray maxLoc, InputArray mask = noArray());
其中,各个参数的含义如下:
src
:输入图像或矩阵,可以是单通道、多通道或彩色图像。minVal
:输出参数,指向一个double类型的指针,用于存储计算得到的最小值。maxVal
:输出参数,指向一个double类型的指针,用于存储计算得到的最大值。如果不提供此参数,则默认为0。minLoc
:输出参数,指向一个Point类型的指针,用于存储计算得到的最小值的位置。如果不提供此参数,则默认为0。maxLoc
:输出参数,指向一个Point类型的指针,用于存储计算得到的最大值的位置。如果不提供此参数,则默认为0。mask
:可选参数,输入图像或矩阵,用于指定感兴趣区域。只有位于mask内的像素才会被计算最小值和最大值。如果不提供此参数,则默认为noArray()。
三、函数使用的场景
minMaxLoc
函数可以应用于以下场景:
- 图像分割:在图像分割中,需要找到图像中的前景和背景,可以使用
minMaxLoc
函数来确定前景和背景的阈值。 - 目标检测:在目标检测中,需要找到目标的位置,可以使用
minMaxLoc
函数来确定目标的边界框。 - 特征提取:在特征提取中,需要找到图像中的特征点,可以使用
minMaxLoc
函数来确定特征点的位置。
四、代码实例
下面是一个使用minMaxLoc
函数查找图像中最大值和最小值及其位置的完整代码实例:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
// 读取图像
Mat img = imread("test.jpg");
if (img.empty())
{
cout << "Failed to read image!" << endl;
return -1;
}
// 初始化输出参数
double minVal, maxVal;
Point minLoc, maxLoc;
// 查找最大值和最小值及其位置
minMaxLoc(img, &minVal, &maxVal, &minLoc, &maxLoc);
// 输出结果
cout << "Min value: " << minVal << endl;
cout << "Max value: " << maxVal << endl;
cout << "Min location: (" << minLoc.x << ", " << minLoc.y << ")" << endl;
cout << "Max location: (" << maxLoc.x << ", " << maxLoc.y << ")" << endl;
return 0;
}
下面是一个YoloV8推理程序中使用minMaxLoc
函数查找某张图像在coco数据集的80个分类(1维数组 1x80)中哪个类别的概率最大值及其分类Id的部分代码实例:
std::vector<Detection> Yolov8::detect(const cv::Mat& rawImg, cv::dnn::Net& net) {
clock_t t1 = clock();
// transform raw image with 3 channels
cv::Mat squareRawImg = tranformToSquare(rawImg);
cv::Mat blob;
// create 4-dimensional mat (1 ,3 , 640 , 640) which means (batch size + channels + height + width)
cv::dnn::blobFromImage(squareRawImg, blob, 1.0 / 255.0, cv::Size(netWidth, netHeight), cv::Scalar(), true, false);
clock_t t2 = clock();
// detect the object and get the outputs
net.setInput(blob);
std::vector<cv::Mat> outputs;
net.forward(outputs, net.getUnconnectedOutLayersNames());
clock_t t3 = clock();
// yolov8 has an output of shape (1, 84, 8400), 84=(box[x,y,w,h] + Num of classes),8400=the detection count
cv::Mat outputMat = outputs[0];
int rows = outputMat.size[2];
int dimensions = outputMat.size[1];
// change mat from (1, 84, 8400) to (84, 8400)
outputMat = outputMat.reshape(1, dimensions);
// change mat from (84, 8400) to (8400, 84)
cv::transpose(outputMat, outputMat);
float* data = (float*)outputMat.data;
float xFactor = (float)squareRawImg.cols / netWidth;
float yFactor = (float)squareRawImg.rows / netHeight;
std::vector<int> classIds;
std::vector<float> confidences;
std::vector<cv::Rect> boxes;
// iterate the 8400 detections and keep the result >= confidence thresold.
for (int i = 0; i < rows; ++i)
{
// get the score for every class and find out the class with highest score
cv::Mat scores(1, classes.size(), CV_32FC1, data + 4);
cv::Point classId;
double maxClassScore;
cv::minMaxLoc(scores, 0, &maxClassScore, 0, &classId);
if (maxClassScore >= confidenceThreshold)
{
confidences.push_back(maxClassScore);
classIds.push_back(classId.x);
float x = data[0]; // the center x for detection box
float y = data[1]; // the center y for detection box
float w = data[2]; // the width for detection box
float h = data[3]; // the height for detection box
int left = int((x - 0.5 * w) * xFactor);
int top = int((y - 0.5 * h) * yFactor);
int width = int(w * xFactor);
int height = int(h * yFactor);
boxes.push_back(cv::Rect(left, top, width, height));
}
data += dimensions;
}
...
}
五、总结
本文介绍了OpenCV中的minMaxLoc
函数,包括函数的介绍、函数原型和参数说明、函数使用的场景、完整代码实例以及总结等。minMaxLoc
函数是OpenCV中非常重要的一个函数,可以方便地进行图像分割、特征提取等任务。在实际应用中,我们可以根据具体需求选择不同的颜色空间转换码,以实现不同的图像处理任务。