我们都知道,HDevelop中,在菜单栏“助手”中,可以通过“Matching”助手辅助模板匹配的建模等操作。

 

基于形状”的模板匹配, 主要有三种类型:find_shape_model、find_scaled_shape_model、find_aniso_shape_model。

那么这三种类型有什么区别呢?我用一张图来说明。

 

 

说明:find_shape_model指的是行列方向均无缩放的模板匹配,find_scaled_shape_model指的是行列等比例缩放的模板匹配,find_aniso_shape_model指的是行列不等比例缩放各向异性缩放)的模板匹配。

 

 

上面三个算子一般如何根据实际情况选择呢?

 

① 在实际的视觉项目中,一般工件的大小是基本相同的。如果只有一个相机,那么可以直接用find_shape_model来做模板匹配;

 

② 如果有多个工站、多个相机,并且用的还是同款相机、同款远心镜头的话,由于远心镜头只有一个固定的对焦距离,因此两个工位中的工件在图中的大小是一样大的。此时还是可以用find_shape_model来做模板匹配;

 

③ 如果有多个工站、多个相机,但是用的是普通镜头的话,由于普通镜头的对焦距离是不固定的,因此视野的放大倍率也不固定,此时两个工位中的工件在图中的大小是不一样的。此时适合用find_scaled_shape_model来做模板匹配;

 

④ find_aniso_shape_model的应用场景较少,很少用于精细的模板匹配定位检测。在运动速度不固定的线扫项目中,可能会用到这个算子。因为线扫平台速度变化时,待测工件图像的长宽比经常会发生变化,此时用find_aniso_shape_model就比较合适。一般来说,这个算子的执行时间是三个里面最长的,因为它有最大的不确定性

 

find_aniso_shape_model的应用场景有限,因此我不讨论它。从上面的分析可以看出:find_scaled_shape_model是完全可以涵盖find_shape_model的功能的,因此下文以find_scaled_shape_model算子来展开分析。

 

以下图为例:

 

测试的软硬件环境为:Windows 10、Intel Xeon E5-2630 v3   2.40GHz、Halcon 17.12。

 

该图的建模区域,以及初始参数设置如下图所示:

 

另外,最小分数为0.3,匹配的最大数为1。除此之外的所有参数均使用默认值。

 

 

一键生成的代码精简后如下:

 1 set_system ('border_shape_models', 'false')
 2 read_image (Image, 'C:/Users/02/Desktop/形状模板匹配/接口.png')
 3 gen_rectangle1 (ModelRegion, 92, 80, 339, 731)
 4 reduce_domain (Image, ModelRegion, TemplateImage)
 5 * 
 6 create_scaled_shape_model (TemplateImage, 4, rad(0), rad(360), rad(0.3386), 0.97, 1.03, 0.0059, ['point_reduction_high','no_pregeneration'], 'use_polarity', [60,80,10], 5, ModelID)
 7 *
 8 get_shape_model_contours (ModelContours, ModelID, 1)
 9 * 
10 * Matching 02: Get the reference position
11 area_center (ModelRegion, ModelRegionArea, RefRow, RefColumn)
12 vector_angle_to_rigid (0, 0, 0, RefRow, RefColumn, 0, HomMat2D)
13 affine_trans_contour_xld (ModelContours, TransContours, HomMat2D)
14 * 
15 * Matching 02: Display the model contours
16 dev_display (Image)
17 dev_set_color ('green')
18 dev_set_draw ('margin')
19 dev_display (ModelRegion)
20 dev_display (TransContours)
21 
22 *开始匹配(这里简单起见,匹配的就是建模图像本身)
23 find_scaled_shape_model (Image, ModelID, rad(0), rad(360), 0.97, 1.03, 0.3, 1, 0.5, 'least_squares', [4,1], 0.75, Row, Column, Angle, Scale, Score)
24 
25 dev_display (Image)
26 for I := 0 to |Score| - 1 by 1
27     hom_mat2d_identity (HomMat2D)
28     hom_mat2d_scale (HomMat2D, Scale[I], Scale[I], 0, 0, HomMat2D)
29     hom_mat2d_rotate (HomMat2D, Angle[I], 0, 0, HomMat2D)
30     hom_mat2d_translate (HomMat2D, Row[I], Column[I], HomMat2D)
31     affine_trans_contour_xld (ModelContours, TransContours, HomMat2D)
32     dev_set_color ('green')
33     dev_display (TransContours)
34 endfor
35 
36 clear_shape_model (ModelID)

 

一般来说,我们不太在意建模算子create_scaled_shape_model的速度,因为模型文件一般是提前准备好保存在本地的。建模快一点慢一点,问题不大。但是建模中,也有几个参数对查找模板的速度有较大影响的,它们是:

 

设置合适的对比度,设置较大的“最小组件尺寸”,可以确保模板轮廓XLD不会过于复杂。过于复杂的XLD是会影响后面的模板查找速度的。

 

 

find_scaled_shape_model语句中,对查找速度有明显影响的算子,我已经标红了,如下:

find_scaled_shape_model (Image, ModelID, rad(0), rad(360), 0.97, 1.03, 0.3, 1, 0.5, 'least_squares', [4,1], 0.75, Row, Column, Angle, Scale, Score) 

 

上面6个参数的参数名和含义如下:

AngleStart(rad(0)): 搜索时的起始角度。

AngleExtent(rad(360)):搜索时的角度范围。

ScaleMin(0.97):行列的最小缩放比例。

ScaleMax(1.03):行列的最大缩放比例。

NumLevels(4):搜索时金字塔的层数。

Greediness(0.75):贪婪系数,启发式搜索,默认值0.75,越高速度越快,但容易出现找不到的情况。这个值我们一般不改它。

 

① 在我电脑上,上面find_scaled_shape_model 算子的查找时间为:25毫秒

 

② find_scaled_shape_model (Image, ModelID, rad(0), rad(360), 0.97, 1.03, 0.3, 1, 0.5, 'least_squares', [3,1], 0.75, Row, Column, Angle, Scale, Score) 

将金字塔层级由“4”改成“3”,查找时间为:83毫秒。(金字塔层级一般不会设置为“1”或者“2”,因为此时查找会特别慢,经常超过1秒钟。如果图像较大,该值一般最小设置为“4”

将金字塔层级由“4”改成“7”,查找时间为:25毫秒。(主要是这张图比较小,当金字塔层级大于4以后,再增加,并不能显著减少查找时间)

 

值得说明的是:使用较小的金字塔层级,模板匹配的成功率会大大增加。(但是时间会增加)

 

另外,NumLevels可以包含第二个值,该值确定跟踪找到的匹配项的最低金字塔级别。因此,NumLevels值[4,2]表示匹配从第4个金字塔级别开始,并跟踪匹配到第2个金字塔级别(最低的金字塔级别由值1表示)。该机制可用于减少匹配的运行时间。

然而,应当注意,一般在该模式下提取的姿态参数的精度低于在正常模式中的精度,在正常模式中,匹配被跟踪到最低金字塔级别(本人注:即级别1)。因此,如果需要高精度,则子像素应至少设置为“least_squares”。

如果要使用的最低金字塔级别选择得太大,则可能会发生无法实现所需精度的情况,或者由于模型在较高金字塔级别上不够具体而可能会找到错误的模型实例。在这种情况下,要使用的最低金字塔级别(我自己的理解:这里指的应该是NumLevels的第二个值)必须设置为较小的值。 (上面三段话翻译自find_scaled_shape_model 的帮助文档)

 

可以得出结论,一般来说,NumLevels := [4, 2],查找速度应该会略快于NumLevels := [4, 1]和NumLevels := [4]。

NumLevels 的第二个值还可以为负数(通常针对边缘模糊的图像的匹配定位),具体参考find_scaled_shape_model 的帮助文档或find_shape_mode参数详解及时长优化

 

③ find_scaled_shape_model (Image, ModelID, rad(0), rad(360), 1.0, 1.0, 0.3, 1, 0.5, 'least_squares', [4,1], 0.75, Row, Column, Angle, Scale, Score) 

将行列最小、最大缩放比例均改为1.0,此时等效于使用find_shape_model算子(查找时间也几乎一样)。此时查找时间为:14毫秒

 

实测可以发现,ScaleMin、ScaleMax这两个参数越接近1,查找所需的时间越短。其实也很好理解,当缩放比例变化范围较大时,准确的模板匹配需要进行更多的尝试,自然会需要更长的计算时间。

 

④ find_scaled_shape_model (Image, ModelID, rad(-10), rad(20), 0.97, 1.03, 0.3, 1, 0.5, 'least_squares', [4,1], 0.75, Row, Column, Angle, Scale, Score) 

将搜索的起始角度设置为rad(-10), 角度范围设置为rad(20),即 [rad(-10), rad(10)] ,此时查找时间为:6毫秒

可见选择合适的搜索起始角度和角度范围,可以大幅度提高查找速度。

 

实验总结:如果想减少模板查找时间,需要创建轮廓XLD不那么复杂的模板,需要设置较小的角度范围,需要设置尽可能小的行列缩放比例,需要设置尽可能大的金字塔层级。

但是,金字塔层级不宜设置过大,金字塔层级太大时,很容易查找模板失败。

 

 

另外,还有两篇文章对模板匹配有一些经验总结,我贴过来:

https://www.cnblogs.com/bile/p/8528843.html

 

https://blog.csdn.net/ABC13222880223/article/details/94437545

 

 

基于形状匹配的参数关系与优化

 

这里主要是重复说明一下这些参数的作用,再强调一下它们影响匹配速度的程度;在为了提高速度而设置参数之前,有必要找出那些在所有测试图像中匹配成功的设置,这时需考虑以下情况:

 

① 必须保证物体在图像边缘处截断,也就是保证轮廓的清晰,这些可以通过形态学的一些方法来处理;

② 如果Greediness值设的太高,就找不到其中一些可见物体,这时最后将其设为0来执行完全搜索;

③ 物体是否有封闭区域,如果要求物体在任何状态下都能被识别,则应减小MinScore值;

④ 判断在金字塔最高级上的匹配是否失败,可以通过find_shape_model()减小NumLevels值来测试;

⑤ 物体是否具有较低的对比度,如果要求物体在任何状态下都能被识别,则应减小MinContrast值;

⑥ 判断是否全局地或者局部地转化对比度极性,如果需要在任何状态下都能被识别,则应给参数Metric设置一个合适的值;

⑦ 物体是否与物体的其他实例重叠,如果需要在任何状态下都能识别物体,则应增加MaxOverlap值;

⑧ 判断是否在相同物体上找到多个匹配值,如果物体几乎是对称的,则需要控制旋转范围。

 

 

如何加快搜索匹配,需要在这些参数中进行合理的搭配,有以下方法可以参考:

 

① 只要匹配成功,则尽可能增加参数MinScore的值;

② 增加Greediness值直到匹配失败,同时在需要时减小MinScore值;

③ 如果有可能,在创建模板时使用一个大的NumLevels,即将图像多分几个金字塔级;

④ 限定允许的旋转范围和大小范围,在调用find_shape_model()时调整相应的参数;

⑤ 尽量限定搜索ROI的区域。

 

除上面介绍的以外,在保证能够匹配的情况下,尽可能的增大Greediness的值,因为在后面的实验中,用模板匹配进行视频对象跟踪的过程中,这个值在很大程度上影响到匹配的速度。

当然这些方法都需要跟实际联系起来,不同图像在匹配过程中也会有不同的匹配效果,在具体到某些应用,不同的硬件设施也会对这个匹配算法提出新的要求,所以需要不断地去尝试。

 

posted on 2019-09-09 16:17  xh6300  阅读(5817)  评论(5编辑  收藏  举报