文章目录


算法详情见:

​模板匹配​​ 官方给出了好的示例。

  1. 平方差匹配 method=CV_TM_SQDIFF
    这类方法利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大.
    OpenCV + CPP 系列(廿五)模板匹配(Template Match)_类方法
  2. 标准平方差匹配 method=CV_TM_SQDIFF_NORMED
    OpenCV + CPP 系列(廿五)模板匹配(Template Match)_c++_02
  3. 相关匹配 method=CV_TM_CCORR
    这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高, 0标识最坏的匹配效果.
    OpenCV + CPP 系列(廿五)模板匹配(Template Match)_类方法_03
  4. 标准相关匹配 method=CV_TM_CCORR_NORMED
    OpenCV + CPP 系列(廿五)模板匹配(Template Match)_类方法_04
  5. 相关匹配 method=CV_TM_CCOEFF
    这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列).
    OpenCV + CPP 系列(廿五)模板匹配(Template Match)_#include_05
    其中
    OpenCV + CPP 系列(廿五)模板匹配(Template Match)_相关匹配_06
  6. 标准相关匹配 method=CV_TM_CCOEFF_NORMED
    OpenCV + CPP 系列(廿五)模板匹配(Template Match)_#include_07

函数签名:


InputArray image,     源图像,必须是8-bit或者32-bit浮点数图像

InputArray templ,     模板图像,类型与输入图像一致


OutputArray result,     输出结果,必须是单通道32位浮点数,假设源图像WxH,模板图像wxh, 则结果必须为W-w+1, H-h+1的大小。


int method,        匹配方法


InputArray mask = noArray()  掩码


);


头文件 quick_opencv.h:声明类与公共函数

#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;

class QuickDemo {
public:
...
void template_match_Demo(Mat& image1, Mat& image2);

};

主函数调用该类的公共成员函数

#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;


int main(int argc, char** argv) {
Mat src1 = imread("D:\\Desktop\\pandas_small22.png");
Mat src2 = imread("D:\\Desktop\\pandas_small22_test1.png");

if (src1.empty()) {
printf("Could not load images src1...\n");
return -1;
}
if (src2.empty()) {
printf("Could not load images src2...\n");
return -1;
}

QuickDemo qk;
qk.template_match_Demo(src1, src2);
waitKey(0);
destroyAllWindows();
return 0;
}

源文件 quick_demo.cpp:实现类与公共函数

效果演示

#include <quick_opencv.h>
#include <opencv2/dnn.hpp>
#include <iostream>

using namespace cv;
using namespace std;

class templ_match {
public:
Mat image_src;
Mat image_tem;
const char* OUTPUT_t;
const char* MATCH_t;
};

static void on_match(int method_index, void* templ_match_) {
Mat img_display;
templ_match match_info = *((templ_match*)templ_match_);
Mat src = match_info.image_src;
Mat templ = match_info.image_tem;
src.copyTo(img_display);

int result_rows = src.rows - templ.rows + 1;
int result_cols = src.cols - templ.cols + 1;
Mat result = Mat::zeros(src.cols, src.rows, CV_32FC1);

matchTemplate(src, templ, result, method_index, Mat());
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());

double minValue, maxValue;
Point minLoc, maxLoc;
Point matcLoc;

minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc, Mat());
if ((method_index == TM_SQDIFF) || (method_index == TM_SQDIFF_NORMED)) {
matcLoc = minLoc;
}else{
matcLoc = maxLoc;
}
rectangle(img_display, matcLoc, Point(matcLoc.x + templ.cols, matcLoc.y + templ.rows), Scalar::all(0), 2, LINE_AA);
rectangle(result, matcLoc, Point(matcLoc.x + templ.cols, matcLoc.y + templ.rows), Scalar::all(0), 2, LINE_AA);

imshow(match_info.OUTPUT_t, result);
imshow(match_info.MATCH_t, img_display);
}

void QuickDemo::template_match_Demo(Mat& image, Mat& test1) {
const char* OUTPUT_WIN = "result image";
const char* MATCH_WIN = "match demo";
namedWindow(OUTPUT_WIN, WINDOW_AUTOSIZE);
namedWindow(MATCH_WIN, WINDOW_AUTOSIZE);

templ_match match_info;
match_info.OUTPUT_t = OUTPUT_WIN;
match_info.MATCH_t = MATCH_WIN;
match_info.image_src = image;
match_info.image_tem = test1;

int current_Method = 0;
createTrackbar("Algo_type", MATCH_WIN, &current_Method, 5, on_match, &match_info);
on_match(current_Method, &match_info);
}

OpenCV + CPP 系列(廿五)模板匹配(Template Match)_c++_08