模板匹配算法简介

基本概念

  在图像中寻找目标图像(模板),或者说,就是在图像中寻找与模板图像相似部分的一种图像处理技术。依赖于选择的方法不同,模板匹配可以处理各种情形下的变换,如照明、杂点、大小、位置以及旋转,甚至模板内部的相对移动。

分类

  HDevelop开发环境中提供的匹配的方法主要有三种,即Component-BasedGray-Value-BasedShape-Based,分别是基于组件(或成分、元素)的匹配,基于灰度值的匹配和基于形状的匹配。

总体流程

形状匹配

基本流程

详细步骤

  1. 读取图像,这里一定要是灰度图,如果是彩色图,先用rgb1_to_gray()转成灰度图像;
  2. 确定ROI的区域。例如确定矩形,只需要确定矩形的左上点和右下点的坐标即可,利用gen_rectangle1()生成一个矩形,利用area_center()找到这个矩形的中心;
  3. 从图像中获取这个ROI区域的图像,利用reduce_domain()可以得到这个ROI。在建立模板之前,可以先对这个区域进行一些预处理,方便以后的建模,比如阈值分割,形态学的一些处理等等(后续匹配时,也需要执行预处理操作);
  4. 利用create_shape_model()创建模板。这个函数有许多参数,具体见下文分析;
  5. 创建好模板后,这时还需要使用inspect_shape_model()来监视模板,它检查参数的适用性,还能帮助找到合适的参数;然后在使用get_shape_model_contours()获得这个模板的轮廓,用于后面的匹配;
  6. 创建好模板后,就可以打开另一幅图像,进行模板匹配了。这个过程就是在新图像中寻找与模板匹配的图像部分,利用find_shape_model()进行模板匹配,具体参数含义见下文分析;
  7. 最后利用vector_angle_to_rigid()affine_trans_contour_xld()将其转化并显示。前一个是从一个点和角度计算一个刚体仿射变换,这个函数从匹配函数的结果中对构造一个刚体仿射变换(平移,旋转和缩放)很有用,把参考图像变为当前图像。

参数含义

create_shape_model()

1
2
3
4
5
6
7
8
9
10
11
create_shape_model(
const Hobject& Template , //reduce_domain后的模板图像
Hlong NumLevels, //金字塔的层数,可设为“auto”或0—10的整数
Double AngleStart, //模板旋转的起始角度
Double AngleExtent, //模板旋转角度范围, >=0
Double AngleStep, //旋转角度的步长, >=0 and <=pi/16
const char* Optimization, //设置模板优化和模板创建方法
const char* Metric, //匹配方法设置
Hlong Contrast, //设置对比度
Hlong MinContrast , //设置最小对比度
Hlong* ModelID ) //输出模板句柄

  NumLevels越大,找到匹配使用的时间就越小。如果金字塔的层数太大,模板不容易识别出来,这是需要将find_shape_model函数中MinScoreGreediness参数设置的低一些。如果金字塔层数太少找到模板的时间会增加。
  AngleStartAngleExtent决定可能的旋转范围,AngleStep指定角度范围搜索的步长;
  Optimization:模板定位时使用的特征点的数量,模板点储存模式,设为none时,全点储存。当模板较小时,较少点数并不会降低模板匹配时间。在模板数据量大时有必要降低数据量(point_reduction_high),以提高定位速度。
  Metric定义了在图像中匹配模板的条件,如果Metric=use_polarity,图像中的目标必须和模型具有一样的对比度。例如,如果模型是一个亮的目标在一个暗的背景上,那么仅仅那些比背景亮的目标可以找到。如果Metric=ignore_global_polarity,在两者对比度完全相反时也能找到目标。在上面的例子中,如果目标是比背景暗的也能将目标找到。
  Contras决定着模型点的对比度。对比度是用来测量目标与背景之间和目标不同部分之间局部的灰度值差异。Contrast的选择应该确保模板中的主要特征用于模型中。Contrast也可以是两个数值,这时模板使用近似edges_image函数中滞后阈值的算法进行分割。这里第一个数值是比较低的阈值,第二个数值是比较高的阈值。Contrast也可以包含第三个,这个数值是在基于组件尺寸选择重要模型组件时所设置的阈值,比如,比指定的最小尺寸的点数还少的组件将被抑制。这个最小尺寸的阈值会在每相邻的金字塔层之间除以2。如果一个小的模型组件被抑制,但是不使用滞后阈值,然而在Contrast中必须指定三个数值,在这种情况下前两个数值设置成相同的数值。这个参数的设置可以在inspect_shape_model函数中查看效果。如果Contrast设置为autocreate_shape_model将会自动确定三个上面描述的数值。或者仅仅自动设置对比度(auto_contrast),滞后阈值(auto_contrast_hyst)或是 最小尺寸(auto_min_size)中一个。其他没有自动设置的数值可以按照上面的格式再进行设置。可以允许各种组合,例如:如果设置 [‘auto_contrast’,’auto_min_size’],对比度和最小尺寸自动确定;如果设置 [‘auto_min_size’,20,30],最小尺寸会自动设定,而滞后阈值被设为20和30。有时候可能对比度阈值自动设置的结果是不满意的,例 如,由于一些具体应用的原因当某一个模型组件是被包含或是被抑制时,或是目标包含几种不同的对比度时,手动设置这些参数效果会更好。
  MinContrast用来确定在执行find_shape_model函数进行识别时模型的哪一个对比度必须存在,也就是说,这个参数将模型从噪声图像中分离出来。因此一个好的选择应该是在图像中噪声所引起的灰度变化范围。例如,如果灰度浮动在10个灰度级内,MinContrast应该设置成10。如果模板和搜索图像是多通道图像,Metric参数设置成ignore_color_polarity,在一个通道中的噪声必须乘以通道个数的平方根再去设置MinContrast。例如,如果灰度值在一个通道的浮动范围是10个灰度级,图像是三通道的,那么MinContrast应该设置为17。很显然,MinContrast必须小于Contrast。如果要在对比度较低的图像中识别模板,MinContrast必须设置为一个相对较小的数值。如果要是模板即使严重遮挡(occluded)也能识别出来,MinContrast应该设置成一个比噪声引起的灰度浮动范围略大的数值,这样才能确保在find_shape_model函数中提取出模板准确的位置和旋转角度。如果MinContrast设置为auto,最小对比度会基于模板图像中的噪声自动定义。因此自动设定仅仅在搜索图像和模板图像噪声近似时才可以使用。

find_shape_model()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
find_shape_model(
const Hobject& Image, //搜索图像
Hlong ModelID, //模板句柄
Double AngleStart, // 搜索时的起始角度
Double AngleExtent, //搜索时的角度范围,必须与创建模板时的有交集。
Double MinScore, // 输出的匹配的质量系数Score 都得大于该值
Hlong NumMatches, // 定义要输出的匹配的最大个数
Double MaxOverlap, // 当找到的目标存在重叠时,且重叠大于该值时选
//择一个好的输出
const char* SubPixel, // 计算精度的设置,五种模式,多选2,3
Hlong NumLevels, // 搜索时金字塔的层数
Double Greediness , //贪婪度,搜索启发式,一般都设为0.9,越高速度快
//容易出现找不到的情况
Halcon::HTuple* Row, //输出匹配位置的行坐标
Halcon::HTuple* Column, //输出匹配位置的列坐标
Halcon::HTuple* Angle, //输出匹配角度
Halcon::HTuple* Score ) //输出匹配质量

  Score是一个01之间的数,是模板在搜索图像中可见比例的近似测量。如果模板的一半被遮挡,该值就不能超过0.5
  Imagedomain定义了模型参考点的搜索区域,参数AngleStartAngleExtent确定了模型搜索的旋转角度,参数MinScore定义模板匹配时至少有个什么样的质量系数才算是在图像中找到模板。MinScore设置的越大,搜索的就越快。如果模板在图像中没有被遮挡, MinScore可以设置为0.8这么高甚至0.9
  NumMatches定义了在图像上找到模板的最大的个数。如果匹配时的质量系数大于MinScore的目标个数多于NumMatches,仅仅返回质量系数最好的NumMatches个目标位置。如果找的匹配目标不足NumMatches,那么就只返回找到的这几个。参数MinScore优于NumMatches
  如果模型具有对称性,会在搜索图像的同一位置和不同角度上找到多个与目标匹配的区域。参数MaxOverlap01之间的,定义了找到的两个目标区域最多重叠的系数,以便于把他们作为两个不同的目标区域分别返回。如果找到的两个目标区域彼此重叠并且大于MaxOverlap,仅仅返回效果最好的一个。重叠的计算方法是基于找到的目标区域的任意方向的最小外接矩形(看smallest_rectangle2)。如果MaxOverlap=0, 找到的目标区域不能存在重叠, 如果MaxOverla p=1,所有找到的目标区域都要返回。
  SubPixel确定找到的目标是否使用亚像素精度提取。如果SubPixel设置为none(或者false背景兼容),模型的位置仅仅是一个像素精度和在create_shape_model中定义的角度分辨率。如果SubPixel设置为interpolation(或true),位置和角度都是亚像素精度的。在这种模式下模型的位置是在质量系数函数中插入的,这种模式几乎不花费计算时间,并且能达到足够高的精度,被广泛使用。
  NumLevels是在搜索时使用的金字塔层数,如有必要,层数截成创建模型时的范围。如果NumLevels=0,使用创建模板时金字塔的层数。另外NumLevels还可以包含第二个参数,这个参数定义了找到匹配模板的最低金字塔层数。NumLevels=[4,2]表示匹配在第四层金字塔开始,在第二层金字塔找到匹配(最低的设为1)。可以使用这种方法降低匹配的运行时间,但是这种模式下位置精度是比正常模式下低的,所谓正常模式是在金字塔最底层匹配。因此如果需要较高的精度,应该设置SubPixel至少为least_squares。如果金字塔最底层设置的过大,可能不会达到期望的精度,或者找到一个不正确的匹配区域。这是因为在较高层的金字塔上模板是不够具体的,不足以找到可靠的模板最佳匹配。在这种情况下最低金字塔层数应设为最小值。
  参数Greediness确定在搜索时的“贪婪程度”。如果Greediness=0,使用一个安全的搜索启发式,只要模板在图像中存在就一定能找到模板,然而这种方式下搜索是相对浪费时间的。如果Greediness=1,使用不安全的搜索启发式,这样即使模板存在于图像中,也有可能找不到模板,但只是少数情况。如果设置Greediness=0.9,在几乎所有的情况下,总能找到模型的匹配。

实战代码解释

读取图像

1
2
3
4
5
read_image (Image, 'C:/Users/Cxx/Desktop/Image.jpg') //读取图像
get_image_size (Image, Width, Height)//获取图像的大小
dev_close_window ()//关闭窗口
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)//打开一个新窗口
dev_display (Image)//显示图像

创建ROI区域(人为给定取值)

1
2
3
gen_circle (Circle, 270, 280, 90)//创建圆形区域 
reduce_domain (Image, Circle, ImageReduced)//获得ROI区域的图像
area_center (Circle, Area, Row1, Column1)//求出中心坐标

创建模板并监视模板

1
2
3
4
5
create_scaled_shape_model (ImageReduced, 5, rad(-45), rad(90), 'auto', 0.8, 1.1, 'auto', 'auto', 'ignore_global_polarity', 'auto', 'auto', ModelID)// 准备一个可缩放比例的匹配轮廓模型
inspect_shape_model (ImageReduced, ModelImages, ModelRegions, 4, 20)//创建一个轮廓匹配模型基于金字塔的图像
get_shape_model_params (ModelID, NumLevels, AngleStart, AngleExtent, AngleStep, ScaleMin, ScaleMax, ScaleStep, Metric, MinContrast)//返回一个轮廓匹配模型的参数
get_shape_model_contours (ModelContours, ModelID, 1)
write_shape_model (ModelID, 'C:/Users/Cxx/Desktop/img_model3.shm')//保存模板

仿射变换

1
2
3
4
5
dev_set_color ('red')//设置颜色
dev_set_line_width (2)//设置线宽
vector_angle_to_rigid (0, 0, 0, Row1, Column1, 0, HomMat2D)//通过点和角度方面来计算一个放射变换矩阵
affine_trans_contour_xld (ModelContours, ContoursAffineTrans, HomMat2D)//通过任意2D放射变换转换为XLD轮廓
stop ()

模板匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
read_image (Image1, 'C:/Users/Cxx/Desktop/Image1.jpg')//读取另一张图片
dev_display (Image1)//显示图像
find_scaled_shape_model (Image1, ModelID, rad(-45), rad(90), 0.8, 1.1, 0.5, 0, 0.5, 'least_squares', 5, 0.8, Row2, Column2, Angle, Scale, Score)//模板匹配
for I := 0 to |Score| - 1 by 1
*生成一个单位矩阵
hom_mat2d_identity (HomMat2DIdentity)
*平移
hom_mat2d_translate (HomMat2DIdentity, Row2[I], Column2[I], HomMat2DTranslate)
*旋转
hom_mat2d_rotate (HomMat2DTranslate, Angle[I], Row2[I], Column2[I], HomMat2DRotate)
*放缩,得到最终的仿射变换矩阵
hom_mat2d_scale (HomMat2DRotate, Scale[I], Scale[I], Row2[I], Column2[I], HomMat2DScale)
*仿射变换
affine_trans_contour_xld (ModelContours, ModelTrans, HomMat2DScale)
dev_display (ModelTrans)
endfor

  最终显示的模板匹配结果为:

其他

形态学

  1. 膨胀:通过结构元素(正方形,圆形等),对原图像进行对应法则处理,增加像素
  2. 腐蚀:减少像素
  3. 开运算:先腐蚀后膨胀,减少像素
  4. 闭运算:先膨胀后腐蚀,增加像素

注:

  1. 膨胀>闭运算,腐蚀>开运算
  2. 对二值化图像:腐蚀,膨胀等:改变形状;对灰度图像:腐蚀:变暗,膨胀:变亮,开闭运算同理。

Bloab分析

  二值化->形态学->特征选择

预处理

  1. 中值滤波:求中间值,消除过亮或过暗的点,即消除椒盐噪声;
  2. 均值滤波:求均值
  3. 高斯滤波:加权值

参考博客

  1. 基于HALCON的模板匹配方法总结
  2. Halcon 模板匹配参数详解
  3. halcon第十四讲:基于形状的模板匹配
谢谢老板!
-------------本文结束感谢您的阅读给个五星好评吧~~-------------