【小白】Open-CV 学习笔记 - 9.5 模板匹配

模板匹配(TemplateMatching)就是在一幅图像中寻找和模板图像(template)最相似的区域,该方法原理简单计算速度快,能够应用于目标识别,目标跟踪等多个领域。OpenCV中对应的函数为matchTemplate或cvMatchTemplate(参考opencvdoc),简单介绍下:

1、函数原型

C++: void matchTemplate(InputArray image, InputArray templ, OutputArray result, int method);
C: void cvMatchTemplate(const CvArr* image, const CvArr* templ, CvArr* result, int method);

2、参数解释

  • image:输入图像。必须为8位或者32位的浮点型。

  • templ:用于搜索的模板图像。必须小于输入图像并且是一样的数据类型。

  • result:匹配结果图像。必须是单通道32位浮点型,且大小是(W-w+1)*(H-h+1),其中W,H分别为输入图像的宽和高,w,h分别为模板图像的宽和高。

  • method:相似度衡量的方法。具体如下(这里T是templ,I是image,R是result,x’是从0到w-1,y’是从0到h-1):

在这里插入图片描述
在这里插入图片描述
最后需要注意:

(1)前面两种方法为越小的值表示越匹配,后四种方法值越大越匹配。原因在于我们把第一种方法CV_TM_SQDIFF的计算公式展开可以得到:
在这里插入图片描述

上式的第一项(模板图像T的能量)是一个常数,第三项(图像I局部的能量)也可以近似一个常数,剩下的第二项与第三种方法CV_TM_CCORR的计算公式一样。而我们知道互相关系数(Cross Correlation)越大相似度越大,所以第一、二种方法的数值越小相似度越高,而第三、四种方法的数值越大相似度越高,第五、六种方法的计算公式与第三、四种方法的类似,所以也是数值越大相似度越高。

如果输入图像和模板图像都是彩色图像,则三个通道分别计算上述相似度,然后求平均值。

3、功能描述

函数通过在输入图像image中滑动(从左到右,从上到下),寻找各个位置的区块(搜索窗口)与模板图像templ的相似度,并将结果保存在结果图像result中。该图像中的每一个点的亮度表示该处的输入图像与模板图像的匹配程度,然后可以通过某方法(一般使用函数minMaxLoc)定位result中的最大值或者最小值得到最佳匹配点,最后根据匹配点和模板图像的矩形框标出匹配区域(如下图,红圈标出的亮点是最佳匹配点,黑框是模板图像矩形框)。
在这里插入图片描述

代码示例

/**
 * Object matching using function matchTemplate
 */
 
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
 
/// 全局变量 ///
Mat srcImg;			//原始图像
Mat templImg;		//模板图像
Mat resultImg;		//匹配结果图像
 
const char* imageWindow = "Source Image";		//原始图像显示窗口
const char* resultWindow = "Result Window";		//匹配结果图像显示窗口
 
int matchMethod;		//匹配方法index
int maxTrackbar = 5;	//滑动条范围(与匹配方法个数对应)
 
/// 函数声明 ///
void MatchingMethod( int, void* );		//匹配函数
 
int main( int argc, char** argv )
{
  // 加载原始图像和模板图像
  srcImg = imread( "D:\\opencv_pic\\cat0.jpg", 1 );
  templImg = imread( "D:\\opencv_pic\\cat3d120.jpg", 1 );
 
  // 创建显示窗口
  namedWindow( imageWindow, CV_WINDOW_AUTOSIZE );
  namedWindow( resultWindow, CV_WINDOW_AUTOSIZE );
  
  // 创建滑动条
  char* trackbarLabel = 
	  "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";
  //参数:滑动条名称 显示窗口名称 匹配方法index 滑动条范围 回调函数
  createTrackbar( trackbarLabel, imageWindow, &matchMethod, maxTrackbar, MatchingMethod );
 
  MatchingMethod( 0, 0 );
 
  waitKey(0);
  return 0;
}
 
/// 函数定义 ///
void MatchingMethod( int, void* )		//匹配函数
{
  // 深拷贝用于显示
  Mat displayImg;
  srcImg.copyTo( displayImg );
 
  // 创建匹配结果图像,为每个模板位置存储匹配结果
  // 匹配结果图像大小为:(W-w+1)*(H-h+1)
  int result_cols =  srcImg.cols - templImg.cols + 1;
  int result_rows = srcImg.rows - templImg.rows + 1;
  resultImg.create( result_cols, result_rows, CV_32FC1 );
 
  // 进行匹配并归一化
  matchTemplate( srcImg, templImg, resultImg, matchMethod );
  normalize( resultImg, resultImg, 0, 1, NORM_MINMAX, -1, Mat() );
 
  // 使用minMaxLoc找出最佳匹配
  double minVal, maxVal;
  Point minLoc, maxLoc, matchLoc;
  minMaxLoc( resultImg, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
 
  // 对于CV_TM_SQDIFF和 CV_TM_SQDIFF_NORMED这两种方法,最小值为最佳匹配;对于别的方法最大值为最佳匹配
  if( matchMethod  == CV_TM_SQDIFF || matchMethod == CV_TM_SQDIFF_NORMED )
    { matchLoc = minLoc; }
  else  
    { matchLoc = maxLoc; }
 
  // 在原始图像和匹配结果图像中以最佳匹配点为左上角标出最佳匹配框
  rectangle( displayImg, matchLoc, Point( matchLoc.x + templImg.cols , matchLoc.y + templImg.rows ), Scalar::all(0), 2, 8, 0 ); 
  rectangle( resultImg, matchLoc, Point( matchLoc.x + templImg.cols , matchLoc.y + templImg.rows ), Scalar::all(0), 2, 8, 0 ); 
 
  imshow( imageWindow, displayImg );
  imshow( resultWindow, resultImg );
 
  return;
}

在这里插入图片描述
在这里插入图片描述


作者:holybin
来源:CSDN
原文:https://blog.csdn.net/holybin/article/details/40541933
版权声明:本文为博主原创文章,转载请附上博文链接!

发布了34 篇原创文章 · 获赞 8 · 访问量 1869

猜你喜欢

转载自blog.csdn.net/weixin_43583163/article/details/97822580