示例程序040--模板匹配

模板匹配的概念:

    在源图片中寻找与模板图片最匹配部分的技术。

 

模板匹配如何实现:

需要2幅图像:

  1. 原图像 (I): 在这幅图像里,我们希望找到一块和模板匹配的区域
  2. 模板 (T): 将和原图像比照的图像块

    目标是检测最匹配的区域:

             ../../../../../_images/Template_Matching_Template_Theory_Summary.jpg

    为了确定匹配区域, 要滑动模板图像和原图像进行 比较 :

                    ../../../../../_images/Template_Matching_Template_Theory_Sliding.jpg

 

 滑动的意思是图像块一次移动一个像素 (从左往右,从上往下). 在每一个位置, 都进行一次度量计算来表明它是 “好” 或 “坏” 地与那个位置匹配 (或者说块图像和原图像的特定区域有多么相似).

 

对于 T 覆盖在 I 上的每个位置,你把度量值 保存 到 结果图像矩阵 (R) 中. 在 R 中的每个位置 (x,y) 都包含匹配度量值:

                            ../../../../../_images/Template_Matching_Template_Theory_Result.jpg

 

上图就是 TM_CCORR_NORMED 方法处理后的结果图像 R . 最白的位置代表最高的匹配. 正如您所见, 红色椭圆框住的位置很可能是结果图像矩阵中的最大数值, 所以这个区域 (以这个点为顶点,长宽和模板图像一样大小的矩阵) 被认为是匹配的.

我们使用函数 minMaxLoc 来定位在矩阵 R 中的最大值点 (或者最小值, 根据函数输入的匹配参数) .

 

用到的函数:

matchTemplate 提供了6中模板匹配算法

 CV_TM_SQDIFF  平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
 CV_TM_SQDIFF_NORMED 标准平方差匹配

 

3  CV_TM_CCORR        相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
4  CV_TM_CCORR_NORMED 归一化相关匹配法


 CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。

 CV_TM_CCOEFF_NORMED 归一化相关系数匹配法
    通常,随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价). 最好的办法是对所有这些设置多做一些测试实验,以便为自己的应用选择同时兼顾速度和精度的最佳方案.

    后三种的匹配效果比较完美,计算时间也越多。

 

代码及注释:

// 048 模板匹配 2.3版.cpp : 定义控制台应用程序的入口点。
//

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

 

using namespace std;
using namespace cv;

 

/// 全局变量
Mat img; Mat templ; Mat result;
char* image_window = "Source Image";
char* result_window = "Result window";

 

int match_method;
int max_Trackbar = 5;   //6种不同的匹配算法

 

/// 函数声明
void MatchingMethod( int, void* );

 

int main( int argc, char** argv )
{
 
  img=imread("tempMatch_src.bmp");
  templ=imread("tempmatch_temp.bmp");

 

   namedWindow( image_window, CV_WINDOW_AUTOSIZE );
  namedWindow( result_window, CV_WINDOW_AUTOSIZE );

 

  /// 创建滑动条
  char* trackbar_label = "Method:";
  createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );

 

  MatchingMethod( 0, 0 );

 

  waitKey(0);
  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_cols, result_rows, CV_32FC1 );

 

  /// 进行匹配,匹配结果存入result矩阵
  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  == CV_TM_SQDIFF || match_method == CV_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;
}

 

 运行结果:

示例程序040--模板匹配 示例程序040--模板匹配 示例程序040--模板匹配

示例程序040--模板匹配 示例程序040--模板匹配 示例程序040--模板匹配

 

可以看到效果并不好,可能是图像前期没有做处理,比如二值等

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值