基于VS与OpenCV的模板匹配学习(1):OpenCV matchTemplate()示例

基于C++与OpenCV的模板匹配学习(1)

OpenCV matchTemplate()示例


文章目录

  • 基于C++与OpenCV的模板匹配学习(1)
  • OpenCV matchTemplate()示例
  • 前言
  • 一、模板匹配
    • 1.1 概念
    • 1.2 基于灰度值的模板匹配
      • 1.2.1 差值平方和SAD与SSD
      • 1.2.2 归一化互相关系数NCC
    • 1.3 基于边缘的模板匹配
  • 二、OpenCV matchTemplate示例
    • 2.1 引入库
    • 2.2 读入图像
    • 2.3 匹配参数
    • 2.4 匹配函数实现
    • 2.5 结果分析


前言

本项目基于OpenCV3.4.12与Visual Studio2022进行开发,项目目标是实现特定目标的Pattern Match从而进行工业上的位置校正。这篇文章主要分享项目过程的学习经验,不涉及工程的具体实现,希望可以给刚接触到OpenCV的朋友们提供参考。


一、模板匹配

1.1 概念

模板匹配是一项在一副图像中寻找与另一幅模板图像最匹配的部分的技术。我们使用一个模板图像描述被搜索物体,计算模板图像与目标图像的相关位姿之间的相似度。如果相似度很高,那么意味着找到了该模板的一个示例。
相似度是一个广义的概念,我们将相似度使用不同的方式定义,例如基于模板与图像的灰度值或基于模板边缘与图像边缘的接近程度。这也使得模板匹配大致分为基于灰度值的模板匹配与基于特征的模板匹配。

1.2 基于灰度值的模板匹配

基于灰度值的模板匹配是最简单的一类匹配算法,该算法基于模板与图像中最原始的灰度值进行匹配。算法中,我们暂时假设目标物的位姿可以使用一个平移描述。我们沿图像中所有点移动模板并在每个位置计算相似度。

1.2.1 差值平方和SAD与SSD

最简单的相似度量方法是计算计算模板与图像之间差值的绝对值的总和或所有差值的平方和(SAD和SSD)。如果模板与图像是相同的,那么相似度等于0,如果模板与图像的区别越大,相似度量的值也越大。为了在图像中找到模板的实例,我们可以使用一个给定的上限对相似性图像进行阈值分割,一般情况阈值分割得到的是包含一些邻接像素的区域。为了得到模板的唯一位置,我们必须在阈值分割得到每个连通区域中的相似度量最小值。
在光照情况保持不变的状况下,SAD和SSD相似度量结果非常好。但是如果光照发生变化,甚至在图像中存在相同物体的情况下,相似度量返回非常大的结果。这主要是因为图像中的灰度值已经不再相等。

1.2.2 归一化互相关系数NCC

在不能保证光照稳定的情况下,必须使用另外一种相似度量方法。理想的情况下,这个相似度量应该不随任何线性光照变化而变化,能够达到这种要求的一种相似度量是归一化互相关系数NCC。
归一化互相关系数通过直接减去平均灰度值可以消除加法对图像的影响,通过除以灰度值的标准方差可以消除乘法对图像的影响。

1.3 基于边缘的模板匹配

基于灰度值的模板匹配算法可以解决机器视觉应用中许多问题。然而,越来越多的应用中要求遭受部分遮挡或者本身存在极大干扰的目标物体依旧实现匹配。这些干扰通常称为混乱,目前的基于灰度值的模板匹配算法不能处理这种类型的干扰。因为,我们需要一些其他方法,可以在存在遮挡、混乱和非线性光照变化的情况下找到目标物体。
图像的边缘不会(至少很少)受光线变化的影响,这是一个很重要的光学特性,并经常被应用在可靠的模板匹配算法中。使用边缘匹配的唯一问题,是如何选择合适阈值进行边缘分割。阈值太大,目标物体的重要边缘可能丢失;阈值太小,图像中会有乱七八糟的边缘。
使用边缘匹配存在几种策略。
(1)使用原始的边缘点
(2)将边缘分割为多个几何基元,匹配几何基元
(3)边缘分割,匹配边缘的突变点

二、OpenCV matchTemplate示例

本文基于OpenCV的matchTemplate()函数,以SAD举例作为基于灰度值的模板匹配的demo。OpenCV版本为3.4.12。

2.1 引入库

代码如下:

#include
#include
#include 
#include 
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/features2d.hpp"
#include 

2.2 读入图像

代码如下:

	cv::Mat srcImage; //原图像
	cv::Mat templateImage;//模板图像
	srcImage = cv::imread("1.png", 0);
	templateImage = cv::imread("2.png", 0);

srcImage为原图像,templateImage为模板。

2.3 匹配参数

代码如下:

    //MatchMethod:
    //CV_TM_SQDIFF_NORMED 归一化平方差匹配法; 
    //CV_TM_CCORR_NORMED 归一化相关匹配法; 
    //CV_TM_CCOEFF_NORMED 归一化相关系数匹配法
	int MatchMethod = CV_TM_SQDIFF;
	TemplateMatching_GrayValueBased(srcImage, templateImage, MatchMethod);

MatchMethod为匹配模式,OpenCV有六种,这边列出了归一化的三种,归一化平方差匹配法、归一化相关匹配法、归一化相关系数匹配法。

2.4 匹配函数实现

代码如下:

	cv::Mat resultImage; //输出结果
	int resultImage_rows = srcImage.rows - templateImage.rows + 1;
	int resultImage_cols = srcImage.cols - templateImage.cols + 1;
	resultImage.create(resultImage_rows, resultImage_cols, CV_32FC1);
	cv::matchTemplate(srcImage, templateImage, resultImage, MatchMethod);
	cv::normalize(resultImage, resultImage, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
	double minValue;
	double maxValue;
	double objectValue;
	cv::Point minLocation;
	cv::Point maxLocation;
	cv::Point matchLocation;
	cv::minMaxLoc(resultImage, &minValue, &maxValue, &minLocation, &maxLocation, cv::Mat());
	if (MatchMethod == CV_TM_SQDIFF_NORMED|| MatchMethod == CV_TM_SQDIFF)
	{
		matchLocation = minLocation;
		objectValue = minValue;
	}
	else
	{
		matchLocation = maxLocation;
		objectValue = maxValue;
	}
	cv::rectangle(srcImage, matchLocation, cv::Point(matchLocation.x + templateImage.cols, matchLocation.y + templateImage.rows), 255, 4, 16, 0);
	cv::drawMarker(srcImage, cv::Point(matchLocation.x + templateImage.cols/2, matchLocation.y + templateImage.rows/2), 255, cv::MarkerTypes::MARKER_CROSS, 20, 2, 8);

这里主要用了OpenCV的matchTemplate和normalize函数,前者是模板匹配,后者是对相似度量进行归一化操作;由于不同相似度量代表的意义不同,当选择SSD或SAD时,我们选择相似度量的最小值作为匹配目标,当选择其他的匹配模式,我们选择相似度量的最大值作为匹配目标。

2.5 结果分析

基于VS与OpenCV的模板匹配学习(1):OpenCV matchTemplate()示例_第1张图片
基于VS与OpenCV的模板匹配学习(1):OpenCV matchTemplate()示例_第2张图片
基于VS与OpenCV的模板匹配学习(1):OpenCV matchTemplate()示例_第3张图片
第一张图为匹配结果图,白色方框区域为匹配结果区域,中心的十字代表最优的匹配点,可以看到在平方差匹配模式下,该图像的模板匹配效果良好;第二张图为模板图像;第三张图为相似度量结果图,由于SAD算法的相似度量越小,代表图像匹配度越高,图像的黑点区域为全图的最优解。


参考文献:
《机器视觉算法及应用 Machine vision algorithm and Application》

你可能感兴趣的:(OpenCV模板匹配,opencv,c++)