1模板匹配
1.1绪论
模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。
所以模板匹配首先需要一个模板图像T(给定的子图像)。
另外需要一个待检测的图像-源图像S。
工作方法,在带检测图像上,从左到右,从上向下计算模板图像与重叠子图像的匹配度,匹配程度越大,两者相同的可能性越大。
模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。
1.2常用匹配算法
1)平方差匹配-CV_TM_SQDIFF
从名字来理解,平方差匹配就是通过计算每个像素点的差的平方的和,和数学中统计里面的平方差类似。但是因为我们要的只是一个值,所以我们最后不需要求平均。
如果相近,则每个差都很小,最终的和也很小,如果完全一致,则差为0,所以最好的匹配就是这个值为零的时候。值越大,匹配越差。
2)标准平方差匹配-CV_TM_SQDIFF_NORMED
这个只是对上面的进行了标准化处理,经过处理后,上面的值就不会太大。
3)相关匹配-CV_TM_CCORR
这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。
4)标准相关匹配-CV_TM_CCORR_NORMED
这个只是对上面的进行了标准化处理,经过处理后,上面的值就不会太大。
5)相关匹配-CV_TM_CCOEFF
这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。
6)标准相关匹配-CV_TM_CCOEFF_NORMED
这个只是对上面的进行了标准化处理,经过处理后,上面的值就不会太大。
1.3相应的API
void matchTemplate(
InputArray image,
InputArray templ,
OutputArray result,
int method,
InputArray mask = noArray()
);
参数说明:
(1)InputArray类型的src ,运行搜索的图像。它必须是8位或32位浮点。
(2)InputArray类型的templ,已搜索模板。它不能大于源映像,并且具有相同的数据类型。。
(3)OutputArray类型的result,比较结果的映射。它必须是单通道32位浮点。
(4)int类型的method,指定比较方法的参数,请参见cv::TemplateMatchModes。
(5)InputArray类型的mask,搜索模板的掩码。它必须与temp具有相同的数据类型和大小。默认情况下不设置。
```cpp
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());
这个函数可以在一个矩阵中寻找最大点或最小点,并将位置返回回来。
综合示例:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
Mat src, temp, dst;
int match_method = TM_SQDIFF;
int max_track = 5;
const char* INPUT_T = "input image";
const char* OUTPUT_T = "result image";
const char* match_t = "template match-demo";
void Match_Demo(int, void*);
int main(int argc, char** argv) {
// 待检测图像
src = imread("E:/cvpicture/1.png");
// 模板图像
temp = imread("E:/cvpicture/12.png");
if (src.empty() || temp.empty()) {
printf("could not load image...\n");
return -1;
}
namedWindow(INPUT_T, CV_WINDOW_AUTOSIZE);
namedWindow(OUTPUT_T, CV_WINDOW_NORMAL);
namedWindow(match_t, CV_WINDOW_AUTOSIZE);
imshow(INPUT_T, temp);
const char* trackbar_title = "Match Algo Type:";
createTrackbar(trackbar_title, OUTPUT_T, &match_method, max_track, Match_Demo);
Match_Demo(0, 0);
waitKey(0);
return 0;
}
void Match_Demo(int, void*) {
int width = src.cols - temp.cols + 1;
int height = src.rows - temp.rows + 1;
//创建结果输出矩阵
Mat result(width, height, CV_32FC1);
//进行匹配和标准化
matchTemplate(src, temp, result, match_method, Mat());
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
Point minLoc;
Point maxLoc;
double min, max;
src.copyTo(dst);
Point temLoc;
//通过函数minMaxLoc定位最佳匹配位置
minMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat());
// 对于方法 SQDIFF 和 SQDIFF_NORMED, 越小的数值代表更高的匹配结果. 而对于其他方法, 数值越大匹配越好
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED) {
temLoc = minLoc;
}
else {
temLoc = maxLoc;
}
// 绘制矩形
rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);
rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);
imshow(OUTPUT_T, result);
imshow(match_t, dst);
}
2轮廓发现(find contour)
2.1绪论
轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法。所以边缘提取的阈值选定会影响最终轮廓发现结果。
对于opencv计算机视觉来说,轮廓发现就是通过对图像进行处理之后,提取物体的轮廓的操作。想要提取图像的轮廓,我们就肯定要先找到图像的边缘。
因此,在opencv中,我们想要获得图像的轮廓,分为两部分操作:
1)发现轮廓
2)绘制轮廓
2.2相应的API
在二值图像上发现轮廓使用API cv::findContours(
InputOutputArray binImg, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit
OutputArrayOfArrays contours,// 全部发现的轮廓对象
OutputArray, hierachy// 图该的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。
int mode, // 轮廓返回的模式
int method,// 发现方法
Point offset=Point()// 轮廓像素的位移,默认(0, 0)没有位移
)
在二值图像上发现轮廓使用API cv