1.26【OpenCV圖像處理】模板匹配

模板匹配matchTemplate()、6種匹配演算法、找最大最小位置minMaxLoc()、繪製矩陣rectangle() Rect()

1.26.1 模板匹配(Template Match)介紹

模板匹配:是一項在一幅圖像中尋找與另一幅模板圖像最匹配(相似)部分的技術。就是在整個圖像區域發現與給定子圖像匹配的那小塊區域。

模板匹配需要一個給定的子圖像-模板圖像 T 和一個待檢測的圖像-源圖像 I 。

工作方法:在待檢測圖像上,模板圖像從左到右,從上向下逐個像素滑動,計算模板圖像與重疊子圖像的匹配度,匹配程度越大,兩者相同的可能性越大。

對於 T 覆蓋在 I 上的每個位置,把度量值保存到結果圖像矩陣 (R) 中,在 R 中的每個位置 (x,y) 都包含匹配度量值。R 圖像中最黑(0 1)或最白(2 3 4 5)(匹配方法不同)的位置代表最高的匹配,紅色框住的位置很可能是結果圖像矩陣中的最大數值,所以這個區域 (以這個點為頂點,長寬和模板圖像一樣大小的矩陣) 被認為是匹配的。

1.26.2 模板匹配演算法

OpenCV通過函數matchTemplate()實現了6種模板匹配演算法:

(1)平方差匹配 method=CV_TM_SQDIFF

最佳匹配為最小值 0,匹配值越大匹配越差。

(2)標準平方差匹配 method=CV_TM_SQDIFF_NORMED

0~1,值越小越匹配, 計算歸一化平方不同。

(3)相關匹配 method=CV_TM_CCORR

這類方法採用模板和圖像間的乘法操作,計算相關性。

最佳匹配為最大值,最壞匹配效果為最小值 0。

(4)標準相關匹配 method=CV_TM_CCORR_NORMED

0~1,值越大越匹配。

(5)相關係數匹配 method=CV_TM_CCOEFF

這類方法將模版對其均值的相對值與圖像對其均值的相關值進行匹配。

最佳匹配為最大值 1,-1表示糟糕匹配,0表示沒有任何相關性(隨機序列),越大越相關。

(6)標準相關係數匹配 method=CV_TM_CCOEFF_NORMED

0~1, 越大越相關。

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

1.26.3 相關API介紹

matchTemplate(

InputArray image, // 源圖像,必須是8-bit或者32-bit浮點數圖像

InputArray templ, // 模板圖像,類型與輸入圖像一致

OutputArray result, // 把度量值保存到匹配結果圖像矩陣,必須是單通道32位浮點數,假設源圖像大小WxH,模板圖像wxh,則結果必須為W-w+1, H-h+1的大小。

int method,//使用上面的6種匹配方法。(推薦使用歸一化的,0-1間度量容易給定閾值)

InputArray mask=noArray() //optional可選的掩模

)

matchTemplate(src, temp, result, match_method, Mat()); //模板匹配:8位或32位原圖像,模板,匹配結果圖,匹配方法,卷積核n

6種匹配方法:

實現步驟:

1)創建跟蹤條控制6種匹配方法 - createTrackbar()

/*創建跟蹤條控制6種匹配方法*/nint match_method = CV_TM_CCOEFF; //匹配方法,默認4相關係數匹配nconst char* trackbar_title = "Match Algo Type";ncreateTrackbar(trackbar_title, output_title, &match_method, 5, Match_Demo); //跟蹤條控制6種匹配方法n

2)模板匹配並歸一化,把度量值保存到匹配結果圖像矩陣result中 - matchTemplate()

/*模板匹配並歸一化,把度量值保存到匹配結果圖像矩陣result中*/nint width = src.cols - temp.cols + 1;nint height = src.rows - temp.rows + 1;nMat result(width, height, CV_32FC1); //定義匹配圖大小W-w+1、H-h+1,32位一通道nmatchTemplate(src, temp, result, match_method, Mat()); //模板匹配:8位或32位原圖像,模板,匹配結果圖,匹配方法,卷積核nnormalize(result, result, 0, 1, NORM_MINMAX, -1, Mat()); //歸一化到0-1範圍n

3)找匹配結果圖中最大最小匹配度量值的位置 - minMaxLoc()

/*找匹配結果圖中最大最小匹配度量值的位置*/nPoint minLoc; //最小度量值位置nPoint maxLoc; //最大值位置ndouble min, max; //最小值、最大值nPoint temLoc; //最佳匹配位置nsrc.copyTo(dst);nminMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat()); //找匹配結果圖的最大最小值位置:圖,最小值指針,最大值指針,最小值位置指針,最打值位置指針,卷積核 nif (match_method == CV_TM_CCOEFF || match_method == CV_TM_SQDIFF_NORMED) {n temLoc = minLoc; //匹配方法為平方差和標準平方差時,匹配位置取最小值位置n}nelse {n temLoc = maxLoc; //其他方法取最大值位置n}n

4)繪製最佳匹配矩陣 - rectangle()、Rect()

/*繪製最佳匹配矩陣*/nrectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8); //繪製矩形,Rect(左上角坐標,寬,高)2d矩形的模板類nrectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);n


完整程序:

/*1.26 模板匹配Template Match*/n#include <opencv2/opencv.hpp>n#include <iostream> n#include <math.h>nusing namespace cv;nusing namespace std;nnMat src, temp, dst;nint match_method = CV_TM_CCOEFF; //匹配方法,默認0 平方差匹配nconst char output_title[] = "Template Match Result";nvoid Match_Demo(int, void*);nnint main(int argc, char** argv) {n src = imread("E:/OpenCV/testimage/test9.jpg"); //待檢測圖n temp = imread("E:/OpenCV/testimage/temp.jpg"); //模板圖nif (src.empty()) {n printf("could not load image...n");nreturn -1;n }nchar input_title[] = "input image";n namedWindow(input_title, CV_WINDOW_AUTOSIZE);n imshow(input_title, src);n imshow("temp image", temp);n namedWindow(output_title, CV_WINDOW_AUTOSIZE);nn /*跟蹤條控制6種匹配方法*/nconst char* trackbar_title = "Match Algo Type";n createTrackbar(trackbar_title, output_title, &match_method, 5, Match_Demo); //跟蹤條控制6種匹配方法n Match_Demo(0, 0);nn waitKey(0);nreturn 0;n}nnvoid Match_Demo(int, void*) {n/*模板匹配並歸一化,把度量值保存到匹配結果圖像矩陣result中*/nint width = src.cols - temp.cols + 1;nint height = src.rows - temp.rows + 1;nMat result(width, height, CV_32FC1); //定義匹配圖大小W-w+1、H-h+1,32位一通道nmatchTemplate(src, temp, result, match_method, Mat()); //模板匹配:8位或32位原圖像,模板,匹配結果圖,匹配方法,卷積核n normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat()); //歸一化到0-1範圍nn /*找匹配結果圖中最大最小匹配度量值的位置*/nPoint minLoc; //最小度量值位置nPoint maxLoc; //最大值位置ndouble min, max; //最小值、最大值nPoint temLoc; //最佳匹配位置n src.copyTo(dst);nminMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat()); //找匹配結果圖的最大最小值位置:圖,最小值指針,最大值指針,最小值位置指針,最打值位置指針,卷積核 nif (match_method == CV_TM_CCOEFF || match_method == CV_TM_SQDIFF_NORMED) {n temLoc = minLoc; //匹配方法為平方差和標準平方差時,匹配位置取最小值位置n }nelse {n temLoc = maxLoc; //其他方法取最大值位置n }nn /*繪製最佳匹配矩陣*/n rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8); //繪製矩形,Rect(左上角坐標,寬,高)2d矩形的模板類n rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);nn imshow(output_title, result);n imshow("最佳匹配矩陣", dst);n}n

運行結果:

第0、1方法, 最黑的部分代表最好的匹配;對於其它方法, 越白的區域代表越好的匹配。需要注意的是方法SQDIFF、CCORR 和 CCOEFF 給出了錯誤的匹配結果, 但是它們的歸一化版本給出了正確的結果, 這或許是由於我們實際上僅僅考慮 「最匹配」 而沒考慮其他可能的高匹配位置的原因。要根據不同的圖像情況不同分析。


推薦閱讀:

1.25【OpenCV圖像處理】直方圖反向投影
OpenCV檢測篇(一)——貓臉檢測
【小林的OpenCV基礎課 3】視頻淺淺談

TAG:OpenCV | 图像处理 | 计算机视觉 |