imgproc模塊--模板匹配

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章