日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

matchTemplate函数

發(fā)布時間:2025/4/16 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 matchTemplate函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  • 使用OpenCV函數(shù)?matchTemplate?在模板塊和輸入圖像之間尋找匹配,獲得匹配結(jié)果圖像
  • 使用OpenCV函數(shù)?minMaxLoc?在給定的矩陣中尋找最大和最小值(包括它們的位置).

原理

什么是模板匹配?

模板匹配是一項在一幅圖像中尋找與另一幅模板圖像最匹配(相似)部分的技術(shù).

它是怎么實現(xiàn)的?

  • 我們需要2幅圖像:

  • 原圖像 (I):?在這幅圖像里,我們希望找到一塊和模板匹配的區(qū)域
  • 模板 (T):?將和原圖像比照的圖像塊
  • 我們的目標(biāo)是檢測最匹配的區(qū)域:

  • 為了確定匹配區(qū)域, 我們不得不滑動模板圖像和原圖像進行?比較?:

  • 通過?滑動, 我們的意思是圖像塊一次移動一個像素 (從左往右,從上往下). 在每一個位置, 都進行一次度量計算來表明它是 “好” 或 “壞” 地與那個位置匹配 (或者說塊圖像和原圖像的特定區(qū)域有多么相似).

  • 對于?T?覆蓋在?I?上的每個位置,你把度量值?保存?到?結(jié)果圖像矩陣?(R)?中. 在?R?中的每個位置??都包含匹配度量值:

    上圖就是?TM_CCORR_NORMED?方法處理后的結(jié)果圖像?R?. 最白的位置代表最高的匹配. 正如您所見, 紅色橢圓框住的位置很可能是結(jié)果圖像矩陣中的最大數(shù)值, 所以這個區(qū)域 (以這個點為頂點,長寬和模板圖像一樣大小的矩陣) 被認為是匹配的.

  • 實際上, 我們使用函數(shù)?minMaxLoc?來定位在矩陣?R?中的最大值點 (或者最小值, 根據(jù)函數(shù)輸入的匹配參數(shù)) .

OpenCV中支持哪些匹配算法?

問得好. OpenCV通過函數(shù)?matchTemplate?實現(xiàn)了模板匹配算法. 可用的方法有6個:

  • 平方差匹配 method=CV_TM_SQDIFF
  • 這類方法利用平方差來進行匹配,最好匹配為0.匹配越差,匹配值越大.

  • 標(biāo)準平方差匹配 method=CV_TM_SQDIFF_NORMED

  • 相關(guān)匹配 method=CV_TM_CCORR

  • 這類方法采用模板和圖像間的乘法操作,所以較大的數(shù)表示匹配程度較高,0標(biāo)識最壞的匹配效果.

  • 標(biāo)準相關(guān)匹配 method=CV_TM_CCORR_NORMED

  • 相關(guān)匹配 method=CV_TM_CCOEFF

  • 這類方法將模版對其均值的相對值與圖像對其均值的相關(guān)值進行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示沒有任何相關(guān)性(隨機序列).

    在這里

  • 標(biāo)準相關(guān)匹配 method=CV_TM_CCOEFF_NORMED

  • 通常,隨著從簡單的測量(平方差)到更復(fù)雜的測量(相關(guān)系數(shù)),我們可獲得越來越準確的匹配(同時也意味著越來越大的計算代價). 最好的辦法是對所有這些設(shè)置多做一些測試實驗,以便為自己的應(yīng)用選擇同時兼顧速度和精度的最佳方案.

    代碼

    • 在這程序?qū)崿F(xiàn)了什么?

      • 載入一幅輸入圖像和一幅模板圖像塊 (template)
      • 通過使用函數(shù)?matchTemplate?實現(xiàn)之前所述的6種匹配方法的任一個. 用戶可以通過滑動條選取任何一種方法.
      • 歸一化匹配后的輸出結(jié)果
      • 定位最匹配的區(qū)域
      • 用矩形標(biāo)注最匹配的區(qū)域
    • 下載代碼: 單擊?這里

    • 看一下代碼:

    #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h>using namespace std; using namespace cv;/// 全局變量 Mat img; Mat templ; Mat result; char* image_window = "Source Image"; char* result_window = "Result window";int match_method; int max_Trackbar = 5;/// 函數(shù)聲明 void MatchingMethod( int, void* );/** @主函數(shù) */ int main( int argc, char** argv ) {/// 載入原圖像和模板塊img = imread( argv[1], 1 );templ = imread( argv[2], 1 );/// 創(chuàng)建窗口namedWindow( image_window, CV_WINDOW_AUTOSIZE );namedWindow( result_window, CV_WINDOW_AUTOSIZE );/// 創(chuàng)建滑動條char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );MatchingMethod( 0, 0 );waitKey(0);return 0; }/** * @函數(shù) MatchingMethod * @簡單的滑動條回調(diào)函數(shù) */ void MatchingMethod( int, void* ) {/// 將被顯示的原圖像Mat img_display;img.copyTo( img_display );/// 創(chuàng)建輸出結(jié)果的矩陣int result_cols = img.cols - templ.cols + 1;int result_rows = img.rows - templ.rows + 1;result.create( result_cols, result_rows, CV_32FC1 );/// 進行匹配和標(biāo)準化matchTemplate( img, templ, result, match_method );normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );/// 通過函數(shù) minMaxLoc 定位最匹配的位置double minVal; double maxVal; Point minLoc; Point maxLoc;Point matchLoc;minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );/// 對于方法 SQDIFF 和 SQDIFF_NORMED, 越小的數(shù)值代表更高的匹配結(jié)果. 而對于其他方法, 數(shù)值越大匹配越好if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED ){ matchLoc = minLoc; }else{ matchLoc = maxLoc; }/// 讓我看看您的最終結(jié)果rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );imshow( image_window, img_display );imshow( result_window, result );return; }

    代碼說明

  • 定義一些全局變量, 例如原圖像(img), 模板圖像(templ) 和結(jié)果圖像(result) , 還有匹配方法以及窗口名稱:

    Mat img; Mat templ; Mat result; char* image_window = "Source Image"; char* result_window = "Result window";int match_method; int max_Trackbar = 5;
  • 載入原圖像和匹配塊:

    img = imread( argv[1], 1 ); templ = imread( argv[2], 1 );
  • 創(chuàng)建窗口,顯示原圖像和結(jié)果圖像:

    namedWindow( image_window, CV_WINDOW_AUTOSIZE ); namedWindow( result_window, CV_WINDOW_AUTOSIZE );
  • 創(chuàng)建滑動條并輸入將被使用的匹配方法. 一旦滑動條發(fā)生改變,回調(diào)函數(shù)?MatchingMethod?就會被調(diào)用.

    char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED"; createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
  • 一直等待,直到用戶退出這個程序.

    waitKey(0); return 0;
  • 讓我們先看看回調(diào)函數(shù). 首先, 它對原圖像進行了一份復(fù)制:

    Mat img_display; img.copyTo( img_display );
  • 然后, 它創(chuàng)建了一幅用來存放匹配結(jié)果的輸出圖像矩陣. 仔細看看輸出矩陣的大小(它包含了所有可能的匹配位置)

    int result_cols = img.cols - templ.cols + 1; int result_rows = img.rows - templ.rows + 1;result.create( result_cols, result_rows, CV_32FC1 );
  • 執(zhí)行模板匹配操作:

    matchTemplate( img, templ, result, match_method );

    很自然地,參數(shù)是輸入圖像?I, 模板圖像?T, 結(jié)果圖像?R?還有匹配方法 (通過滑動條給出)

  • 我們對結(jié)果進行歸一化:

    normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
  • 通過使用函數(shù)?minMaxLoc?,我們確定結(jié)果矩陣?R?的最大值和最小值的位置.

    double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc;minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

    函數(shù)中的參數(shù)有:

    • result:?匹配結(jié)果矩陣
    • &minVal?和?&maxVal:?在矩陣?result?中存儲的最小值和最大值
    • &minLoc?和?&maxLoc:?在結(jié)果矩陣中最小值和最大值的坐標(biāo).
    • Mat():?可選的掩模
  • 對于前二種方法 ( CV_SQDIFF 和 CV_SQDIFF_NORMED ) 最低的數(shù)值標(biāo)識最好的匹配. 對于其他的, 越大的數(shù)值代表越好的匹配. 所以, 我們在matchLoc?中存放相符的變量值:

    if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED ){ matchLoc = minLoc; } else{ matchLoc = maxLoc; }
  • 顯示原圖像和結(jié)果圖像. 再用矩形框標(biāo)注最符合的區(qū)域:

    rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 ); rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );imshow( image_window, img_display ); imshow( result_window, result );
  • 結(jié)果

  • 開始測試我們的程序,一幅輸入圖像:

    還有一幅模版圖像:

  • 產(chǎn)生了一下結(jié)果圖像矩陣 (第一行是標(biāo)準的方法 SQDIFF, CCORR 和 CCOEFF, 第二行是相同的方法在進行標(biāo)準化后的圖像). 在第1列, 最黑的部分代表最好的匹配, 對于其它2列, 越白的區(qū)域代表越好的匹配.

  • 正確的匹配在下面顯示 (右側(cè)被矩形標(biāo)注的人臉). 需要注意的是方法 CCORR 和 CCOEFF 給出了錯誤的匹配結(jié)果, 但是它們的歸一化版本給出了正確的結(jié)果, 這或許是由于我們實際上僅僅考慮 “最匹配” 而沒考慮其他可能的高匹配位置.

  • 總結(jié)

    以上是生活随笔為你收集整理的matchTemplate函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。