最近在給老師做一個圖像拼接的東西,然后就用到了Opencv中的matchTemplate函數,在網上也有很多大神寫了相關的博客:
已經有很多了關於這個函數的解釋,我就主要從一些不好理解的地方解釋一下吧,可能也不一定對_,同樣也是為了給自己做一個回顧。
不想看的直接上參考文檔.
函數原型:
void cv::matchTemplate(
cv::InputArray image, // 用於搜索的輸入圖像, 8U 或 32F, 大小 W*H
cv::InputArray templ, // 用於匹配的模板,和image類型相同, 大小 w*h
cv::OutputArray result, // 匹配結果圖像, 類型 32F, 大小 (W-w+1)*(H-h+1)
int method // 用於比較的方法
);
函數參數解釋:
templ:是小圖,在image中進行步長為1的滑動,每一次都移動一個格子。
image:匹配圖(大圖,其中存在templ區域)。
如下圖所示:紅色部分為templ,背景棕黃色為image,templ從(0,0)處開始滑動。
method:
有以下六種:
enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
1. TM_SQDIFF,TM_SQDIFF_NORMED匹配數值越低表示匹配效果越好,其它四種反之。
2. TM_SQDIFF_NORMED,TM_CCORR_NORMED,TM_CCOEFF_NORMED是標准化的匹配,得到的最大值,最小值范圍在0~1之間,其它則需要自己對結果矩陣歸一化。
result:存放每一次templ和image進行比對得到相似度。
如上圖可知,模板在待測圖像上每次在橫向或是縱向上移動一個像素,並作一次比較計算,由此,橫向比較W-w+1次,縱向比較H-h+1次,從而得到一個(W-w+1)×(H-h+1)維的結果矩陣,result即是用圖像來表示這樣的矩陣,因而圖像result的大小為(W-w+1)×(H-h+1)。匹配結果圖像與原圖像之間的大小關系,他們之間差了一個模板大小。
從result中獲得最佳匹配區域
使用函數cvMinMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc,NULL);從result中提取最大值(相似度最高)以及最大值的位置(即在result中該最大值max_val的坐標位置max_loc,即模板滑行時左上角的坐標,類似於圖中的坐標(x,y)。
在這里有min_val,max_val。為什么會有兩個值呢?
我的理解是由於我們的對比方法method的不同,對於匹配結果:有的方法是匹配數值越小匹配效果越好;有的方法則是匹配數值越大匹配效果越好。因此返回的是兩種不同的結果。
這個函數中引用修改的無論是 min_loc 還是 max_loc返回的都是在當前選取的方法method上得到的最佳匹配的,image上templ最佳位置的左上角的點。由此可以得到最佳匹配區域:
rect=cvRect(max_loc.x,max_loc.y,tmp->width,tmp->height); //rect表示最佳的匹配的矩形區域。
具體的使用函數如下:
Point templateMatching(const Mat& srcImage,const Mat& templateImage)
{
Mat result;
int result_cols = srcImage.cols - templateImage.cols + 1;
int result_rows = srcImage.rows - templateImage.rows + 1;
if(result_cols < 0 || result_rows < 0)
{
qDebug() << "Please input correct image!";
return;
}
result.create(result_cols, result_rows, CV_32FC1);
//enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
matchTemplate(srcImage,templateImage,result,TM_CCOEFF_NORMED); //最好匹配為1,值越小匹配越差
double minVal = -1;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
//取大值(視匹配方法而定)
// matchLoc = minLoc;
matchLoc = maxLoc;
return matchLoc;
}
that's all thank you!