1.目的
(1)使用openCV函數matchTemplate()在輸入圖像中搜索圖像塊
(2)使用openCV函數minMaxLoc()尋找數組中的最大或者最小值
2.原理
[1]模板匹配
給定一個圖像塊,搜索配對的圖像塊,當模板是矩形時候,並不一定所有的矩形塊內容都是相關的,在這種情況下,可以利用掩碼分離有用信息。
[2]工作原理
輸入:原圖像,模板
目標:尋找最高的匹配塊
搜索:比較模板和原圖像,通過滑動形式配對模板。
搜索過程是從左到右,從上到下,逐個像素像素遍歷的過程,通過計算每一次滑動過程的配對效果的好壞確定最佳匹配模塊,並將度量結果存儲在結果矩陣R中。矩陣R中的每一個位置(x,y)包含了配對度量。
如上圖所示,紅色圓圈中的亮點區域表示匹配高的區域,黑色的矩形框框表示匹配區域,實際過程中,我們通過minMaxLoc函數在結果矩陣R中尋找最佳匹配。
PS:如果使用掩碼,則需要輸入原圖像,模板,掩碼。掩碼的維度必須和模板一致,並且擁有CV_8U和CV_32F的深度以及和模板具有相同通道數。CV_8U的掩碼必須是二進制值,CV_32F則是在[0,1]之間的小數,掩碼和模板對應相乘,獲得經過掩碼操作的模板。現在只有CV_TM_SQDIFF和CV_TM_CCORR_NORMED支持掩碼操作。
[3]配對方法
<1>method=CV_TM_SQDIFF:平方差匹配法
<2>method=CV_TM_SQDIFF_NORMED:歸一化平方差匹配法
<3>method=CV_TM_CCORR:相關匹配法
<4>method=CV_TM_CCORR_NORMED:歸一化相關匹配法
<5>method=CV_TM_CCOEFF:相關係數匹配法
<6>method=CV_TM_CCOEFF_NORMED:歸一化相關係數匹配法
3.部分代碼解釋
(1)minMaxLoc
/*
minMaxLoc參數解釋
result:輸入數組
minVal:數組最小值
maxVal:數組最大值
minLoc:數組最小值所在位置
maxLoc:數組最大值所在位置
Mat():掩碼,沒定義則爲無掩碼操作
*/
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
(2)matchTemplate
matchTemplate參數解釋
img:輸入圖像
templ:模板
result:匹配結果,存儲匹配過程中的度量值metric value
type:匹配方法
*/
matchTemplate(img, templ, result, type);
4.完整代碼
(1)CommonInclude.h
#ifndef COMMON_INCLUDE
#define COMMON_INCLUDE
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
#endif
(2)Matching.cpp
#include"CommonInclude.h"
/*
配對方法0,1,2,3,4,5
*/
int type = 0;
int num_type = 5;
Mat img, templ, mask, result;
char windowResultName[] = "Matched";
char windowOriginName[] = "Origin";
void Matching(int, void*){
Mat display_img = img.clone();
/*
matchTemplate參數解釋
img:輸入圖像
templ:模板
result:匹配結果,存儲匹配過程中的度量值metric value
type:匹配方法
*/
matchTemplate(img, templ, result, type);
//歸一化
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
double minVal, maxVal;
Point minLoc, maxLoc;
Point matchLoc;
//使用minMaxLoc函數確定數組的最值以及位置
/*
minMaxLoc參數解釋
result:輸入數組
minVal:數組最小值
maxVal:數組最大值
minLoc:數組最小值所在位置
maxLoc:數組最大值所在位置
Mat():掩碼,沒定義則爲無掩碼操作
*/
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if( type == CV_TM_SQDIFF || type == CV_TM_SQDIFF_NORMED )
{
matchLoc = minLoc;
}else{
matchLoc = maxLoc;
}
//繪製匹配的區域
rectangle(display_img, matchLoc, Point(matchLoc.x+templ.cols, matchLoc.y+templ.rows), Scalar(0,0,0), 2, 8);
rectangle(result, matchLoc, Point(matchLoc.x+templ.cols, matchLoc.y+templ.rows), Scalar(0,0,0), 2, 8);
imshow(windowOriginName, img);
imshow(windowResultName,display_img);
imshow("result", result);
}
int main(int argc, char**argv){
if(argc<3){
cout << "more parameters are required!!!" << endl;
return(-1);
}
img = imread(argv[1]);
templ = imread(argv[2]);
//mask = imread(argv[3]);
if(!img.data || !templ.data){
cout << "error to read images!!!" << endl;
return(-1);
}
namedWindow(windowResultName, CV_WINDOW_AUTOSIZE);
const 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, windowResultName,&type, num_type, Matching);
Matching(0,0);
waitKey(0);
return(0);
}
參考文獻
1.http://docs.opencv.org/master/de/da9/tutorial_template_matching.html