1. 程式人生 > >OpenCV學習模板匹配

OpenCV學習模板匹配

轉載自 https://blog.csdn.net/Small_Munich/article/details/79437482

模板匹配演算法介紹


模板匹配演算法主要為模板影象在基準圖上進行由左往右、由上到下進行相關運算,最後得到一個進行相關運算後的係數矩陣:係數矩陣中的引數值用來度量模板影象在基準圖中的子區域相似程度。採用相關係數來進行評判,模板匹配演算法主要有基於灰度值的模板匹配、梯度值的模板匹配、相位相關匹配等方法。 

灰度值匹配: 


模板影象未經過任何預處理,直接取其畫素值在原始影象上進行相關運算,灰度匹配演算法優點在於速度快,缺點是對光照、亮度變化敏感,匹配魯棒性不強。 


梯度值匹配: 


針對模板匹配對光照、亮度變化敏感,有學者提出採取先對模板圖和原始圖分別計算其對應的梯度圖。通過梯度圖進行相關運算,匹配準確率得以大幅提高。 
模板匹配主要缺點: 
1 基於灰度匹配演算法不能夠解決匹配景物存在旋轉的情況 
2 模板匹配演算法耗時較大,相對於特徵匹配效率低

模板匹配演算法示例(影象數字化展示)
採取矩陣演示模式,假設基準影象矩陣G為:

模板影象為T(假設為基準圖矩陣G的子區域複製版本):

計算T在G的匹配位置(相關運算):越界部分補零 
[模板T中心點5從矩陣G起點(0,0)由左往右從上往下依次進行運算] 
Gs(0, 0) = 0*1 + 0*2 + 0*3 + 0*4 + 0*5 + 0*6 + 0*7 + 0*8 + 1*9 = 9 
Gs(0, 1) = 0*1 + 0*2 + 0*3 + 0*4 + 0*5 + 0*6 + 0*7 + 1*8 + 2*9 = 26 
…… 


計算所有的相關係數矩陣Gs : 

通過相關係數矩陣Gs可以看出,矩陣中最大引數值為285,最大引數值對應模板匹配的中心位置點(座標)[綠色線框標定匹配結果]。當然,模板匹配演算法改進會新增歸一化步驟,梯度影象或者相點陣圖的匹配。

模板匹配演算法實驗程式碼

#include "stdafx.h"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

/// 全域性變數宣告
bool use_mask;
Mat img; Mat templ; Mat mask; Mat result;
const char* image_window = "Source Image";
const char* result_window = "Result window";

int match_method;
int max_Trackbar = 5;

void MatchingMethod(int, void*);

int main(int argc, char** argv)
{

    argv[1] = "..\\Histograms_Matching\\image\\lena.jpg";
    argv[2] = "..\\Histograms_Matching\\image\\template.jpg";
    // argv[3] = "..\\Histograms_Matching\\image\\template2.jpg";
    /// 載入模板圖與基準圖
    img = imread(argv[1], IMREAD_COLOR);
    templ = imread(argv[2], IMREAD_COLOR);

    if (argc > 3) {
        use_mask = true;
        mask = imread(argv[3], IMREAD_COLOR);
    }

    if (img.empty() || templ.empty() || (use_mask && mask.empty()))
    {
        cout << "Can't read one of the images" << endl;
        return -1;
    }

    /// 顯示視窗建立
    namedWindow(image_window, WINDOW_AUTOSIZE);
    namedWindow(result_window, WINDOW_AUTOSIZE);

    /// 建立軌跡條
    /// SQDIFF: 差值平方和匹配    SQDIFF NORMED: 標準化差值平方和匹配
    /// TM_CORR: 相關匹配         TM_CORR NORMED: 標準(歸一化)相關匹配
    /// TM_COEFF: 相關係數匹配        TM_COEFF NORMED: 標準相關係數匹配
    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, image_window, &match_method, max_Trackbar, MatchingMethod);

    MatchingMethod(0, 0);  /// 匹配引數入口函式

    /// [wait_key]
    waitKey(0);
    system("pause");

    return 0;
}
//// 匹配函式
void MatchingMethod(int, void*)
{
    /// 原始影象拷貝
    Mat img_display;
    img.copyTo(img_display);

    /// 建立匹配輸出影象結果矩陣
    int result_cols = img.cols - templ.cols + 1;
    int result_rows = img.rows - templ.rows + 1;

    result.create(result_rows, result_cols, CV_32FC1);

    /// 模板匹配
    bool method_accepts_mask = (CV_TM_SQDIFF == match_method || match_method == CV_TM_CCORR_NORMED);
    if (use_mask && method_accepts_mask)
    {
        matchTemplate(img, templ, result, match_method, mask);
    }
    else
    {
        matchTemplate(img, templ, result, match_method);
    }

    //! 歸一化
    normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());

    /// 通過minMaxLoc來定位最佳匹配位置
    double minVal; double maxVal; Point minLoc; Point maxLoc;
    Point matchLoc;
    /// 尋找影象矩陣中最大最小畫素點
    minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());

    /// 對於SQDIFF與SQDIFF_NORMED方式, 最佳匹配在最小點. 相反其它模式,最佳匹配在最大點位置
    if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED)
    {
        matchLoc = minLoc;
    }
    else
    {
        matchLoc = maxLoc;
    }

    /// 繪製匹配區
    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;
}

匹配實驗結果:

總結


模板匹配演算法經過多年發展已近趨於成熟,基於影象灰度資訊的模板匹配演算法最先被提出與使用,通過計算模板影象與基準影象滑動的子區域的相關係數進行判決匹配位置。隨後由於基於灰度的匹配方法魯棒性較差:光照、亮度等影響;因此出現基於梯度影象的模板匹配演算法,梯度圖抗光照、噪聲、亮度等較好。模板匹配進行相關運算時耗時較高,由於卷積與相關實際運算中較為接近(可以近似理解卷積運算就是相關運算過程中核函式(模板影象)旋轉180°),可以通過FFT進行加速運算;由於模板匹配對於景象有旋轉變化時失效,後期逐漸發展為區域性特徵模式下的匹配演算法,如SIFT、SURF等代表的演算法火熱了前二十年。隨著12年Alexnet網路分類效能在ImageNet上脫穎而出,經典的手工設計方式告一段落,基於深度學習模式下的影象識別已經成為當下最流行的技術。但是,經典手工設計核函式思想在卷積神經網路設計中啟發:Ps 低層次語義特徵到高層次的語義特徵是否類似於尺度空間的思想,不同大小的卷積核函式代表著不同的感受野等等。

程式碼下載

環境:windows10 x64 + vs2015 + opencv3.3.1

百度網盤連結:https://pan.baidu.com/s/1c3CFoIk 密碼:xnce