服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

​详细剖析模板匹配

日期: 来源:新机器视觉收集编辑:

点击下方卡片,关注“新机器视觉”公众号

重磅干货,第一时间送达

模板匹配介绍


我们需要2幅图像:

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

模板 (T): 将和原图像比照的图像块


  • 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。

  • 所以模板匹配首先需要一个模板图像T(给定的子图像)

  • 另外需要一个待检测的图像-源图像S

  • 工作方法,在带检测图像上,从左到右,从上向下计算模板图像与重叠子图像的匹配度,匹配程度越大,两者相同的可能性越大。

模板匹配原理


我们的目标是检测最匹配模板的原图像的区域:


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


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


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


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

void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
  • src:输入图像。

  • minVal:在矩阵 src中存储的最小值,可输入NULL表示不需要。

  • maxVal :在矩阵 src中存储的最大值,可输入NULL表示不需要。

  • minLoc:在结果矩阵中最小值的坐标,可输入NULL表示不需要,Point类型。

  • maxLoc:在结果矩阵中最大值的坐标,可输入NULL表示不需要,Point类型。

  • mask:可选的掩模


模板匹配介绍 – 匹配算法介绍:

OpenCV中提供了六种常见的匹配算法如下:

  • 计算平方不同 :计算出来的值越小,越相关 TM_SQDIFF = 0

  • 计算相关性:计算出来的值越大,越相关 TM_CCORR = 2

  • 计算相关系数:计算出来的值越大,越相关 TM_CCOEFF = 4

  • 计算归一化平方不同 :计算出来的值越接近0,越相关 TM_SQDIFF_NORMED = 1

  • 计算归一化相关性:计算出来的值越接近1,越相关 TM_CCORR_NORMED = 3

  • 计算归一化相关系数:计算出来的值越接近1,越相关 TM_CCOEFF_NORMED = 5

总结如下:


相关API介绍cv::matchTemplate

matchTemplate(
InputArray image,// 源图像,必须是8-bit或者32-bit浮点数图像
InputArray templ,// 模板图像,类型与输入图像一致
OutputArray result,// 输出结果,必须是单通道32位浮点数,假设源图像WxH,模板图像wxh, 则结果必须为W-w+1, H-h+1的大小。
int method,//使用的匹配方法
InputArray mask=noArray()//(optional)
)



程序代码

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

// 定义一些全局变量, 例如原图像(img), 模板图像(templ) 和结果图像(result) , 
// 还有匹配方法以及窗口名称:
Mat img, templ, result;
char* image_window = "Source Image";
char* result_window = "Result window";

int match_method = TM_SQDIFF;
int max_Trackbar = 5;

void MatchingMethod( int, void* );

int main( int argc, char** argv )
{
 // 1. 载入原图像和模板块
 img = imread("E:/Experiment/OpenCV/Pictures/TargetSearch.jpg");
 templ = imread("E:/Experiment/OpenCV/Pictures/Target.jpg");
 imshow("模板图像",templ);

 // 创建窗口
 namedWindow( image_window, CV_WINDOW_AUTOSIZE );
 namedWindow( result_window, CV_WINDOW_AUTOSIZE );

 // 2. 创建滑动条并输入将被使用的匹配方法. 一旦滑动条发生改变,回调函数 MatchingMethod 就会被调用.
 char* trackbar_label = "模板匹配方式";
 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 );

 // 执行模板匹配操作,并对结果进行归一化:
 matchTemplate( img, templ, result, match_method );
 normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );

 // 通过函数 minMaxLoc 定位最匹配的位置
 double minVal, maxVal; 
 Point minLoc, maxLoc;
 Point matchLoc;
 
 //通过使用函数 minMaxLoc ,我们确定结果矩阵 R 的最大值和最小值的位置.
 minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );//寻找result中最大值,最小值,及它们所在的位置

 // 对于方法 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;
}


运行结果


本文主要借鉴”Madcola“和”Micheal超“两位大神的文章。两位大神的博客主页是:

https://www.cnblogs.com/skyfsm/(Madcola)

https://blog.csdn.net/qq_42887760(Micheal超)

转自:小白学视觉

本文仅做学术分享,如有侵权,请联系删文。

—THE END—

相关阅读

  • 1亿+粉丝后,小杨哥「疯狂」开小号!

  • 关注「电商老高」公众号并转发本文凭截图免费领取仓储宝典中大型电商仓储供应链必做布局直播短视频的格局一天一个样,中腰部们还在苦思冥想不得要领的时候,顶流们随便一个决定
  • 再见了,大主播

  • 潮水的流向,已经发生了转变。来源 |首席电商观察(微信ID:EC-guancha)作 者 | 李 迎排 版 | 群 响01美ONE打造主播“选秀”综艺在《所有女生的offer》爆火,引领了一波带
  • SEO精准引流2万+,低成本引流获客经验分享

  • 引流,不管做什么项目,流量都是至关重要的一环,怎么实现精准引流呢?这里核心会有两个关键问题:1.如何选择一个性价比高的渠道先进行引流?2.不同渠道如何精准引流?全文共9000多字,生财
  • 浙大电子笔记本,为你新学期加油!

  • 笔记记述老师的叮咛标注自己的思考见证求索的历程不知你是否也有这个习惯用一个崭新的笔记本开启一个新的学期?开学之际,小浙特别带来三套浙大专属的电子笔记本为你的新学期加

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • ​详细剖析模板匹配

  • 点击下方卡片,关注“新机器视觉”公众号重磅干货,第一时间送达模板匹配介绍我们需要2幅图像:原图像 (I): 在这幅图像里,我们希望找到一块和模板匹配的区域模板 (T): 将和原图像
  • See U in Denver:在DAO与数字游民的会客厅

  • See U in Denver: Sit down on couch and talk with Digital Nomads.以太坊引领了去中心化应用程序的发展,并推动了区块链技术的发展。近年来,以太坊社区经常举办活动,以促进来
  • SeeDAO:数字城邦 ── DAO的新形态

  • Whaler捕鲸船社区是Web3领域一个具备开发属性的投研社区,致力于打造纯粹和谐的Crypto氛围,成为宣传共建、践行去中心化的Web3窗口。本周捕鲸词典迎来自立项以来最为浓墨重彩的
  • SeeDAO 第二届节点大会会议议程公布

  • 012.22(周三) SeeDAO 公共岗位竞选演讲 - 1 (治理+技术条线) 19:00 - 22:00扫码预约022.23(周四)SeeDAO 公共岗位竞选演讲 - 2(品牌条线) 20:00 - 22:00扫码预约032.24(周五)节点大会d