opencv笔记(二十二)——模板匹配 template matching
模板匹配就是在给定一幅图像和一幅模板(一般模板比图像的尺寸小很多)的情况下,找到这个图像中最最相似于模板的位置,比如

第一幅是给定的图片,第二幅是模板,第三幅就是搜索到的匹配的位置。
这个搜索的过程,我没有在源码中求索,但是根据tutorial,应该是采用sliding window的方法,利用滑动的窗口,逐像素进行匹配。这个逐像素的意思,就是锚定某个像素之后,在这个像素的右边和下方,以template的宽度和高度的距离的范围内,进行模板与图像的相似度计算。

这种方法和行人检测中常用的方法类似。就是sliding window。
计算匹配度,即计算相似度的方法一般有以下六种:
-
method=CV_TM_SQDIFF
![R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2]()
-
method=CV_TM_SQDIFF_NORMED
![R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}]()
-
method=CV_TM_CCORR
![R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))]()
-
method=CV_TM_CCORR_NORMED
![R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}]()
-
method=CV_TM_CCOEFF
![R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I(x+x',y+y'))]()
where
![\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}]()
-
method=CV_TM_CCOEFF_NORMED
![R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }]()
第一种和第二种,是求得的结果越小越好。其余四种是求得的结果越大越好。注意,一般不使用第三种,因为这种方法在图像某块像素值普遍较大的情况下,就会错误匹配这个位置。看公式便知。
另外,我们的结果图像也有一点需要注意的,就是它的宽度是原图像宽度-模板宽度+1,它的高度是原图像高度-模板高度+1。为什么这样呢?想想便知。
当我们得到result之后,找到这个result当中的最大值或者最小值(取决于我们的相似度计算方法),就是找到匹配的位置。
OpenCV中对应的函数的介绍:
void matchTemplate(InputArray image, InputArray templ, OutputArray result, int method)
method从0到5,分别对应上述六种方法。
void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArraymask=noArray())
用来找最大值或者最小值及其位置的方法。
对应的使用范例:
1 /// Source image to display 2 Mat img_display; 3 img.copyTo( img_display ); 4 5 /// Create the result matrix 6 int result_cols = img.cols - templ.cols + 1; 7 int result_rows = img.rows - templ.rows + 1; 8 9 result.create( result_cols, result_rows, CV_32FC1 ); 10 11 /// Do the Matching and Normalize 12 matchTemplate( img, templ, result, match_method ); 13 normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() ); 14 15 /// Localizing the best match with minMaxLoc 16 double minVal; double maxVal; Point minLoc; Point maxLoc; 17 Point matchLoc; 18 19 minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); 20 21 /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better 22 if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED ) 23 { matchLoc = minLoc; } 24 else 25 { matchLoc = maxLoc; } 26 27 /// Show me what you got 28 rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 ); 29 rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 ); 30 31 imshow( image_window, img_display ); 32 imshow( result_window, result );








浙公网安备 33010602011771号