opencv筆記(二十二)——模板匹配 template matching


模板匹配就是在給定一幅圖像和一幅模板(一般模板比圖像的尺寸小很多)的情況下,找到這個圖像中最最相似於模板的位置,比如

../../../../../_images/Template_Matching_Template_Theory_Summary.jpg

第一幅是給定的圖片,第二幅是模板,第三幅就是搜索到的匹配的位置。

這個搜索的過程,我沒有在源碼中求索,但是根據tutorial,應該是采用sliding window的方法,利用滑動的窗口,逐像素進行匹配。這個逐像素的意思,就是錨定某個像素之后,在這個像素的右邊和下方,以template的寬度和高度的距離的范圍內,進行模板與圖像的相似度計算。

../../../../../_images/Template_Matching_Template_Theory_Sliding.jpg

這種方法和行人檢測中常用的方法類似。就是sliding window。

 

計算匹配度,即計算相似度的方法一般有以下六種:

  1. method=CV_TM_SQDIFF

    R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2

  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}}

  3. method=CV_TM_CCORR

    R(x,y)= \sum _{x',y'} (T(x',y')  \cdot I(x+x',y+y'))

  4. 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}}

  5. 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}

  6. 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 );

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM