Halcon模板匹配——各向同性比例缩放形状模板(超详细讲解)

需求

考虑以下这张图像,图片中有三个形状一样,但是尺寸大小不一样的图案。观察可以发现三个图案的有着各项同性比例缩放的关系。假如要采样模板匹配来识别出这三个图案该怎么做?Halcon提供create_scaled_shape_model()算子来解决这种场景。
在这里插入图片描述

算子函原型

create_scaled_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, ScaleMin, ScaleMax, ScaleStep, Optimization, Metric, Contrast, MinContrast : ModelID)

参数说明

Template :image类型,输入图像,其域将用于创建模型。

NumLevels:金字塔层的最大数目。
金字塔层的数量由参数NumLevels决定。 应该选择尽可能大的对象,因为这样寻找对象所需的时间就会大大减少。 另一方面,numlevel的选择必须保证模型仍然是可识别的,并且在金字塔的最高层次上包含足够数量的点(至少4个)。 这可以使用inspect_shape_model的输出进行检查。 如果没有生成足够的模型点,则内部减少金字塔层的数量,直到在最高金字塔层上找到足够的模型点。 如果这个过程将导致一个没有金字塔级别的模型,也就是说,如果最低金字塔级别上的模型点的数量已经太少,那么create_scaled_shape_model将返回一条错误消息。 如果NumLevels设置为’auto’(或为向后兼容设置为0),则create_scaled_shape_model自动确定金字塔级别的数量。 可以使用get_shape_model_params查询自动计算的金字塔级别数。 在极少数情况下,可能会出现create_scaled_shape_model决定金字塔级别数量的值太大或太小。 如果金字塔的层数选择的太大,可能会在图像中识别不出模型,或者可能需要在find_scaled_shape_model中为MinScore或Greediness选择非常低的参数来找到模型。 如果金字塔层数选择得太少,那么在find_scaled_shape_model中寻找模型所需的时间可能会增加。 在这些情况下,应该使用inspect_shape_model的输出来选择金字塔级别的数量。

AngleStart:图案的最小旋转角度。
AngleExtent:旋转角度的范围。
AngleStep:角度每次旋转的步长。
参数AngleStart和AngleExtent决定了可能的旋转范围,在这个范围内模型可以出现在图像中。 注意,该模型只能通过find_scaled_shape_model在这个角度范围内找到。 参数AngleStep确定所选角度范围内的步长。 因此,如果find_scaled_shape_model中没有指定亚像素精度,则该参数指定find_scaled_shape_model中角度可达到的精度。 AngleStep应该根据对象的大小来选择。 较小的模型在图像中没有很多不同的离散旋转,因此,对于较小的模型,应该选择较大的AngleStep。如果AngleExtent不是AngleStep的整数倍,则相应地修改AngleStep。为了确保find_scaled_shape_model返回的没有旋转角度值恰好为0.0的模型实例,可能的旋转范围被修改如下:如果没有正整数n使AngleStart加上n倍的AngleStep正好是0.0,则AngleStart减少最多到AngleStep,而AngleExtent增加到AngleStep。

ScaleMin:图案的最小缩放比例。
ScaleMax:图案的最大缩放比例。
ScaleStep:图案每次缩放的步长。
参数ScaleMin和ScaleMax决定了模型的可能尺度(尺寸)的范围。 1的比例对应于模型的原始大小。 参数ScaleStep确定所选范围内的步长。 因此,如果find_scaled_shape_model中没有指定亚像素精度,则该参数指定find_scaled_shape_model中尺度可实现的精度。 像AngleStep一样,ScaleStep应该根据对象的大小来选择。 如果scales的范围不是ScaleStep的整数倍,那么ScaleStep也会相应的修改。 为了确保find_scaled_shape_model返回的比例值不是精确为1.0的模型实例,可能的比例范围被修改如下: 如果没有正整数n使ScaleMin加上n倍的ScaleStep正好为1.0,那么ScaleMin将减少到ScaleStep, ScaleMax将增加,这样ScaleStep将增加可能的范围。

Optimization:生成模型时,可选的优化方法。
对于特别大的模型,通过将Optimization设置为不同于“none”的值来减少模型点的数量可能是有用的。 如果Optimization = ‘none’,则存储所有的模型点。 在所有其他情况下,点数的数量将根据Optimization的值而减少。 如果点数减少,可能需要在find_scaled_shape_model中将Greediness参数设置为更小的值,例如,0.7或0.8。 对于小型模型,模型点数量的减少不会导致搜索速度的加快,因为在这种情况下,通常需要检查更多的潜在模型实例。 如果Optimization被设置为’auto’, create_scaled_shape_model自动决定模型点数量的减少。

Metric:参数Metric决定了模型在图像中被识别的条
如果Metric = ’ use_polarity’,则图像中的对象和模型必须具有相同的对比度。 例如,如果模型是黑色背景上的一个明亮物体,那么只有当该物体也比背景亮时才会被发现。 如果Metric = ’ ignore_global_polarity’,如果对比度全局反转,该对象也会在图像中找到。 在上面的例子中,如果物体的颜色比背景深,物体也会被发现。 在这种情况下,find_scaled_shape_model的运行时间会略微增加。 如果Metric = ’ ignore_local_polarity’,即使对比局部发生变化,也会找到模型。 这种模式可以,例如,如果对象由一个具有中等灰度值的部分组成,其中有较暗或较亮的子对象。 因为在这种情况下,find_scaled_shape_model的运行时间显著增加,所以通常更好的做法是创建几个模型来反映create_scaled_shape_model对象可能的对比变化,并同时将它们与find_scaled_shape_model匹配。 以上三个指标只能应用于单通道图像。 如果使用多通道图像作为模型图像或搜索图像,则只使用第一个通道(并且不会返回错误消息)。 如果Metric = ’ ignore_color_polarity’,则即使颜色对比局部发生变化,也会找到该模型。 例如,如果对象的部分可以改变它们的颜色,例如,从红色到绿色。 特别是,如果事先不知道对象在哪些通道中是可见的,这种模式非常有用。 在这种模式下,find_scaled_shape_model的运行时间也会显著增加。 度量’ ignore_color_polarity’可以用于任意数量的通道图像。 如果它被用于单通道图像,它具有与’ ignore_local_polarity’相同的效果。 需要注意的是,对于Metric = ’ ignore_color_polarity’,使用create_scaled_shape_model创建的模型和使用find_scaled_shape_model搜索的通道数量可以不同。 例如,这可以用于从综合生成的单通道图像创建模型。 此外,应该注意的是,通道不需要包含光的光谱细分(像在一个RGB图像中)。 例如,通道也可以包含同一物体的图像,这些图像是通过从不同的方向照射物体而获得的。

Contrast:模板图像中匹配对象的对比度和可选地最小尺寸的阈值或迟滞阈值。
参数对比度决定了模型点必须具有的对比度。 对比度是测量物体与背景之间以及物体不同部分之间的局部灰度值差异的一种方法。 应该选择对比,以便只有模板的重要特征被用于模型。 对比度还可以包含具有两个值的元组。 在这种情况下,使用与edges_image中使用的迟滞阈值方法类似的方法对模型进行分割。 在这里,元组的第一个元素决定下限阈值,而第二个元素决定上限阈值。 有关迟滞阈值方法的更多信息,请参见hysteresis_threshold。 对比度可选地包含第三个值作为元组的最后一个元素。 这个值决定了基于组件的大小来选择重要模型组件的阈值,也就是说,如果组件的点数小于因此指定的最小尺寸,则会被抑制。 对于每个连续的金字塔水平,最小尺寸的阈值除以2。 如果小模型组件应该被抑制,但不应该执行迟滞阈值,但是必须在对比中指定三个值。 在本例中,可以简单地将前两个值设置为相同的值。 可以使用inspect_shape_model提前检查该参数的效果。 如果对比度设置为’auto’, create_scaled_shape_model自动确定上面描述的三个值。 或者,只有对比度(‘auto_contrast’)、迟滞阈值(‘auto_contrast_hyst’)或最小大小(‘auto_min_size’)可以自动确定。 其余未自动确定的值可以另外以元组的形式传递。 也允许各种组合:例如,如果传入[‘auto_contrast’,‘auto_min_size’],则对比度和最小大小都是自动确定的。 如果传入[‘auto_min_size’,20,30],则自动确定最小大小,同时将迟滞阈值设置为20和30,等等。 在某些情况下,可能会出现对比度阈值的自动确定不令人满意的情况。 例如,如果由于特定于应用程序的原因,应该包含或抑制某些模型组件,或者如果对象包含几个不同的对比,则应该首选手动设置这些参数。 因此,应该使用determine_shape_model_params自动确定对比度阈值,并在调用create_scaled_shape_model之前使用inspect_shape_model进行验证。

MinContrast :待搜索图像中匹配对象的最小对比度。
使用MinContrast,可以确定在find_scaled_shape_model执行的识别中,模型至少必须具有哪一种对比。 换句话说,这个参数将模型从图像中的噪声中分离出来。 因此,一个很好的选择是图像中由噪声引起的灰度值变化的范围。 例如,如果灰色值在10个灰度级别范围内波动,则MinContrast应设置为10。 如果模型和搜索图像使用多通道图像,并且参数Metric被设置为’ ignore_color_polarity’(见上文),一个通道中的噪声必须乘以通道数量的平方根来确定min对比度。 例如,如果在一个通道中,灰度值在10个灰度级别范围内波动,且图像是一个三通道图像,则MinContrast应该设置为17。 显然,MinContrast必须小于Contrast。 如果要在非常低对比度的图像中识别模型,则必须将min对比度设置为一个相应的小值。 为了保证find_scaled_shape_model稳健准确地提取出模型的位置和旋转,在严重遮挡的情况下也要识别出模型,MinContrast应略大于噪声造成的灰度值波动范围。 如果min对比度设置为“auto”,则根据模型图像中的噪声自动确定最小对比度。 因此,只有当识别过程中的图像噪声与模型图像中的噪声相似时,自动判断才有意义。 此外,在某些情况下,为了增加对遮挡的鲁棒性,增加自动确定的值是可取的(见上文)。 可以使用get_shape_model_params查询自动计算的最小对比度。

ModelID:ModelID是该模型的句柄,在后续调用find_scaled_shape_model时使用它

可选地,可以在Optimization中传递第二个值。 此值决定是否完全预生成模型。 为此,Optimization的第二个值必须设置为’pregeneration’或’no_pregeneration’。 如果第二个值没有被使用(即,如果只有一个值被传递),则使用set_system(‘pregenerate_shape_models’,…)设置的模式。 使用默认值(‘pregenerate_shape_models’ = ‘false’),模型不会完全预生成。 模型的完整预生成通常会导致稍低的运行时,因为模型不需要在运行时进行转换。 但是,在这种情况下,创建模型所需的内存需求和时间要高得多。 还应该注意的是,不能期望两种模式返回完全相同的结果,因为在运行时转换模型必然会导致转换模型的内部数据与预先生成转换模型的内部数据不同。 例如,如果模型没有完全预先生成,find_scaled_shape_model通常会返回稍低的分数,这可能需要为MinScore设置一个比完全预先生成的模型稍低的值。 此外,通过插值得到的位姿在两种模态中可能略有不同。 如果需要最大的精度,模型的位姿应确定最小二乘平差。
如果选择了完整的模型预生成,则为所选的角度和比例范围预生成模型并存储在内存中。 存储模型所需的内存与角度阶数、比例阶数和模型中的点数成正比。 因此,如果AngleStep或ScaleStep太小,或者AngleExtent或scale的范围太大,可能会发生模型不再适合(虚拟)内存。 在这种情况下,必须放大AngleStep或ScaleStep,或者缩小AngleExtent或缩放范围。 在任何情况下,都希望模型完全适合主内存,因为这避免了操作系统的分页,因此查找对象的时间将会小得多。 由于角度可以通过find_scaled_shape_model以亚像素分辨率确定,所以对于直径小于200像素的模型,可以选择AngleStep >= 1°和ScaleStep >= 0.02。 如果选择了AngleStep = 'auto’或ScaleStep = ‘auto’(或在两种情况下为向后兼容为0),则create_scaled_shape_model根据模型的大小分别自动确定合适的角度或缩放步长。 自动计算的角度和缩放步长可以使用get_shape_model_params查询。
如果一个完整的模型的预生成没有被选择,模型只被创建在参考姿态在每个金字塔水平。 在这种情况下,模型必须在运行时在find_scaled_shape_model中转换为不同的角度和比例。 因此,识别模型可能需要稍微多一点的时间。
请注意,预生成的形状模型是根据特定的图像大小定制的。 出于运行时的原因,不支持在同一模型的搜索过程中并行使用不同大小的图像。 在这种情况下,必须使用相同型号的副本,否则程序可能会崩溃!

实例讲解

1.读取图像

read_image (Image, 'green-dot')

2.blob分析,生成将创建模板的ROI

*二值化
threshold (Image, Region, 0, 128)
*连通域分割
connection (Region, ConnectedRegions)
*处于面积过滤
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 10000, 20000)
*填补区域
fill_up (SelectedRegions, RegionFillUp)
*膨胀
dilation_circle (RegionFillUp, RegionDilation, 5.5)
*ROi区域裁剪
reduce_domain (Image, RegionDilation, ImageReduced)

3.创建模板

create_scaled_shape_model (ImageReduced, 5, rad(-45), rad(90), 'auto', 0.8, 1.0, 'auto', 'none', 'ignore_global_polarity', 40, 10, ModelID)

4.获取模板XLD轮廓

get_shape_model_contours (Model, ModelID, 1)

5.转正XLD轮廓

*获取ROI的重心和角度
area_center (RegionFillUp, Area, RowRef, ColumnRef)
*计算仿射变换矩阵
vector_angle_to_rigid (0, 0, 0, RowRef, ColumnRef, 0, HomMat2D)
*对XLD轮廓仿射变换。
affine_trans_contour_xld (Model, ModelTrans, HomMat2D)

6.重新读取新的图像,进行模板匹配

read_image (ImageSearch, 'green-dots')
find_scaled_shape_model (ImageSearch, ModelID, rad(-45), rad(90), 0.8, 1.0, 0.5, 0, 0.5, 'least_squares', 5, 0.8, Row, Column, Angle, Scale, Score)

7.将搜索到的所有满足条件的XLD轮廓进行仿射变换

for I := 0 to |Score| - 1 by 1
    hom_mat2d_identity (HomMat2DIdentity)
    hom_mat2d_translate (HomMat2DIdentity, Row[I], Column[I], HomMat2DTranslate)
    hom_mat2d_rotate (HomMat2DTranslate, Angle[I], Row[I], Column[I], HomMat2DRotate)
    hom_mat2d_scale (HomMat2DRotate, Scale[I], Scale[I], Row[I], Column[I], HomMat2DScale)
    affine_trans_contour_xld (Model, ModelTrans, HomMat2DScale)
    dev_display (ModelTrans)
endfor

8.清除模型句柄

clear_shape_model (ModelID)

效果:

在这里插入图片描述

完整代码:

read_image (Image, 'green-dot')
threshold (Image, Region, 0, 128)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 10000, 20000)
fill_up (SelectedRegions, RegionFillUp)
dilation_circle (RegionFillUp, RegionDilation, 5.5)
reduce_domain (Image, RegionDilation, ImageReduced)
create_scaled_shape_model (ImageReduced, 5, rad(-45), rad(90), 'auto', 0.8, 1.0, 'auto', 'none', 'ignore_global_polarity', 40, 10, ModelID)
get_shape_model_contours (Model, ModelID, 1)
area_center (RegionFillUp, Area, RowRef, ColumnRef)
vector_angle_to_rigid (0, 0, 0, RowRef, ColumnRef, 0, HomMat2D)
affine_trans_contour_xld (Model, ModelTrans, HomMat2D)
read_image (ImageSearch, 'green-dots')
find_scaled_shape_model (ImageSearch, ModelID, rad(-45), rad(90), 0.8, 1.0, 0.5, 0, 0.5, 'least_squares', 5, 0.8, Row, Column, Angle, Scale, Score)
for I := 0 to |Score| - 1 by 1
    hom_mat2d_identity (HomMat2DIdentity)
    hom_mat2d_translate (HomMat2DIdentity, Row[I], Column[I], HomMat2DTranslate)
    hom_mat2d_rotate (HomMat2DTranslate, Angle[I], Row[I], Column[I], HomMat2DRotate)
    hom_mat2d_scale (HomMat2DRotate, Scale[I], Scale[I], Row[I], Column[I], HomMat2DScale)
    affine_trans_contour_xld (Model, ModelTrans, HomMat2DScale)
    dev_display (ModelTrans)
endfor
clear_shape_model (ModelID)```


猜你喜欢

转载自blog.csdn.net/weixin_44901043/article/details/123544462