当前位置: 首页 > news >正文

open cv模板匹配

模板匹配介绍(Template Match)

模板匹配:模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术

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

所以模板匹配首先需要一个模板图像T(给定的子图像)
另外需要一个待检测的图像S

工作方法:在待检测图像上,从左到右,从上向下计算模板图像与
重叠子图像的匹配度(这样的搜寻策略叫做滑动窗口) 匹配程度越大,两者相同的可能性越大
(工作原理类似于卷积操作 逐像素寻找匹配像素)

寻找子图像和目标图像直方数据的相似程度


!!!
模板匹配具有自身的局限性,主要表现在它只能进行平行移动
原图像中的匹配目标发生旋转或大小变化,该算法无效


2、匹配算法方法介绍

opencv中提供了6种常见的匹配算法如下:

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

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

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

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

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

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

3、相关API介绍
cv::matchTemplate

matchTemplate(
InputArray image,//源图像,必须是8bit或者32bit浮点数图像
InputArray templ,//模板图像,类型与输入图像一致
OutputArray result,//输出矩阵图像结果,必须是单通道32bit浮点数。例如:
假设原图像大小是WH,模板图像大小是wh,那么结果大小必须为(W-w+1)*(H-h+1)。
int method,//使用的模板匹配方法
InputArray mask=noArray()//(optional)//掩膜矩阵 选择操作区域 一般不使用
)

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

Mat src,roi,dst;

int method;//模板匹配方法
int MAXmethod = 6;//匹配方法最高值

void MatchDemo(int,void*);

int main()
{

	src = imread("D:/实验台/机器视觉/测试图片/焊接.jpg");
	roi = imread("D:/实验台/机器视觉/测试图片/焊接目标.jpg");
	if (src.empty())//如果src这个数据库属性为空
	{
		cout << "无法打开" << endl;
		return -1;
	}
	imshow("原图", src);
	imshow("模板", roi);
	namedWindow("模板匹配",CV_WINDOW_AUTOSIZE);
	createTrackbar("匹配算法类型","模板匹配",&method, MAXmethod, MatchDemo);
	MatchDemo(0, 0);
	waitKey(0);
	return 0;
}

void MatchDemo(int, void*)
{
	//设置相似性匹配结果矩阵result的大小
	int width = src.cols - roi.cols + 1;  //每行横向移动只需移动raw_img.cols - mask_img_cols + 1次
	int height = src.rows - roi.rows + 1;//每列纵向移动只需移动raw_img.cols - mask_img.cols + 1次
	Mat result(height, width,CV_32FC1);//矩阵类型设置为32浮点型单通道图片 便于后期进行模板匹配计算
	//在Mat类型变量访问时下标是反着写的,即:按照(y, x)的关系形式访问
	imshow("生成的矩阵模板result",result);

	printf("src col=%d src row=%d \n roi col=%d roi row=%d \n result col=%d result row=%d \n ", src.cols, src.rows, roi.cols, roi.rows, result.cols, result.rows);

	matchTemplate(src,roi,result,method,Mat());//模板匹配
	//模板目标匹配函数
	//image:待匹配的源图像 必须是8位整数或32位浮点图像
	//temp:匹配模板图像 必须不大于源图像并具有相同的数据类型
	//result:保存计算出的每一个位置的相关系数结果的矩阵(通过minMaxloc函数确认矩阵的最大值和最小值) 必须是单通道32位浮点 如果image的尺寸为W x H,templ的尺寸为w x h,则result的尺寸为(W-w+1)x(H-h+1)
	//模板匹配的算法
	//掩膜 选取需要处理的矩阵范围 此处默认为不进行掩膜操作
	imshow("未进行归一化的相关系数图", result);


	//将模板匹配的相关系数归一化到0-1之间(适配模板匹配方法的阈值范围)
	normalize(result,result,0,1,NORM_MINMAX,-1,Mat());
	imshow("进行归一化的相关系数图", result);

	//寻找最小值的位置和最大值的位置 
	Point minloc;//相关系数最小值的坐标
	Point maxloc;//相关系数最大值的坐标
	Point roiloc;//画矩形时坐标的最终选择位置
	double min, max;
	minMaxLoc(result, &min, &max, &minloc, &maxloc, Mat());
	//在一个数组中找到全局最小值和全局最大值(此案例中我们给定的是一个保存每一个位置的相关系数结果的矩阵)
	//result-输入的给定矩阵(之前匹配好的矩阵结果 单通道图像)任意单通道图像的图片都可以(src.[0,mask] 还可以设置掩膜)多通道图像在使用minMaxLoc()函数是不能给出其最大最小值坐标的 因为每个像素点其实有多个坐标
	//min-参数表示返回的最小值,如果不需要,则使用NULL
	//max-参数表示返回的最大值,如果不需要,则使用NULL
	//minloc- 参数表示返回的最小位置的指针(在2D情况下) 如果不需要,则使用NULL
	//maxloc-参数表示返回的最大位置的指针 (在2D情况下)	   如果不需要,则使用NULL
	//Mat()-建立掩膜 默认不建立掩膜
	
	printf("显示返回的最小值和最大值min=%1f,max=%1f",min,max);//double的格式说明符为 1f 
	//此案例中 返回的min为0 max为1

	/*
	TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
	TM_CCORR:计算相关性,计算出来的值越大,越相关
	TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
	TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
	TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
	TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关
    */
	//因为这六种计算方法中 只有 CV_TM_SQDIFF和CV_TM_SQDIFF_NORMED是值越小越相关
	if (method == CV_TM_SQDIFF || method == CV_TM_SQDIFF_NORMED)
	{
		//所以当使用的方法为CV_TM_SQDIFF或CV_TM_SQDIFF_NORMED时(0相关)
		//选择返回相关性最小的坐标位置作为绘制矩形的坐标起点
		roiloc = minloc;
	}
	else
	{
		//如果未使用这两个方法时(1相关) 
		//选择返回相关性最大的坐标位置指针作为绘制矩形的坐标起点
		roiloc = maxloc;
	}

	printf("\n相关性最小的坐标位置 为 X=%d Y=%d", roiloc.x, roiloc.y);
	printf("\n相关性最大的坐标位置 为 X=%d Y=%d", roiloc.x, roiloc.y);
	printf("\n矩形绘制坐标起点为 X=%d Y=%d", roiloc.x, roiloc.y);
	
	
	//对找到的位置点 进行几何形状矩形绘制
	src.copyTo(dst);
	rectangle(dst,Rect(roiloc.x,roiloc.y,roi.cols, roi.rows),Scalar(0,0,255),2,LINE_AA);//在原图上绘制矩形
	rectangle(result, Rect(roiloc.x, roiloc.y, roi.cols, roi.rows), Scalar(0, 0, 255), 2, LINE_AA);//在相关性关系图上绘制矩形
	//绘制矩形(目标图片,矩形(矩形顶点的X坐标位置,矩形顶点的Y坐标位置,矩形宽度,矩形高度),线框颜色,线宽,线类型)
	//Point是对象类型,它有两个属性x, y,分别代表x, y坐标 所以我们可以用roiloc.x,roiloc.y确认绘制矩形的左上角的XY坐标
	
	imshow("每一个位置的相关系数图",result);
	imshow("模板匹配", dst);
}

基于模板匹配的焊缝识别
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//模板匹配案例 交警识别
https://blog.csdn.net/qq_39861376/article/details/82191411?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.nonecase


matchTemplate()参数详解

函数原型
CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, OutputArray result, int method );

image:待匹配的源图像
templ:模板图像
result:保存结果的矩阵,我们可以通过minMaxLoc() 确定结果矩阵的最大值和最小值的位置.
  minMaxLoc()函数:查找全局最小和最大稀疏数组元素并返回其值及其位置
  void minMaxLoc(const SparseMat& a, double* minVal,double* maxVal, int* minIdx=0, int* maxIdx=0);
a: 匹配结果矩阵
&minVal 和 &maxVal: 在矩阵 result 中存储的最小值和最大值
&minLoc 和 &maxLoc: 在结果矩阵中最小值和最大值的坐标.

method :模板匹配的算法
有以下六种:
  enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
TM_SQDIFF,TM_SQDIFF_NORMED匹配数值越低表示匹配效果越好,其它四种反之。
TM_SQDIFF_NORMED,TM_CCORR_NORMED,TM_CCOEFF_NORMED是标准化的匹配,得到的最大值,最小值范围在0~1之间,其它则需要自己对结果矩阵归一化。
不同的方法会得到差异很大的结果,可以通过测试选择最合适的方法。


模板匹配详解
https://blog.csdn.net/KYJL888/article/details/81480670

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

https://www.jianshu.com/p/749e206fd15d

相关文章:

  • 京东为什么要加班?算是爆料吗?
  • open cv轮廓发现
  • open cv凸包
  • open cv轮廓周围绘制圆形和矩形
  • open cv图形矩
  • Python标准库的学习准备
  • open cv点多边形测试
  • 将redhat的yum换成centos的yum
  • open cv基于距离变换与分水岭的图像分割
  • poj 1661 Help Jimmy (动态规划)
  • 呕心沥血!open cv4.1.2添加contrib4.1.2扩展模块
  • java基础----垃圾回收器如何工作
  • open cvSURF特征检测
  • php条件判断
  • open cvSIFT特征点检测
  • emacs初体验
  • es6--symbol
  • HTTP请求重发
  • IDEA常用插件整理
  • JavaScript学习总结——原型
  • linux安装openssl、swoole等扩展的具体步骤
  • Linux下的乱码问题
  • Python学习之路13-记分
  • unity如何实现一个固定宽度的orthagraphic相机
  • Vue.js-Day01
  • Vue实战(四)登录/注册页的实现
  • Webpack 4 学习01(基础配置)
  • 对JS继承的一点思考
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 人脸识别最新开发经验demo
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 【干货分享】dos命令大全
  • C# - 为值类型重定义相等性
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • 进程与线程(三)——进程/线程间通信
  • $L^p$ 调和函数恒为零
  • (16)Reactor的测试——响应式Spring的道法术器
  • (3)选择元素——(17)练习(Exercises)
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (四)鸿鹄云架构一服务注册中心
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • **PHP二维数组遍历时同时赋值
  • .net 调用php,php 调用.net com组件 --
  • .NET/C# 使用反射注册事件
  • .NETCORE 开发登录接口MFA谷歌多因子身份验证
  • .net专家(张羿专栏)
  • @Autowired和@Resource装配
  • @EnableWebMvc介绍和使用详细demo
  • @test注解_Spring 自定义注解你了解过吗?
  • [2016.7 day.5] T2
  • [Android学习笔记]ScrollView的使用
  • [Arduino学习] ESP8266读取DHT11数字温湿度传感器数据
  • [autojs]逍遥模拟器和vscode对接