一、模板匹配概念
模板匹配是一项在一副图像中寻找与另一幅模板图像最匹配(相似)部分的技术。模板匹配不是基于直方图的,而是通过在输入图像上滑动图像块(模板)同时对比相似度,来对模板和输入图像进行匹配的一种方法。
应用:
(1)目标查找定位
(2)运动物体跟踪
1、模板匹配 --- matchTemplate()
1 CV_EXPORTS_W void matchTemplate(InputArray image, InputArray temp1, OutputArray result, int method);
image:待搜索图像(大图)
temp1:搜索模板,需和原图一样数据类型且尺寸大小不能大于源图像
reuslt:比较结果的映射图像,其必须为单通道的,32位浮点型图像,如果原图(待搜索图像)尺寸为W*H,二temp1的尺寸为w*h,则result的尺寸一定是(W-w+1)*(H-h+1)
method:指定的匹配方法,有如下六种:
1 CV_TM_SQDIFF --- 平方差匹配法(最好匹配0) 2 CV_TM_SQDIFF_NORMED --- 归一化平方差匹配法(最好匹配0) 3 CV_TM_CCORR --- 相关匹配法(最坏匹配0) 4 CV_TM_CCORR_NORMED ---归一化相关匹配法(最坏匹配0) 5 CV_TM_CCOEFF --- 系数匹配法(最好匹配1) 6 CV_TM_CCOEFF_NORMED --- 归一化系数匹配法(最好匹配1)
2、矩阵归一化 --- normalize()
1 C++: void normalize(InputArray src,OutputArray dst, double alpha=1,
double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )
src:输入源图像,Mat类型
dst:输出结果图像,需要和原图一样的尺寸和类型
alpha:归一化后的最小值,默认为1
beta:归一化后的最大值,默认为0
norm_type:归一化类型,可选:NORM_INF, NORM_L1, NORM_L2(默认)等
dtype:默认值为-1,此参数为负值时,输出矩阵和src有同样的类型
mask:可选的掩码操作
normallize()函数的作用是进行矩阵归一化。
3、寻找最值 --- minMaxLoc()
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());
src:输入源图像,单通道图像
minVal:返回最小值的指针,若无需返回,则置为0
maxVal:返回最大值的指针,若无需返回,则置为0
minLoc:返回最小位置的指针,若无需返回,则置为0
maxLoc:返回最大位置的指针,若无需返回,则置为0
mask:可选的掩码操作
minMaxLoc()函数的作用是在数组中找到全局最小值和最大值
二、单模板匹配
【示例】
1 //模板匹配 2 #include "opencv2/opencv.hpp" 3 #include <iostream> 4 5 using namespace std; 6 using namespace cv; 7 8 int main() 9 { 10 Mat temp=imread("mu.jpg"); 11 Mat src=imread("1.jpg"); 12 Mat dst=src.clone(); 13 imshow("temp",temp); 14 15 int width=src.cols-temp.cols+1;//result宽度 16 int height=src.rows-temp.rows+1;//result高度 17 18 Mat result(height,width,CV_32FC1);//创建结果映射图像 19 //matchTemplate(srcImg, templateImg, resultImg, CV_TM_SQDIFF); //平方差匹配法(最好匹配0) 20 //matchTemplate(srcImg, templateImg, resultImg, CV_TM_SQDIFF_NORMED); //归一化平方差匹配法(最好匹配0) 21 //matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCORR); //相关匹配法(最坏匹配0) 22 //matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCORR_NORMED); //归一化相关匹配法(最坏匹配0) 23 //matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCOEFF); //系数匹配法(最好匹配1) 24 matchTemplate(src,temp,result,CV_TM_CCOEFF_NORMED);//化相关系数匹配,最佳值1 25 imshow("result",result); 26 normalize(result,result,0,1,NORM_MINMAX,-1);//归一化到0-1范围 27 28 double minValue,maxValue; 29 Point minLoc,maxLoc; 30 minMaxLoc(result,&minValue,&maxValue,&minLoc,&maxLoc); 31 cout<<"minValue="<<minValue<<endl; 32 cout<<"maxValue="<<maxValue<<endl; 33 34 rectangle(dst,maxLoc,Point(maxLoc.x+temp.cols,maxLoc.y+temp.rows),Scalar(0,255,0),2,8); 35 imshow("dst",dst); 36 37 waitKey(0); 38 return 0; 39 }
注意:result的长宽正好是(原图-模板图)的长宽,result图中白亮程度表示匹配程度
三、视频模板匹配
【示例】
1 //视频模板匹配 2 #include "opencv2/opencv.hpp" 3 #include <iostream> 4 5 using namespace std; 6 using namespace cv; 7 8 int main() 9 { 10 Mat frame,resultImg; 11 Mat templateImg = imread("green.jpg"); 12 VideoCapture cap("1.mp4"); 13 if(!cap.isOpened()) 14 return; 15 int resultImg_cols,resultImg_rows; 16 17 while(1) 18 { 19 cap>>frame; 20 if(frame.empty()) break; 21 Mat showImg = frame.clone(); 22 resultImg_cols = frame.cols - templateImg.cols + 1; 23 resultImg_rows = frame.rows - templateImg.rows + 1; 24 resultImg.create(resultImg_cols, resultImg_rows, CV_32FC1); 25 matchTemplate(frame, templateImg, resultImg, CV_TM_CCOEFF_NORMED); //归一化相关系数匹配法(最好匹配1) 26 normalize(resultImg, resultImg, 0, 1, NORM_MINMAX); 27 28 double minValue, maxValue; 29 Point minLoc, maxLoc; 30 Point matchLoc; 31 32 minMaxLoc(resultImg, &minValue, &maxValue, &minLoc, &maxLoc); 33 cout<<"max_value= "<<maxValue<<endl; 34 //cout<<"min_value= "<<minValue<<endl; 35 if(maxValue>=0.7) 36 rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2); 37 imshow("frame", frame); 38 imshow("result", showImg); 39 if(27 == waitKey(10)) 40 break; 41 } 42 destroyAllWindows(); 43 44 waitKey(0); 45 return 0; 46 }
四、多模板匹配
【示例】
1 //多模板匹配 2 #include "opencv2/opencv.hpp" 3 #include <iostream> 4 #include <stdio.h> 5 6 using namespace std; 7 using namespace cv; 8 9 int main() 10 { 11 Mat srcImg = imread("E://src.png"); 12 Mat templateImg = imread("E://temp.png"); 13 Mat resultImg; 14 Mat showImg = srcImg.clone(); 15 16 int resultImg_cols = srcImg.cols - templateImg.cols + 1; 17 int resultImg_rows = srcImg.rows - templateImg.rows + 1; 18 19 resultImg.create(resultImg_cols, resultImg_rows, CV_32FC1); 20 matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCOEFF_NORMED); //化相关系数匹配法(最好匹配1) 21 normalize(resultImg, resultImg, 0, 1, NORM_MINMAX); 22 Mat midImg = resultImg.clone(); 23 24 //多目标模板匹配---方法一 25 /*double matchValue; 26 int count0=0; 27 int tempW=0, tempH=0; 28 char matchRate[10]; 29 30 for(int i=0; i<resultImg_rows; i++) 31 { 32 for(int j=0; j<resultImg_cols; j++) 33 { 34 matchValue = resultImg.at<float>(i, j); 35 sprintf(matchRate, "%0.2f", matchValue); 36 if(matchValue>=0.85 && (abs(j - tempW)>5) && (abs(i - tempH)>5) ) 37 { 38 count0++; 39 putText(showImg, matchRate, Point(j-5, i-5), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 1); 40 rectangle(showImg, Point(j, i), Point(j + templateImg.cols, i + templateImg.rows), Scalar(0, 255, 0), 2); 41 tempW = j; 42 tempH = i; 43 } 44 } 45 } 46 cout<<"count="<<count0<<endl; 47 imshow("resultImg", resultImg); 48 imshow("dst", showImg);*/ 49 50 //多目标模板匹配---方法二 51 double minValue, maxValue; 52 Point minLoc, maxLoc; 53 Point matchLoc; 54 char matchRate[10]; 55 56 for(int i=0; i<100; i++) 57 { 58 int startX = maxLoc.x - 4; 59 int startY = maxLoc.y - 4; 60 int endX = maxLoc.x + 4; 61 int endY = maxLoc.y + 4; 62 if(startX<0 || startY<0) 63 { 64 startX = 0; 65 startY = 0; 66 } 67 if(endX > resultImg.cols - 1 || endY > resultImg.rows - 1) 68 { 69 endX = resultImg.cols - 1; 70 endY = resultImg.rows- 1; 71 } 72 Mat temp = Mat::zeros(endX - startX, endY - startY, CV_32FC1); 73 //Mat ROI = resultImg(Rect(Point(startX, startY), temp.cols, temp.rows)); 74 temp.copyTo(resultImg(Rect(startX, startY, temp.cols, temp.rows))); 75 minMaxLoc(resultImg, &minValue, &maxValue, &minLoc, &maxLoc); 76 if(maxValue<0.8) break; 77 78 cout<<"max_value= "<<maxValue<<endl; 79 sprintf(matchRate, "%0.2f", maxValue); 80 putText(showImg, matchRate, Point(maxLoc.x - 5, maxLoc.y - 5), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 1); 81 rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2); 82 83 } 84 imshow("midImg", midImg); 85 imshow("resultImg", resultImg); 86 imshow("dst", showImg); 87 88 waitKey(0); 89 return 0; 90 }