打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
解决方案指导--匹配3

https://blog.csdn.net/qq_39025596/article/details/84860648

第三章

单个方法

现在,我们深入研究单个匹配方法,特别是以下几种

  • 基于灰度值的匹配(3.1节)
  • 基于关联的匹配(3.2节),
  • 基于形状的匹配(第64页3.3节),
  • 基于组件的匹配(第92页3.4节),
  • 局部变形匹配(111页3.5节),
  • 透视图可变形匹配(124页3.6节)和
  • 基于描述符的匹配(第136页3.7节)。

3.1 基于灰度的匹配

基于灰度值的匹配是一种经典的匹配方法,只有当对象内部的灰度值没有变化,并且没有缺失的部分和杂乱的情况下才可以使用。该方法可以处理对象的单个实例,这些实例可以在搜索图像中旋转显示。注意,对于几乎所有的应用程序,其他的方法,如基于关联的匹配或基于形状的匹配方法是首选的。非常慢的基于灰度值的经典匹配是首选的情况非常罕见,这种情况包括匹配必须是光照变化的。例如,必须找到一个彩色图案,并且搜索图像中物体的色相值不能偏离模板图像中物体的色相值,那么光照不变的方法可能不太合适,因为它们使用的是标准化的灰度值,即,它们计算的是灰度值之间的相对差异,而不是绝对值。

如果您的应用是必须应用基于灰度值的匹配的少数情况之一,那么该匹配包括以下步骤:

  • 如果期望对象只被转换而不被旋转,则使用create_template创建一个模型;如果对象必须在搜索图像中也处于旋转位置,则使用create_template_rot创建模型。
  • 使用best_match、best_match_mg、best_match_pre_mg、best_match_rot、best_match_rot_mg、fast_match或fast_match_mg在图像中搜索模型(查看下面操作符之间的差异)。
  • 通过算子clear_template清除内存中的模型。

注意,基于灰度值的匹配可以应用于不同的模式。实际上,在创建模型时,可以将参数灰度值设置为“original”“normal”“gradient”或“sobel”。对于照明变量匹配的参数必须设置为“original”。

搜索的基本操作符(best_match和fast_match)之间的主要区别在于输出类型。best_match返回最佳匹配的坐标,即每个图像中对象的单个位置(行、列),fast_match返回一个区域,该区域由参数MaxError指定的公差内匹配的所有点组成。

对于这两个基本操作符,都可以使用特定的变体。例如,best_match_mg和fast_match_mg分别像best_match或fast_match一样工作,但除此之外,搜索是在金字塔中进行的。使用best_match_rot和best_match_rot_mg可以在搜索图像中旋转对象(对于后者再次使用金字塔)。

在创建模型和在图像中搜索模型之间,

  • 通过将模型存储到write_template文件中,并从read_template文件中读取模型,
  • 使用adapt_template,模型可以适应图像的特定大小,
  • 可以在模型灰度值中添加偏移量,利用set_offset_template消除图像灰度值的变化
  • 使用set_reference_template可以更改模型的引用点。

3.2 基于相关性的匹配

另一种基于灰度值的方法是基于相关性的匹配。该方法使用归一化互相关来评估模型与搜索图像之间的对应关系。与传统的基于灰度值的匹配方法相比,该方法具有速度快的优点,可以同时补偿光照的加性变化和乘性变化。与基于形状的匹配不同,还可以找到形状变化较小、纹理较多或模糊图像中的对象(模糊图像中的轮廓消失,例如,由于散焦)。

以下部分显示

  • 基于相关性匹配的一个示例(3.2.1节)
  • 如何选择合适的ROI从参考图像中提取模板图像(第60页第3.2.2节),
  • ·如何创建合适的模型(第61页3.2.3节),以及
  • ·如何优化搜索(第62页3.2.4节)。

3.2.1 一个例程

在这一节中,我们将快速概述基于相关性的匹配过程。为了跟上例子的进程,启动HDevelop程序hdevelop\Matching\Correlation-Based\find_ncc_model_defocused.hdev,该例程证明了基于相关性的匹配对纹理和离焦的鲁棒性。

步骤1:选择参考图像中的对象

首先,在训练图像中,使用gen_rectangle1创建包含对象的区域。使用area_center查询该区域的中心。在后面的步骤中,需要将匹配结果与原始区域覆盖起来。然后,图像被缩小到感兴趣的区域。

  1. read_image (Image, 'smd/smd_on_chip_05')
  2. gen_rectangle1 (Rectangle, 175, 156, 440, 460)
  3. area_center (Rectangle, Area, RowRef, ColumnRef)
  4. reduce_domain (Image, Rectangle, ImageReduced)

步骤2:创建模型

缩小后的图像用于使用create_ncc_model创建NCC模型。该算子的结果返回新创建模型(ModelID)的句柄,然后可以使用该句柄指定模型,例如,在对操作符find_ncc_model的调用中。

  1. create_ncc_model (ImageReduced, 'auto', 0, 0, 'auto', 'use_polarity', \
  2. ModelID)

步骤3:再次找到该对象

现在,在循环中读取搜索图像,对于每个搜索图像,NCC模型将使用第35页2.4.2.1节中描述的仿射变换由模型的区域进行搜索和覆盖。注意,训练应用于聚焦图像,搜索应用于不同散焦的图像。然而,对象实例都已找到。图3.1显示了参考图像和一个散焦但找到的模型实例。

  1. for J := 1 to 11 by 1
  2. read_image (Image, 'smd/smd_on_chip_' + J$'02')
  3. find_ncc_model (Image, ModelID, 0, 0, 0.5, 1, 0.5, 'true', 0, Row, \
  4. Column, Angle, Score)
  5. vector_angle_to_rigid (RowRef, ColumnRef, 0, Row, Column, 0, HomMat2D)
  6. affine_trans_region (Rectangle, RegionAffineTrans, HomMat2D, \
  7. 'nearest_neighbor')
  8. dev_display (Image)
  9. dev_display (RegionAffineTrans)
  10. endfor

步骤4:销毁模型

当不再需要NCC模型时,使用clear_ncc_model销毁它。

clear_ncc_model (ModelID)

3.2.2选择模型ROI

作为基于相关性的匹配的第一步,必须按照描述选择指定模板图像的区域,例如,在第20页的2.1.1节中。该区域可以有任意形状,即它也可以包含孔或由几个没有连接的部分组成。因此,可以创建只包含对象的“健壮”部分的ROI。在大多数情况下,必须选择ROI,以便它也包含一些感兴趣的对象之外的像素,作为直接的环境(邻域)需要对象的邻域来获得模型。但是,如果对象本身包含足够的结构,可以独立于其轮廓识别,那么也可以选择比对象小的结构。然后,在不同的背景下也可以找到物体。注意,您可以使用子采样加快后面的搜索(请参见3.2.3.1节)。因此,ROI不应该太“薄”,否则它将在更高的金字塔级别上消失!根据经验,如果ROI是

像素宽,那么您是安全的。也就是说,8像素的宽度允许使用4个金字塔级别。在选择合适的ROI后,将缩小后的图像作为模板图像用于模型的创建。

3.2.3建立合适的NCC模型

从参考映像派生出模板映像后,可以使用create_ncc_model操作符创建NCC模型。在这里,我们将进一步了解如何调整相应的参数。特别是,你可以

  • 使用子采样通过调整参数NumLevels来加快搜索速度(章节3.2.3.1),
  • 通过调整参数AngleExtent, AngleStart和AngleStep在允许特定的方向范围(3.2.3.2节),
  • 并在后面的搜索中指定与模型相比较的像素,即,通过调整参数度量来指定对象的极性(章节3.2.3.3)。

对于参数NumLevels和AngleStep,您可以让HALCON自动建议值。这可以通过将create_ncc_model中的参数设置为值“auto”来实现;然后,如果需要知道这些值,可以使用get_ncc_model_params查询它们。或者在创建模型之前应用determine_ncc_model_params。然后,您可以根据建议得到自动确定的值的估计值,以便您仍然可以根据模型的实际创建修改它们。注意,这两种方法只返回大致相同的值,create_ncc_model返回的值更精确。

注意,在模型创建之后,仍然可以修改模型。在3.2.3.4节中,给出了检查和修改已经创建的模型的可能性。

3.2.3.1利用子采样加快搜索速度(NumLevels)

为了加快匹配过程,可以使用子采样(参见第30页的2.3.2节)。在这里,我们创建了一个图像金字塔,由原始的全尺寸图像和一组下采样图像组成。然后在不同的金字塔层次上创建和搜索模型。您可以通过参数NumLevels指定使用多少金字塔级别。我们建议HALCON通过指定值“auto”来选择合适的值。然后可以通过操作符get_ncc_model_params查询使用的值。

3.2.3.2允许一个方向范围(角度范围、角度开始、角度步长)

如果对象的旋转在搜索图像中可能发生变化,您可以指定允许的范围在参数角度范围中,这个范围的起始角在参数角度开始(单位:弧度)。我们建议尽可能限制允许的旋转范围,以加快搜索过程。在匹配过程中,在允许的范围内,按照参数搜索不长指定的步长,以不同角度搜索模型。如果选择“auto”值,HALCON自动选择最佳步长,通过确定图像中仍可识别的最小旋转来获得尽可能高的精度。在73页的3.3.3.3节中,对于基于形状的匹配给出了所有三个参数值的选择技巧。这些技巧也适用于基于关联的匹配。

3.2.3.3指定灰度值与模型的比较方式(度规)

参数Metric允许您指定极性,即,必须观察对比的“方向”。如果选择“use_polar”值,则会观察到极性,即搜索图像中的点必须与模型中对应的点具有相同的对比度方向。例如,如果模型是一个在黑暗背景上的亮物体,那么只有当该物体也比背景亮时,才能在搜索图像中找到该物体。您可以通过选择值来选择忽略全局极性“ignore_global_polarity”。在这种模式下,如果一个物体的对比度方向相反,也可以识别它,例如,如果你的物体可以在浅色背景上以黑色的形状出现,反之亦然。然而,灵活性是以稍微降低识别速度和降低鲁棒性为代价获得的。

3.2.3.4检查和修改NCC模型

要检查模型的当前参数值,可以使用get_ncc_model_params查询它们。如果在模型创建过程中使用了自动参数选择,或者模型是在另一个程序中创建的,使用write_ncc_model保存到文件中,并使用read_ncc_model在当前程序中从该文件读取,则可能需要这样做。此外,您可以使用get_ncc_model_origin查询模型原点的坐标。

创建模型之后,在搜索图像中的对象之前,可以进一步修改模型。特别是,您可以应用set_ncc_model_param来更改单个参数,并应用set_ncc_model_origin来更改模型的原点。后者不推荐,因为匹配结果的准确率可能会降低,基于形状的匹配在85页的3.3.4.7节有更详细的说明。

3.2.4优化搜索过程

实际匹配由find_ncc_model操作符执行。下面,我们将展示如何为该操作符选择合适的参数来适应和优化匹配任务。特别是,我们展示了如何

  • 将搜索空间限制在感兴趣的区域(3.2.4.1节),
  • 通过参数AngleStart和AngleExtent限制方向范围从而限制搜索空间 (3.2.4.2节),
  • 将搜索空间限制在对象与模型偏离的特定分数,即,通过参数MinScore指定对象的相似度(3.2.4.3节),
  • 通过调整参数NumMatches和MaxOverlap来搜索模型的多个实例(3.2.4.4节),
  • 通过调整参数SubPixel指定结果所需的精度(3.2.4.5节),
  • 限制搜索过程中的金字塔级别(NumLevels)数量(第64页3.2.4.6节)。

匹配结束时,必须使用clear_ncc_model从内存中清除模型和进一步缓冲的数据。如果您想要重用一个模型,您必须在从内存中清除它之前将它存储到一个文件中。然后,您可以再次从文件中读取它,详细信息见第28页2.2节。

3.2.4.1将搜索范围限制在感兴趣区

限制搜索空间从而加快匹配速度的明显方法是将find_ncc_model操作符应用于ROI,而不是整个图像。78页3.3.4.1节对基于形状的匹配进行了更详细的说明。对于基于关联的匹配,只需将find_shape_model替换为find_ncc_model。

3.2.4.2限制方向范围(AngleStart, AngleExtent)

在创建模型时,您已经指定了允许的方向范围(参见第61页的3.2.3.2节)。在调用find_ncc_model操作符时,可以使用参数AngleStart和AngleExtent进一步限制范围。如果可以通过其他信息来限制这些范围,这是很有用的,这些信息可以通过适当的图像处理操作来获得。在创建模型时使用更大范围的另一个原因可能是您希望将模型用于其他匹配任务。

3.2.4.3指定对象的相似性(MinScore)

参数MinScore指定必须作为匹配返回的潜在匹配的最小分数。分数是衡量匹配质量的一个数值,即,表示模型与搜索图像之间的对应关系或“相似性”。对于基于相关性的匹配,使用模式与图像之间的归一化互相关得到分数(公式参见参考手册find_ncc_model的描述)。为了加快搜索速度,应该选择尽可能大的MinScore值,但当然仍然要尽可能小,以保证搜索的成功

3.2.4.4搜索对象的多个实例(NumMatches、maxoverlay)

要在搜索图像中找到一个模型的多个实例,可以通过参数NumMatches选择返回匹配项的最大数量。此外,参数MaxOverlap指定实例可能重叠的程度。在82页的3.3.4.5节中,对基于形状匹配的相应参数进行了更详细的说明。在这里,给出了参数选择的技巧,这些技巧也适用于基于相关性的匹配。请注意,如果搜索并找到对象的多个实例,则参数行、列、角和分数包含元组。对于基于形状的匹配,如何访问这些结果在第89页的3.3.5.1节中有范例显示。

3.2.4.5指定所需精度(SubPixel)

参数SubPixel指定所找到的模型实例的位置和方向是以像素精度(亚像素设置为“false”)返回还是以亚像素精度(亚像素设置为“true”)返回。由于亚像素精度几乎和像素精度一样快,我们建议将亚像素设置为“真正的”。

3.2.4.6限制金字塔级别的数量(NumLevels)

您在创建模型时已经指定的参数NumLevels允许您在搜索过程中使用不同的(在大多数情况下是更严格的)值。通过将NumLevels的值设置为0,,使用创建模型时指定的值。

NumLevels还可以包含第二个值,这样您不仅可以指定用于搜索的最高金字塔级别,还可以指定最低金字塔级别。如果搜索是在比第一个金字塔级别(对应于原始的全尺寸图像)更高的金字塔级别上完成的,那么搜索将变得更快。另一方面,搜索的健壮性和准确性也会下降。

3.2.4.7通过set_ncc_model_param设置NCC模型参数“timeout”

如果应用程序要求搜索必须在特定时间内完成,可以使用set_ncc_model_param操作符设置参数“timeout”,以指定保证搜索结束后的最大时间周期,即,您可以使搜索可中断。但是请注意,对于中断的搜索不返回结果。此外,在设置超时机制时,搜索的运行时可能增加10%。

3.3 基于形状的匹配

基于形状的匹配不使用像素及其邻域的灰度值作为模板,而是通过轮廓的形状来描述模型。以下部分显示

  • 基于形状的匹配的一个例子(3.3.1节),
  • 如何选择合适的ROI从参考图像中提取模板图像(第67页第3.3.2节),
  • 如何创建合适的模型(69页3.3.3节),
  • 如何优化搜索(第77页3.3.4节),
  • 如何处理特定的基于形状的匹配的结果(第89页3.3.5节),以及
  • 如何适应相机方向的改变(91页3.3.6节)。

注意,对于基于形状的匹配,HDevelop Assistant是可用的,它可以帮助您配置和测试匹配过程,只需单击几下鼠标,并交互式地优化参数,以获得最大的匹配速度和识别率。此外,在选择模型ROI之前,可以利用它来准备参考图像。在HDevelop中如何使用Matching Assistant在HDevelop User’s Guide的第269页7.3节。

3.3.1 一个例子

在这一节中,我们将快速概述基于形状匹配的匹配过程。为了更便于进行这个例子,启动HDevelop程序solution_guide\matching\ first_example_shape_match.hdev,它在IC上定位打印。

步骤1:选择参考图像中的对象

获取参考图像后,第一个任务是创建包含该对象的区域。在示例程序中,使用运算符gen_rectangle1创建一个矩形区域。或者,也可以使用draw_rectangle1交互式地绘制区域,或者使用以前分割过程生成的区域。然后,只包含选定区域的图像,即,模板图像,是使用操作符reduce_domain创建的。结果如图3.2所示。

  1. Row1 := 188
  2. Column1 := 182
  3. Row2 := 298
  4. Column2 := 412
  5. gen_rectangle1 (ROI, Row1, Column1, Row2, Column2)
  6. reduce_domain (ModelImage, ROI, ImageROI)

步骤2:创建模型

使用create_shape_model操作符创建模型。在此之前,我们建议应用操作符inspect_shape_model,它可以帮助您找到适合模型创建的参数。

  1. inspect_shape_model (ImageROI, ShapeModelImages, ShapeModelRegions, 8, 30)
  2. create_shape_model (ImageROI, NumLevels, 0, rad(360), 'auto', 'none', \
  3. 'use_polarity', 30, 10, ModelID)

inspect_shape_model显示了两个参数的效果,特别是创建模型的金字塔级别的数量(NumLevels)和模型中必须包含的对象点的最小对比度(对比度)。结果,操作符inspect_shape_model返回所选金字塔级别上的模型点,如图3.2所示。因此,您可以检查模型是否包含描述感兴趣对象的相关信息。

在实际使用create_shape_model操作符创建模型时,您可以指定除了NumLevels和Contrast之外的其他参数。例如,您可以限制对象的角度范围(AngleStart和AngleExtent)以及创建模型的角度步长(AngleStep)。在参数Optimization的帮助下,可以减少模型点的数量,这在非常大的模型中非常有用。参数Metric允许您指定是否必须观察模型点的极性。最后,可以指定要与模型进行比较的搜索图像中对象点必须具有的最小对比度(MinContrast)。模型的创建将在69页的3.3.3节中详细描述。

因此,操作符create_shape_model返回新创建模型的句柄(ModelID),然后可以使用该句柄指定模型,例如,在对操作符find_shape_model的调用中。注意,如果使用HALCON的COM、. net或c++接口,并通过类HShapeModelX或HShapeModel调用操作符,则不会返回句柄,因为类本身的实例充当句柄。

如果允许搜索对象的方向和比例发生变化,那么必须使用create_scaled_shape_model或create_aniso_shape_model操作符来创建模型。然后,您可以使用与用于角度范围的参数相似的参数来描述允许的刻度范围。

步骤3:再次找到该对象

要在搜索图像中找到对象,只需要调用操作符find_shape_model。图3.3显示了其中一个示例图像的结果。

  1. for i := 1 to 20 by 1
  2. grab_image (SearchImage, FGHandle)
  3. find_shape_model (SearchImage, ModelID, 0, rad(360), 0.7, 1, 0.5, \
  4. 'least_squares', 0, 0.7, RowCheck, ColumnCheck, \
  5. AngleCheck, Score)
  6. endfor

除了前面提到的ModelID之外,find_shape_model还提供了进一步的参数来优化搜索过程。在创建模型时已经指定的参数AngleStart、AngleExtent和NumLevels允许您在搜索过程中使用更多的限制性值。通过对NumLevels使用值0,可以使用创建模型时指定的值。通过参数MinScore您可以指定模型的多少必须是可见的。0.5近似的值意味着模型的一半轮廓必须被找到。此外,您可以指定在映像中预期有多少个对象实例(NumMatches),以及在映像中可能有多少个对象实例重叠(MaxOverlap)。要以亚像素精度计算被发现对象的位置,参数SubPixel应设置为不同于“none”的值。最后,参数Greediness描述了使用的搜索启发式,范围从“安全但缓慢”(值0)到“快速但不安全”(值1)。如何优化搜索过程,详见第77页3.3.4节。

运算符find_shape_model返回在参数Row, Column和Angle中找到的每个对象实例的位置和方向,以及它们对应的Score。

如果使用find_scaled_shape_model或find_aniso_shape_model操作符(分别使用create_scaled_shape_model或create_aniso_shape_model创建模型后),则按比例返回所找到对象的比例,分别以scale或ScaleR和ScaleC返回。

步骤4:销毁模型

当不再需要形状模型时,使用clear_shape_model销毁它。

clear_shape_model (ModelID)

下面几节将更深入地介绍基于形状的匹配的各个步骤以及需要调整的参数。

3.3.2选择模型ROI

作为基于形状的匹配的第一步,必须像第20页2.1.1节所描述的那样选择指定模板图像的感兴趣区域。该区域可以有任意形状,即,它也可以包含孔或由几个没有连接的部分组成。因此,可以创建只包含对象的“健壮”部分的ROI。必须选择ROI,使其包含对象的所有突出结构,以及对象外部的一些像素,作为它们的直接环境(邻域)需要得到模型。此外,您可以使用子采样加快后面的搜索(请参阅第72页的3.3.3.2节)。因此,ROI不应该太“薄”,否则它将在更高的金字塔级别上消失!根据经验,如果ROI是

像素宽,那么您是安全的。也就是说,8像素的宽度允许使用4个金字塔级别。在选择合适的ROI后,将缩小后的图像作为模板图像用于模型的创建。

当参考图像中存在杂波时,使用基于形状的匹配时,还可以使用操作符inspect_shape_model通过附加的图像处理来改进交互式选择的ROI。这在HDevelop示例程序solution_guide\ matching\process_shape_model.hdev中显示,它定位图3.4中所示的箭头。

步骤1:选择箭头

在那里,围绕箭头创建了一个初始ROI,而不试图排除混乱(参见图3.4a)。

  1. gen_rectangle1 (ROI, 361, 131, 406, 171)
  2. reduce_domain (ModelImage, ROI, ImageROI)

步骤2:创建第一个模型区域

然后,通过inspect_shape_model检查这个ROI。

inspect_shape_model (ImageROI, ShapeModelImage, ShapeModelRegion, 1, 30)

图3.4b显示了不同参数值创建的形状模型区域的对比。正如您所看到的,您无法在不丢失箭头本身的特征点的情况下消除混乱。

步骤3:处理模型区域

这个问题可以通过利用操作符inspect_shape_model返回形状模型区域来解决。因此,您可以像处理任何其他区域一样处理它。消除杂乱的主要思想是使用形态运算符opening_circle,它消除了小区域。在此之前,必须调用操作符fill_up来填充箭头的内部部分,因为只有边界点是(原始)模型区域的一部分。

  1. fill_up (ShapeModelRegion, FilledModelRegion)
  2. opening_circle (FilledModelRegion, ROI, 3.5)

步骤4:创建最终模型

然后,获取的区域用于为成功定位所有箭头的匹配创建模型。图3.4c为处理区域、对应的感兴趣区域和最终的模型区域。

  1. create_shape_model (ImageROI, 3, 0, rad(360), 'auto', 'none', \
  2. 'use_polarity', 30, 15, ModelID)

3.3.3创建合适的形状模型

从参考图像派生出模板图像后,可以创建形状模型。需要注意的是,基于形状的匹配包含了不同的方法来寻找图像中的训练对象。根据所选择的方法,以下操作符之一用于创建模型:

  • create_shape_model为基于形状的简单匹配创建了一个模型,该匹配使用模板图像派生模型,并且不支持缩放。
  • create_shape_model_xld为简单的基于形状的匹配创建模型,该匹配使用XLD轮廓派生模型,不支持缩放。
  • create_scaled_shape_model为基于形状的匹配创建一个模型,该模型使用模板图像派生模型,并支持统一的缩放。
  • create_scaled_shape_model_xld为使用XLD轮廓导出的基于形状匹配的模型,它支持均匀缩放。
  • create_aniso_shape_model为基于形状的匹配创建一个模型,该模型使用模板图像派生模型,并支持各向异性缩放。
  • create_aniso_shape_model_xld为基于形状的匹配创建了一个模型,该模型使用XLD轮廓派生模型,并支持各向异性缩放。

注意,如果您从XLD轮廓导出模型,在第一次匹配之后,强烈建议使用set_shape_model_metric来确定模型的极性信息(详细信息请参阅第75页的3.3.3.5节和第25页的2.1.3.2节)。

在下面,描述的参数属于运算符create_scaled_shape_model(如果没有另外说明的话)。

正如“基于形状的匹配”这一名称所表明的,对象是通过形状来表示和识别的。有多种方法来确定或描述一个物体的形状。在这里,形状被提取出来选择相邻对比度超过某个阈值的所有点。通常,这些点是对象轮廓的一部分(参见第65页的图3.2)。在这里,我们将进一步了解如何调整相应的参数。特别是,你可以

  • 通过调整参数Contrast来指定哪些像素是模型的一部分(第71页3.3.3.1节),
  • 使用子采样加快搜索速度,即通过调整参数NumLevels,减少模型点数,即通过调整参数Optimization(第72页第3.3.3.2节),
  • 通过调整参数AngleExtent, AngleStart和AngleStep,来允许特定的方向范围(第73页第3.3.3.3节)
  • 通过调整ScaleMin、ScaleMax、ScaleStep等参数或相应的各向异性缩放参数,允许特定的缩放范围(第74页3.3.3.4节),
  • 通过调整参数MinContrast和Metric,在以后的搜索中指定与模型相比较的像素(第75页3.3.3.5节)。

请注意,在调整参数时,您也可以让HALCON协助您:

  • 应用inspect_shape_model:在创建模型之前,您可以将操作符inspect_shape_model应用到模板图像,以尝试参数NumLevels和Contrast的不同值。该操作符返回具有多个金字塔级别的形状模型的结果表示,因此允许您直观地检查感兴趣的对象是否由模型充分表示。如果几个参数值的组合不能得到令人满意的对象表示,则可能是模板图像,即模型的ROI选择不当。第19页2.1节描述了如何选择合适的ROI。
  • 使用自动参数建议:对于许多参数,可以使用HALCON建议的合适数值。您可以在create_shape_model(或者它的一个等价物)中设置相应的参数值'auto',或者使用determine_shape_model_params自动的决定从模板图像中确定形状模型的参数,然后分别决定是否使用形状模型的创建的建议值。注意,这两种方法都只返回近似相同的值,而create_shape_model(或其等效方法之一)返回更精确的值。

注意,在模型创建之后,仍然可以修改模型。在第77页的3.3.3.6节中,展示了检查和修改已经创建的模型的可能性。

3.3.3.1指定作为模型一部分的像素(Contrast)

对于该模型,被选择的像素点的对比,或者其灰度值与邻域像素点不同,或超过通过参数Contrast所指定的阈值,该参数设置通过调用create_shape_model或其等效值。为了得到一个合适的模型,对比度的选择应该包括对象的重要像素,即这些像素刻画了它的特征,并允许它从其他物体或背景中清晰地辨别出来。显然,模型不应该包含杂波,即,不属于该对象的结构。

在某些情况下,不可能找到一个单一的对比度值,既可以消除杂乱,又不能同时去除对象的某些部分。图3.5显示了一个示例。任务是为pad的轮廓创建一个模型。如果选择了完整的轮廓,模型还包含杂波(图3.5a)。如果去除杂乱,就会丢失轮廓的一部分(图3.5b)。

为了解决这一问题,参数Contrast提供了两种附加的方法:滞回阈值法和根据尺寸选择轮廓零件的方法。这两种方法都是通过指定一组值来进行Contrast,而不是指定单个值。

迟滞阈值(也请参阅操作符hysteresis_threshold阈值)使用两个阈值,一个较低的阈值和一个较高的阈值。对于该模型,首先选择对比度高于上阈值的像素。然后,添加对比度高于低阈值且与高对比度像素相连接的像素,这些像素可以直接连接,也可以通过对比度高于低阈值的另一个像素连接。该方法可以选择局部对比度较低的轮廓部分。回到使用pad的示例:正如您在图3.5 c中看到的那样,通过一个迟滞阈值,您可以为pad的完整轮廓创建一个模型,而不会造成混乱。下面的代码行显示了如何在元组中指定两个阈值:

inspect_shape_model (ImageReduced, ModelImages, ModelRegions, 2, [40,70])

消除杂乱的第二种方法是指定一个最小的尺寸,即,为轮廓组件的像素数。图3.5d显示了示例任务的结果。最小尺寸必须在元组的第三个元素中指定。如果您不想另外使用滞后阈值,您必须将前两个元素设置为相同的值:

inspect_shape_model (ImageReduced, ModelImages, ModelRegions, 2, [40,40,30])

消除杂乱的替代方法是修改ROI,如第67页的3.3.2节所述,或者创建一个合成模型(参见第24页的2.1.3.1节)。

请注意,您可以让HALCON通过为Contrast指定值“auto”来选择合适的值。如果您想指定三个对比度参数中的某些参数,并让HALCON确定其余的参数,请参阅参考手册了解详细信息。

3.3.3.2利用子采样和降点加快搜索速度(NumLevels, Optimization)

为了加快匹配过程,可以使用子采样(参见第30页的2.3.2节)。在这里,我们创建了一个图像金字塔,由原始的全尺寸图像和一组下采样图像组成。然后在不同的金字塔层次上创建和搜索模型。

您可以通过参数NumLevels指定使用多少金字塔级别。我们建议选择最高的金字塔层次,其中模型包含至少10-15像素,并且模型的形状仍然与对象的形状相似。

一个更简单的方法是让HALCON通过为NumLevels指定值“auto”来选择合适的值。然后可以通过操作get_shape_model_params查询使用的值。

通过参数Optimization可以进一步减少模型点。这可能有助于在特别大的模型中加速匹配。同样,我们建议指定值“auto”,让HALCON自己选择合适的值。请注意,无论您的选择,所有通过对比度标准的点都将显示,即,您无法检查哪些点是模型的一部分。

使用可选的第二个值,您可以指定模型是否完全为允许的旋转和缩放范围预生成(请参阅下面的部分)。默认情况下,模型不是预先生成的。您可以通过传递“预生成”作为优化的第二个值来预生成模型,从而可能加快匹配过程。但是,请注意,如果允许大范围的旋转和/或缩放,内存需求就会上升。另一个影响是创建模型的过程需要更多的时间。在大多数情况下,不建议预生成模型。

请注意,如果您想手动设置金字塔级别的数量,您可以使用操作符inspect_shape_model检查模板图像金字塔,例如HDevelop 程序 solution_guide\ matchtion_first_example_shape_match .hdev中所示。在调用inspect_shape_model之后,所选金字塔级别上的模型区域将在HDevelop’s Graphics Window中显示。你可以使用在线缩放(菜单项的Visualization>Zoom Window)更近距离的观察它们。操作符调用之后的代码行循环遍历金字塔,并确定模型至少包含15个点的最高级别。然后在对运算符create_shape_model的调用中使用该值。

  1. inspect_shape_model (ImageROI, ShapeModelImages, ShapeModelRegions, 8, 30)
  2. area_center (ShapeModelRegions, AreaModelRegions, RowModelRegions, \
  3. ColumnModelRegions)
  4. count_obj (ShapeModelRegions, HeightPyramid)
  5. for i := 1 to HeightPyramid by 1
  6. if (AreaModelRegions[i - 1] >= 15)
  7. NumLevels := i
  8. endif
  9. endfor
  10. create_shape_model (ImageROI, NumLevels, 0, rad(360), 'auto', 'none', \
  11. 'use_polarity', 30, 10, ModelID)

注意,操作符inspect_shape_model以图像元组的形式返回金字塔图像(数组)。可以像使用select_obj操作符的模型区域一样访问单个图像。请注意,对象元组以索引1开始,而控制参数元组以索引0开始。

3.3.3.3允许方向范围(AngleExtent, AngleStart, AngleStep)

如果对象的旋转在搜索图像中可能发生变化,您可以在参数AngleExtent中指定允许的范围和这个范围的起始角在参数AngleStart (单位:弧度)中。注意,旋转范围是相对于参考图像定义的,即,起始角为0,对应于物体在参考图像中的方向。因此,允许旋转到+/-5°,则在设置时,应该将开始角度设为-rad(5),角度范围设置为rad(10)。

注意,在搜索过程中调用find_shape_model操作符或其等效操作符之一时,可以进一步限制允许的范围(请参阅第79页的3.3.4.2节)。因此,如果您希望对需要不同角度范围的不同任务重用模型,那么在创建模型时可以使用较大的范围,在搜索时可以使用较小的范围。

如果对象(几乎)是对称的,则应该限制允许的范围。否则,搜索过程将在同一个对象上以不同的角度找到多个几乎同样好的匹配。哪个匹配(以哪个角度)被返回为最佳,因此可以从一个图像“跳转”到另一个图像。合适的旋转范围取决于对称性:对于十字形或正方形物体,允许的范围必须小于90°,对于矩形对象小于180°,对于圆对象则为0°(如图3.6)。

如果预生成模型(请参阅第72页),大范围的旋转也会导致高内存需求。因此,在这种特殊情况下,建议在模型创建过程中尽可能限制允许的旋转范围,以加快搜索过程。

在匹配过程中,在允许的范围内,按照参数AngleStep指定的步长,以不同角度搜索模型。如果你选择的值为‘auto’,HALCON将自动选择最优步长

来获取最佳精度通过确定图像中仍可识别的最小旋转。图3.7解释了底层算法:如果距离物体中心最远的点移动至少2个像素,则可以清楚地从原始图形中分辨出旋转后的十字形物体。因此,相对应的
通过下列计算得到:

为中心到物体边界的最大距离,
像素。对于一些模型,这种估计的角度步长仍然太大。在这些情况下,它自动除以2。

自动确定的角度步长

适用于大多数应用程序。因此,我们建议选择值“auto”。创建之后,可以通过操作符get_shape_model_params查询使用的值。通过选择一个较高的值,可以加速搜索过程,但代价是估计方向的精度降低。注意,对于非常高的值,匹配可能完全失败!

选择的AngleStep值不能偏离最优值太多

.注意,选择非常小的步长并不会增加角度精度!

3.3.3.4允许一定的比例范围(Scale*Min, Scale*Max, Scale*Step)

与方向范围类似,可以指定允许的缩放范围。你可以考虑两种形式的缩放:

  • 行、列方向相同比例(均匀缩放)
  • 行、列方向的不同比例(各向异性缩放)

对于均匀缩放,可以通过运算符create_scaled_shape_model指定ScaleMin、ScaleMax和ScaleStep。对于各向异性缩放,可以使用create_aniso_shape_model操作符,它有六个缩放参数,而不是上面的三个。

注意,在调用find_scaled_shape_model或find_aniso_shape_model操作符时,可以进一步限制允许的范围(请参阅第79页的3.3.4.2节)。因此,如果您想为需要不同规模范围的不同任务重用模型,那么您可以在创建模型时使用较大的范围,在搜索时使用较小的范围。

如果您预生成模型(请参阅第72页),那么大范围的缩放也会导致高内存需求。因此,在这种特殊情况下,建议在模型创建过程中尽可能限制允许的范围,以加快搜索过程。

请注意,如果您在大范围的范围内搜索对象,您应该创建基于大范围的模型,因为HALCON在比原始模型实例更大的范围内预计算模型实例时不能“猜测”模型点。另一方面,应该选择NumLevels,以使最高的级别包含足够的模型点,同时可以用于最小的比例。

如果您选择参数ScaleStep的值为“auto”(或各向异性缩放的等效值),HALCON将自动选择合适的步长,通过确定图像中仍可识别的最小尺度变化来获得尽可能高的精度。与角度步长相似(见第74页图3.7),如果距离物体中心最远的点移动至少2个像素,则缩放后的物体与原始物体可以清晰地分辨出来。因此,相应的改变

由下列计算得到:

为中心到物体边界的最大距离,
像素。对于一些模型,这种估计的尺度步长仍然太大。在这些情况下,它自动除以2。

自动确定的比例步长适用于大多数应用程序。因此,我们建议选择“auto”值。但是,通过选择一个较高的值,您可以加快搜索过程,但代价是估计标度的准确性降低。注意,对于非常高的值,匹配可能完全失败!

为ScaleStep选择的值不应该与最优值相差太多

.请注意,选择非常小的步长并不会提高缩放精度!

3.3.3.5指定与模型比较的像素(MinContrast, Metric)

由于效率的原因,模型包含了影响搜索过程的信息:使用参数MinContrast,您可以指定为了与模型进行比较,搜索图像中的某个点必须至少具有哪个对比度。该参数的主要用途是排除噪声,即,来自匹配过程灰度值波动。您可以让HALCON通过为MinContrast指定值“auto”来选择合适的值。由于该值是根据参考图像中的噪声估计的,因此只有当参考图像中的噪声存在时,自动参数选择才合适。如果使用不含噪声的合成模型,MinContrast将自动设置为0,必须手动设置为更高的值。注意,你能改在后边的步骤中改变MinContrast的值,通过使用set_shape_model_param (在第87页3.3.4.9节)。

参数Metric允许您指定极性有无和如何,即必须观察对比度的方向(见图3.8)。如果选择“use_polar”值,则会观察到极性,即,搜索图像中的点必须与模型中对应的点具有相同的对比度方向。例如,如果模型是一个在黑暗背景上的亮物体,那么只有当该物体也比背景亮时,才能在搜索图像中找到该物体。

您可以通过选择值“ignore_global_polar”来选择全局忽略极性。在这种模式下,如果一个物体的对比度方向相反,也可以识别它,例如,如果你的物体可以在浅色背景上以黑色的形状出现,反之亦然。然而,这种灵活性是以稍低的识别速度为代价获得的。

如果选择“ignore_local_polar”值,即使对比度在本地发生变化,也会找到该对象。这种模式可能是有用的,例如,如果对象由一个中等灰度值的部分组成,其中包含较暗或较亮的子对象。但是请注意,在这种模式下,识别速度和鲁棒性可能会急剧下降,尤其是在允许大范围旋转的情况下(见73页3.3.3.3节)。

如果选择值ignore_color_polar,就可以在彩色图像中执行匹配(或者,更一般地说,在多通道图像中)。一个例子是examples\hdevelop\Applications\Position-Recognition-2D\matching_multi_channel_yogurt.dev.

如果您是从XLD轮廓创建模型的,则没有关于模型极性的可用信息。因此,在创建模型时,Metric的值必须设置为“ignore_local_polar”。当第一次匹配成功时,您可以使用匹配结果来获得将轮廓投影到搜索图像上所需的转换参数(使用vector_angle_to_rigid)。然后,使用set_shape_model_metric操作符可以确定第一个搜索图像的极性,该图像用作极性的训练图像,并将匹配的度量设置为“use_polar”或“ignore_global_polar”。使用值“use_polarity”,即如果以下搜索图像与训练图像具有相同的极性,则搜索速度会更快,更健壮。一个例子是examples\hdevelop\Matching\Shape-Based\create_shape_model_xld.dev。注意,set_shape_model_metric仅对从XLD轮廓创建的模型!

3.3.3.6形状模型的检查和修改

如果您希望直观地查看已经创建的形状模型,可以使用get_shape_model_contours来获得在特定金字塔级别中表示模型的XLD轮廓。请注意,模型的XLD轮廓位于图像的原点,因此可能需要进行转换以获得适当的可视化(请参阅第35页的2.4.2节)。

要检查模型的当前参数值,可以使用get_shape_model_params查询它们。如果在模型创建过程中使用了自动参数选择,或者模型是在另一个程序中创建的,使用write_shape_model保存到文件中,并使用read_shape_model在当前程序中从该文件读取,那么这可能是必要的。另外,您可以使用get_shape_model_origin查询模型原点的坐标。

创建模型之后,在搜索图像中的对象之前,可以进一步修改模型。特别是,您可以应用set_shape_model_param来更改单个参数,并应用set_shape_model_origin来更改模型的原点。注意,后者并不期望新参考点的绝对位置作为参数,而是期望它到默认参考点的距离。也就是说,模型原点的值也可以变为负值,如[-20,-40]。但请注意,通过修改参考点,估计位置的准确性可能会下降(见第85页3.3.4.7节)。因此,如果可能,不应改变参考点。

3.3.4优化搜索过程

实际匹配由以下操作符之一执行:

  • find_shape_model应用于搜索单个模型的实例,且模型的实例在比例上没有变化、
  • find_shape_models应用于同时索多个模型的实例,且模型的实例在比例上没有变化则进行使用,
  • find_scaled_shape_model应用于搜索单个模型的实例,且允许统一的缩放比例,
  • find_scaled_shape_models应用于同时搜索多个模型的实例,且允许统一缩放比例,
  • 使用find_aniso_shape_model搜索单个模型的实例,且行和列的缩放比例不同,
  • 使用find_aniso_shape_models搜索多个模型的实例,且行和列的缩放比例不同。

下面,我们将展示如何为这些操作符选择合适的参数来适应和优化匹配任务。特别是,我们展示了如何

  • 将搜索空间限制在感兴趣的区域(3.3.4.1节),
  • 通过参数AngleStart, AngleExtent, ScaleMin和ScaleMax或相关参数来限制用于各向异性尺度搜索空间(第79页3.3.4.2节),
  • 将搜索空间限制在对象允许的遮挡的特定数量,即,通过参数MinScore指定对象的可见性(第80页3.3.4.3节),
  • 指定使用的搜索试探法,通过调整参数Greediness来决定trade thoroughness versus speed(第81页3.3.4.4节),
  • 通过调整参数NumMatches和MaxOverlap来搜索模型的多个实例(第82页第3.3.4.5节),
  • 通过调整参数ModelIDs同时搜索多个模型(第83页3.3.4.6节),
  • 通过调整参数SubPixel来指定结果所需的精度(第85页第3.3.4.7节),
  • 限制搜索过程的金字塔级别(NumLevels)的数量(第86页3.3.4.8节),
  • 通过set_shape_model_param操作符设置参数“timeout”和“min_contrast”(第87页第3.3.4.9节),
  • 优化匹配速度(第87页3.3.4.10节)。

注意,许多匹配方法只能用于在图像中搜索单个模型的单个实例,而基于形状的匹配还可以用于同时搜索多个模型的多个实例。

匹配结束时,必须使用clear_shape_model从内存中清除模型和进一步缓冲的数据。如果您想要重用一个模型,您必须在从内存中清除它之前将它存储到一个文件中。然后,您可以按照第28页2.2节的描述再次从文件中读取它。

3.3.4.1将搜索范围限制在感兴趣的区域

限制搜索空间的最明显的方法是将find_shape_model(或它的一个对等物)运算符应用于ROI,而不是整个图像。图3.9显示了这样一个示例。减少搜索空间可以在几行代码中实现。

步骤1:创建一个感兴趣的区域

首先,使用gen_rectangle1操作符创建区域(有关创建区域的更多方法,请参阅第20页的2.1.1节)。

  1. Row1 := 141
  2. Column1 := 159
  3. Row2 := 360
  4. Column2 := 477
  5. gen_rectangle1 (SearchROI, Row1, Column1, Row2, Column2)

步骤2:将搜索限制在感兴趣的区域

然后,使用reduce_domain运算符将每个搜索图像缩减到这个ROI。在这个例子中,使用这种方法,搜索速度几乎翻了一番。

  1. for i := 1 to 20 by 1
  2. grab_image (SearchImage, FGHandle)
  3. reduce_domain (SearchImage, SearchROI, SearchImageROI)
  4. find_shape_model (SearchImageROI, ModelID, 0, rad(360), 0.7, 1, 0.5, \
  5. 'interpolation', 0, 0.7, RowCheck, ColumnCheck, \
  6. AngleCheck, Score)
  7. endfor

注意,通过将搜索限制为ROI,实际上限制了模型参考点的位置,即,模型ROI的重心(见第21页的2.1.2节)。这意味着搜索ROI的大小与允许移动的范围相对应。例如,如果需要检测的对象在垂直方向上的移动范围为

个像素点,在水平方向上的移动范围为
个像素点,那么可以将ROI限制在尺寸为
的范围内。为了保证在较高的金字塔层次上进行正确的边界处理,我们建议扩大ROI在每个方向上
个像素点。因此,如果制定NumLevels=4,则可限制ROI的尺寸为
.

请注意,即使您使用set_shape_model_origin(不推荐)修改了引用点,也要修改原始引用点,即,模型ROI的中心点,在搜索过程中使用。因此,您必须始终指定相对于原始参考点的搜索ROI。

3.3.4.2限制方向和尺度范围(AngleStart, AngleExtent, ScaleMin,ScaleMax)

在创建模型时,您已经指定了允许的方向和尺度范围(参见第73页的第3.3.3.3节和第74页的3.3.3.4节)。当调用find_shape_model操作符或它的一个等价操作符时,您可以使用参数AngleStart、AngleExtent、ScaleMin和ScaleMax(或用于各向异性缩放的相应缩放参数)进一步限制这些范围。如果您可以通过其他信息来限制这些范围,例如通过适当的图像处理操作来获得这些信息,则该方法非常有用。

在创建模型时使用更大范围的另一个原因可能是,您还希望将模型用于其他匹配任务。

注意,如果用于创建模型的比例范围大于用于搜索的范围,则可能在搜索图像中找到模型,即使模型稍微超出了更受限制的比例范围。

3.3.4.3指定对象的可见性(MinScore)

使用参数MinScore可以指定模型的可见性。这种机制的一个典型用途是允许一定程度的遮挡,如图3.10所示:如果MinScore设置为0.7,就会找到安全环。

让我们仔细看看这个词“可见性”:当比较搜索图像与模型的一部分,匹配过程计算所谓的分数,这主要是衡量有多少模型点可以匹配到搜索图像中相应的点(从0到1)。一个模型点可能是“隐形的”,由于多种原因无法匹配:

  • 物体轮廓部分被遮挡,如图3.10所示。请注意,在默认情况下,如果在图像边框处裁剪对象,则不会找到它们。这个行为可以用set_system('border_shape_models','true')来更改。一个例子是examples\hdevelop\Applications\Position-Recognition-2D\matching_image_border.dev。注意,搜索的运行时间将在此模式下会增加。
  • 在创建模型时,部分轮廓的对比度低于参数MinContrast中指定的值(参见第75页的3.3.3.5节)。
  • 对比度的极性在全局或局部发生变化(见第75页3.3.3.5节)。
  • 如果物体变形,也包括相机以斜角观察场景,部分轮廓可能是可见的,但出现在错误的位置,因此不再适合模型。注意,如果设置参数'SubPixel' 到 'max_deformation',可能会找到变形对象(见第85页3.3.4.7节)。此外,如果增加的容差模式被激活,可能会发现变形或散焦的对象。对于最底层的金字塔必须负向指定NumLevels。 然后,返回仍然提供匹配的最低金字塔级别的匹配。在91页的3.3.6节中描述了如何处理由于倾斜相机视图而导致的透视变形的具体情况。

除了这些源于搜索图像的明显原因外,还有一些不那么明显的原因是匹配过程本身造成的:

  • 如第73页3.3.3.3节所述,HALCON预先计算了在允许的方向范围内的夹角模型。在搜索过程中,候选匹配将被解析到所有预先计算的模型实例。如果你选择的一个值对于参数AngleStep明显大于自动选择的最小值,如图3.11所示的效应可能发生:如果对象是两个预先计算的角度,远离中心的点与模型点不匹配,因此分数降低。当然,同样的推理也适用于参数ScaleStep及其各向异性标度的变体(参见第74页的3.3.3.4节)。

  • 另一个障碍是在72页第3.3.3.2节介绍的图像金字塔的使用:在将候选匹配与模型进行比较时,必须在每个金字塔级别上达到指定的最小分数。但是,在不同的级别上,得分可能有所不同,只有最低级别的分数在参数Score中返回。这有时会导致明显的矛盾情况,即必须将MinScore设置为显著低于结果Score。注意,如果没有将匹配跟踪到最低的金字塔级别,则可能会找到得分略低于MinScore的实例。

推荐:MinScore越高,搜索速度越快!

3.3.4.4彻底性交交换s速度(Greediness)

参数Greediness可以影响搜索算法本身,因此,以彻底性换取速度。如果选择值0,搜索就彻底了,即如果对象存在(在允许的搜索空间内,达到最小分值),将被找到。然而,在这种模式下,即使是非常不可能的匹配候选人也会被彻底检查,从而大大减缓匹配过程。

“贪心”搜索算法的主要思想是在看起来不太可能达到最低分数的情况下,中断候选人与模型的比较。换句话说,我们的目标不是把时间浪费在毫无希望的候选人身上。然而,这种贪婪可能带来不受欢迎的后果:在某些情况下,无法找到一个完全可见的对象,因为比较“一开始就出师不利”,因此被归类为无望的候选对象,并被中断。

您可以调整搜索的Greediness程度,即,通过选择0 (没有中断:彻底但缓慢)和1 (最早断开:快速但不安全)之间的值,来进行比较。注意,参数Greediness和MinScore相互作用,即,您可能必须指定一个较低的最低分数,以便使用贪婪搜索。通常情况下,你可以用高的贪婪和足够低的最低分数达到更高的速度。

3.3.4.5搜索对象的多个实例(NumMatches, MaxOverlap)

要搜索对象的多个实例,只需相应地设置参数NumMatches。运算符find_shape_model(或它的一个等效物)然后在参数Row, Column, Angle, Scale(或其各向异性比例的变体)和Score中以元组形式返回匹配结果。如果选择值0,则返回所有匹配项。

注意,搜索多个对象只比搜索单个对象稍微慢一点。

第二个参数MaxOverlap允许您指定两个匹配项可以重叠多少(作为一个分数)。在图3.12b中,例如,两个安全环重叠了大约0.2倍。然而,为了尽可能地加快匹配速度,重叠的计算既不针对模型本身,也不针对模型的ROI,而是针对其最小的周围矩形。在指定最大重叠时,必须记住这一点。在大多数情况下,因此需要更大的值(例如,比较图3.12b和图3.12d)。

图3.12e显示了一个“病态”的情况:虽然环本身没有重叠,但它们的外圆矩形在很大程度上重叠。不幸的是,这种影响是无法预防的。

3.3.4.6同时搜索多个模型(ModelIDs)

如果在单个映像中搜索多个模型的实例,当然可以多次调用find_shape_model、find_scaled_shape_model或find_aniso_shape_model操作符。但是一个更快的替代方法是使用find_shape_models、find_scaled_shape_models或find_aniso_shape_models操作符。这些算子期望得到相似的参数,但有以下不同:

  • 使用参数ModelIDs,您可以指定模型IDs的元组,而不是单个ID。与搜索多个实例时一样(请参阅82页的3.3.4.5节),匹配结果参数Row等返回元组值。
  • 输出参数Model显示每个找到的实例属于哪个模型。注意,参数本身并不返回模型IDs,而是返回元组中模型ID的索引ModelIDs(从0开始)。
  • 搜索总是在单个图像中执行。但是,通过传递一个图像元组(参见下面的示例),可以将搜索限制到每个模型的特定区域。
  • 您可以为每个模型指定相同的搜索参数例如AngleStart等,或者传递一个包含每个模型的单独值的元组。
  • 您还可以搜索多个模型的多个实例。如果您搜索独立于它们的类型(模型ID)的特定数量的对象,请在参数NumMatches中指定这个(单个)值。通过传递一个值元组,可以为每个模型单独指定要找到多少个实例。在这个元组中,可以将具体值与值0混合。元组[3,0],例如,指定返回第一个模型的最佳三个实例和第二个模型的所有实例。类似地,如果为MaxOverlap指定一个值,操作符将检查找到的实例是否被独立于其类型的任何其他实例重叠。通过指定一个值元组,每个实例只针对相同类型的所有其他实例进行检查。

本例HDevelop程序solutiontion_guide\matching\multiple_models.hdev使用算子find_scaled_shape_models来同时搜索图3.13所示的环和螺母。

步骤1:创建模型

首先,创建两个模型,一个用于圆环,一个用于螺母。然后使用assign操作符将两个模型IDs连接到一个元组中。

  1. create_scaled_shape_model (ImageROIRing, 'auto', -rad(22.5), rad(45), \
  2. 'auto', 0.8, 1.2, 'auto', 'none', \
  3. 'use_polarity', 60, 10, ModelIDRing)
  4. create_scaled_shape_model (ImageROINut, 'auto', -rad(30), rad(60), 'auto', \
  5. 0.6, 1.4, 'auto', 'none', 'use_polarity', 60, \
  6. 10, ModelIDNut)
  7. ModelIDs := [ModelIDRing,ModelIDNut]

步骤2:指定单个搜索ROIs

在本例中,圆环和螺帽出现在搜索图像的非重叠部分。因此,可以单独限制每个模型的搜索空间。如3.3.4.1节所述,搜索ROI对应的是允许移动的范围。因此,可以在示例中使用窄的水平ROI(见图3.13b)。

两个ROIs使用操作符concat_obj连接成一个区域数组(tuple),然后,使用运算符add_channels“添加”到搜索图像,即,每个区域对应的搜索图像灰度值被“绘制”。该运算符的结果是两个图像数组,它们都具有相同的图像矩阵。第一幅图像的域限制为第一个ROI,第二幅图像的域限制为第二个ROI。

  1. gen_rectangle1 (SearchROIRing, 110, 10, 130, Width - 10)
  2. gen_rectangle1 (SearchROINut, 315, 10, 335, Width - 10)
  3. concat_obj (SearchROIRing, SearchROINut, SearchROIs)
  4. add_channels (SearchROIs, SearchImage, SearchImageReduced)

步骤3:找到这两个模型的所有实例

现在,操作符find_scaled_shape_models应用于创建的图像数组。由于这两个模型允许不同的旋转和缩放范围,因此为相应的参数指定元组。相反,其他参数对这两个模型都是有效的。第90页的3.3.5.2节展示了如何访问匹配结果。

  1. find_scaled_shape_models (SearchImageReduced, ModelIDs, [-rad(22.5), \
  2. -rad(30)], [rad(45),rad(60)], [0.8,0.6], [1.2, \
  3. 1.4], 0.7, 0, 0, 'least_squares', 0, 0.8, \
  4. RowCheck, ColumnCheck, AngleCheck, ScaleCheck, \
  5. Score, ModelIndex)

3.3.4.7指定所需精度(SubPixel)

在匹配过程中,将候选匹配与模型在不同位置、不同角度、不同尺度的实例进行比较。对于每个实例,计算结果匹配分数。如果将参数SubPixel设置为“none”,得到的参数Row, Column, Angle, 和 Scale(或用于各向异性缩放的相应参数)包含最佳匹配的对应值。在这种情况下,位置的精度为1个像素,而方向和尺度的精度分别等于在创建模型时为参数AngleStep 和 ScaleStep(或各向异性尺度对应的参数)所选择的值(见3第73页.3.3.3节和第74页第3.3.3.4节)。

如果您将参数SubPixel设置为'interpolation',HALCON将检查最佳匹配周围相邻位置、角度和比例的匹配得分,并通过插值确定最大匹配值。利用这种方法,可以得到亚像素精度的位置估计(约能实现

像素)。估计方向和尺度的准确性取决于对象的大小,像参数AngleStep 和ScaleStep的最优值或相应的各向异性扩展参数(参见73页3.3.3.3节 和74页部分3.3.3.4节):尺寸越大,被确定的方向和尺度越准确。例如,如果中心与边界之间的最大距离为100像素,则通常以
的精度来指定方向。

推荐:由于插值非常快,在大多数应用程序中可以将SubPixel设置为'interpolation”。

当您将参数SubPixel设置为“least _squared”、“least_squares_high”或'least_squares_very_high',最小二乘调整被用来代替插值,导致更高的精度。但是,这种方法需要额外的计算时间。

有时,由于与模型相比,对象有轻微的变形,所以没有被发现,或者发现的准确率较低。如果您的对象很可能是变形的,您可以通过将SubPixel额外设置为“max_deformation”来允许模型发生几个像素的最大变形,“max_deformation”后面是允许变形的像素数。例如,如果您将SubPixel设置为“max_deformation 2”,搜索对象的轮廓可能与模型的形状相差最多两个像素。为了获得有意义的分数值并避免错误匹配,我们建议总是将变形余量与最小二乘调整相结合。注意,最大允许变形的最大值会增加运行时间和发现错误模型实例的风险,特别是对于小型模型。因此,应该选择尽可能小但尽可能高的值。

请注意,估计位置的精度可能会下降,如果你使用set_shape_model_origin修改参考点!这种效果在图3.14中得到了可视化:正如您在最右边的一列中看到的,估计的方向的不准确“移动”了修改的参考点,而原始参考点不受影响。由此产生的位置误差取决于多个因素,如参考点的偏移量和被发现物体的方向。需要记住的主要一点是,错误随着修改后的参考点与原始参考点的距离线性增加(比较图3.14中的两行)。

3.3.4.8限制金字塔级数(NumLevels)

您在创建模型时已经指定的参数NumLevels允许您在搜索过程中使用不同的(在大多数情况下是更严格的)值。通过将NumLevels的值设为0,则在搜索时NumLevels的值被指定为使用创建模型时的值。

NumLevels还可以包含第二个值,这样您不仅可以指定用于搜索的最高金字塔级别,还可以指定最低金字塔级别。如果搜索是在比第一个金字塔级别(对应于原始的全尺寸图像)更高的金字塔级别上完成的,那么搜索将变得更快。另一方面,搜索的健壮性和准确性也会下降。如果在质量较差的图像中也应该找到对象,例如,如果对象是散焦的、变形的或有噪声的,则可以通过负向指定第二个值来激活增加的容忍模式。然后,返回仍然提供匹配的最低金字塔级别的匹配。

3.3.4.9通过set_shape_model_param设置参数“min_contrast”和“timeout”

大多数参数是在创建形状模型时设置的。稍后还可以使用操作符set_shape_model_param设置两个参数。特别是,可以设置参数'min_contrast' 和 'timeout'。'min_contrast' 可以更改,例如,如果某些搜索图像的对比度太低。 'timeout'只能用set_shape_model_param设置,不能在模型创建过程中设置。使用它,您可以指定保证搜索结束的最大时间期限,即,您可以使搜索可中断。但是请注意,对于中断的搜索,不返回结果。此外,在设置超时机制时,搜索的运行时可能增加10%。这个在hdevelop\Matching\Shape-Based\set_shape_model_timeout.hdev例程中演示了如何使用超时机制。

3.3.4.10优化匹配速度

下面,我们将介绍如何通过两个步骤优化匹配过程。请注意,为了优化匹配,有一组来自您的应用中的测试图像非常重要在,物体出现在所有允许变化的位置,方向,遮挡,和照明。

步骤1:确保找到所有对象

在对速度参数进行优化之前,我们建议在所有测试图像中找到匹配成功的设置,即,以找到所有对象实例。如果使用默认值时情况并非如此,请检查以下情况之一是否适用:

对象是否夹在图像边界?
设置set_system('border_shape_models','true')(参见第80页3.3.4.3节)。

搜索算法“太贪婪”了吗?
正如第81页3.3.4.4节所述,在某些情况下,如果Greediness过高,则无法找到完全可见的对象。选择值0强制进行彻底搜索。

物体是否部分被遮挡?
如果对象应该在这种状态下被识别,则减少参数MinScore。

在金字塔的最高层匹配失败了吗?
如第80页3.3.4.3节所述,在某些情况下,即使最低等级的分数要高得多,在金字塔的最高等级的分数也达不到最低等级。通过减少对find_shape_model或其对等调用中的NumLevels来测试这一点。另外,减少MinScore。

这个物体的对比度低吗?
如果对象应该在这种状态下被识别,则减小参数的MinContrast(见第75页3.3.3.5节)。

对比度的极性是全局的还是局部的?
如果对象应该在这种状态下被识别,那么在创建模型时使用参数Metric的适当值(参见第75页的3.3.3.5节)。如果对象只有一小部分受到影响,那么最好减少MinScore。

对象是否与该对象的另一个实例重叠?
如果对象应该在这种状态下被识别,则增加参数MaxOverlap(见82页3.3.4.5节)。

在同一个对象上找到多个匹配项吗?
如果对象几乎是对称的,则限制第73页第3.3.3.3节所述的允许旋转范围,或减少参数MaxOverlap(参见第82页第3.3.4.5节)。

步骤2:调整有关速度的参数

匹配过程的速度取决于模型和搜索参数。更困难的是,搜索参数依赖于选择的模型参数。我们建议采取以下步骤:

  • 尽量提高MinScore,即,只要匹配成功。
  • 现在,增加Greediness直到匹配失败。尝试减少MinScore。如果这不能帮助恢复以前的值。
  • 如果可能,在创建模型时为NumLevels使用更大的值。
  • 第73页第3.3.3.3节和第74页第3.3.3.4节所述,尽可能限制旋转和缩放的允许范围。或者,在调用find_shape_model、find_scaled_shape_model或find_aniso_shape_model时调整相应的参数。
  • 如78页3.3.4.1节所述,将搜索限制在感兴趣的区域。
  • 确定该模型由多个具有明显的结构特征的轮廓点和轮廓线组成,与图像中的其他结构具有明显的区别。也就是说,在拍摄图像和准备模型时,您已经可以通过优先选择具有主导结构的较大模型,而不是具有弱结构的较小模型来显著影响搜索速度(参见第22页的2.1.2.2节和第30页的2.3.2节)。

以下方法更“危险”,即,如果选择不合适的参数值,匹配可能失败。

  • 只要匹配成功,就增加对比度。
  • 如果您正在搜索一个特别大的对象,通过参数Optimization通常有助于选择一个更高的点(请参阅第72页的3.3.3.2节)。
  • 只要匹配成功,就增加AngleStep(和相应的各向异性缩放参数ScaleStep)。
  • 如果匹配的速度比它的健壮性和准确性更重要,则终止在更高金字塔级别上的搜索,如第86页3.3.4.8节所述。

注意,对于上面描述的许多优化,您还可以使用HDevelop Matching Assistant作为辅助工具,指导您完成整个匹配过程的不同步骤。如何使用Matching Assistant在HDevelop User’s Guide(第269页7.3节)中进行了描述。

3.3.5使用基于形状匹配的具体结果

基于形状的匹配结果可以用于第33页2.4节中介绍的用于通用匹配的所有任务。此外,基于形状的匹配可以返回一个模型的多个实例,还可以同时处理多个模型。3.3.5.1和3.3.5.2节描述了如何使用这些特定的结果。

3.3.5.1处理多个匹配

如果搜索并找到该对象的多个实例,则参数Row, Column,Angle, 和Score包含元组。HDevelop示例程序solution_guide\matching\multiple_objects.hdev展示了如何在循环中访问这些结果。

步骤1:确定仿射变换

与匹配运动相对应的变换如第39页第2.4.3.1节所述。与搜索单个匹配不同,在这里,匹配的位置是通过循环变量从元组中提取的。

  1. find_shape_model (SearchImage, ModelID, 0, rad(360), 0.6, 0, 0.55, \
  2. 'least_squares', 0, 0.8, RowCheck, ColumnCheck, \
  3. AngleCheck, Score)
  4. for j := 0 to |Score| - 1 by 1
  5. vector_angle_to_rigid (0, 0, 0, RowCheck[j], ColumnCheck[j], \
  6. AngleCheck[j], MovementOfObject)
  7. affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, \
  8. MovementOfObject)

步骤2:使用转换

在本例中,转换还用于显示一个箭头,该箭头可视化了方向(请参阅图3.15)。为此,箭头的位置使用affine_trans_pixel进行转换,转换矩阵与XLD模型相同。正如第42页2.4.3.2节所述,必须使用affine_trans_pixel,而不能使用affine_trans_point_2d。

  1. affine_trans_pixel (MovementOfObject, -120, 0, RowArrowHead, \
  2. ColumnArrowHead)
  3. disp_arrow (WindowHandle, RowCheck[j], ColumnCheck[j], RowArrowHead, \
  4. ColumnArrowHead, 2)

3.3.5.2多模型处理

如83页3.3.4.6节所述,在同时搜索多个模型时,存储关于模型的信息是很有用的,即,以元组表示的XLD模型。下面的示例代码来自已经部分描述的hHDevelop程序solution_guide\matching\multiple_models.hdev,它使用find_scaled_shape_models操作符来模拟搜索第84页图3.13中描述的环和螺母。

步骤1:访问XLD模型

与这两个模型对应的XLD轮廓可以通过操作符get_shape_model_contours访问。

  1. create_scaled_shape_model (ImageROIRing, 'auto', -rad(22.5), rad(45), \
  2. 'auto', 0.8, 1.2, 'auto', 'none', \
  3. 'use_polarity', 60, 10, ModelIDRing)
  4. inspect_shape_model (ImageROIRing, PyramidImage, ModelRegionRing, 1, 30)
  5. get_shape_model_contours (ShapeModelRing, ModelIDRing, 1)
  6. create_scaled_shape_model (ImageROINut, 'auto', -rad(30), rad(60), 'auto', \
  7. 0.6, 1.4, 'auto', 'none', 'use_polarity', 60, \
  8. 10, ModelIDNut)
  9. inspect_shape_model (ImageROINut, PyramidImage, ModelRegionNut, 1, 30)
  10. get_shape_model_contours (ShapeModelNut, ModelIDNut, 1)

步骤2:将关于模型的信息保存在元组中

为了方便以后对形状模型的访问,XLD轮廓保存在元组中,与模型ID类似(请参阅83页的3.3.4.6节)。但是,在将XLD轮廓与操作符concat_obj连接起来时,必须记住XLD对象已经是元组,因为它们可能由多个轮廓组成!因此,要访问属于某个模型的轮廓,需要模型的轮廓数和连接后的元组中的起始索引。前者是使用操作符count_obj确定的。环的轮廓从索引1开始,螺帽的轮廓索引1加上环的轮廓数。

  1. count_obj (ShapeModelRing, NumContoursRing)
  2. count_obj (ShapeModelNut, NumContoursNut)
  3. ModelIDs := [ModelIDRing,ModelIDNut]
  4. concat_obj (ShapeModelRing, ShapeModelNut, ShapeModels)
  5. StartContoursInTuple := [1,NumContoursRing + 1]
  6. NumContoursInTuple := [NumContoursRing,NumContoursNut]

步骤3:访问找到的实例

如第89页3.3.5.1节所述,在多个匹配的情况下,输出参数Row等包含值的元组,这些值通常在循环中访问,使用循环变量作为元组的索引。在搜索多个模型时,会涉及到第二个索引:输出参数模型通过将对应模型ID的索引存储在参数ModelIDs中指定的ID元组中来指示匹配的模型属于哪个模型。这听起来可能令人困惑,但是可以在代码中以一种优雅的方式实现:对于每个找到的实例,模型ID索引用于从上面创建的元组中选择相应的信息。

如前所述,表示模型的XLD可以包含多个轮廓。因此,不能直接使用操作符select_obj访问它们。相反,属于模型的轮廓是通过操作符copy_obj选择的,指定连接的元组中模型的开始索引和轮廓的数量作为参数。请注意,copy_obj并不复制轮廓线,而是只复制相应的HALCON对象,这些对象可以看作是对轮廓线的引用。

  1. find_scaled_shape_models (SearchImageReduced, ModelIDs, [-rad(22.5), \
  2. -rad(30)], [rad(45),rad(60)], [0.8,0.6], [1.2, \
  3. 1.4], 0.7, 0, 0, 'least_squares', 0, 0.8, \
  4. RowCheck, ColumnCheck, AngleCheck, ScaleCheck, \
  5. Score, ModelIndex)
  6. for i := 0 to |Score| - 1 by 1
  7. Model := ModelIndex[i]
  8. vector_angle_to_rigid (0, 0, 0, RowCheck[i], ColumnCheck[i], \
  9. AngleCheck[i], MovementOfObject)
  10. hom_mat2d_scale (MovementOfObject, ScaleCheck[i], ScaleCheck[i], \
  11. RowCheck[i], ColumnCheck[i], MoveAndScalingOfObject)
  12. copy_obj (ShapeModels, ShapeModel, StartContoursInTuple[Model], \
  13. NumContoursInTuple[Model])
  14. affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, \
  15. MoveAndScalingOfObject)
  16. dev_display (ModelAtNewPosition)
  17. endfor

3.3.6适应相机方向的改变

如上所示,HALCON基于形状的匹配允许定位对象在图像中的位置和方向或比例发生变化。然而,基于形状的匹配会匹配失败,如果摄像机以斜角观察场景,即如果不是垂直地指向物体运动的平面,那么物体就会因透视投影而变形。更糟糕的是,失真会随着物体的位置和方向而改变。

在这种情况下,一方面可以在应用匹配之前对图像进行校正。这有三个步骤:首先,你必须校准相机,即,使用算符calibrate_cameras确定其位置和方向等参数(见Solution Guide III-C,第68页3.2节)。其次,使用校准数据通过运算符gen_image_to_world_plane_map创建映射函数,然后使用运算符map_image应用于图像(参见Solution Guide III-C,第91页3.4节)。

另一方面,您也可以使用未校准的透视图变形匹配。它的工作原理类似于基于形状的匹配,但已经考虑了模型的透视变形,并返回了一个投影变换矩阵(2D单应性),而不是一个由位置和方向组成的二维姿态。此外,还提供了一种校准过的透视变形匹配,该匹配必须应用摄像机校准,并得到物体的三维姿态。关于透视变形匹配的详细信息,请参阅124页的3.6节或解决方案指南 I,第113页的第9章,未校准的情况和解决方案指南III-C,第136页的4.6节校准的情况。

注意,如果对所有图像使用相同的透视图,那么在应用匹配之前对图像进行校正要比使用透视图变形匹配更快、更准确。但是如果需要不同的透视图,则必须使用透视图匹配。

3.4基于组件的匹配

基于组件的匹配是基于形状的匹配的扩展。与基于形状的匹配类似,基于组件的匹配提取轮廓并将其形状与之前创建的模型的形状进行匹配。但与基于形状的匹配不同,组件模型由多个组件组成,这些组件可以改变它们之间的关系,即,它们可以相对移动和旋转。在创建模型时,必须确定或指定可能的关系。注意,与基于形状的匹配不同,对于基于组件的匹配,大小不可以缩放。

定位可以相对移动的组件的任务比基于形状的匹配所需的过程要复杂一些。例如,不是单个ROI,而是多个ROI(包含初始组件)必须被选择或提取。此外,关系,即,模型组件之间可能的移动必须确定。对于概述,图3.16说明了基于组件的匹配所需的主要步骤。

有关详细信息,请参见以下部分

  • 基于组件的匹配的一个示例(3.4.1节),
  • 如何提取组件模型的初始组件(96页3.4.2节),
  • 如何创建合适的组件模型(第97页3.4.3节),
  • 如何应用搜索(106页3.4.4节),以及
  • 如何处理特定的基于组件的匹配的结果(110页3.4.5节)。

3.4.1一个例子

在本节中,我们将快速概述基于组件的匹配过程。启动HDevelop程序hdevelop\Applications\Position-Recognition-2D\cbm_bin_switch.hdev,它定位由两个组件组成的交换机实例,并确定每个找到的交换机的设置是“开”还是“关”。

步骤1:提取初始组件

首先,读取参考图像。它显示了一个设置为“on”的开关(参见图3.17,左)。由于它由两个可以相对移动的部分组成,因此创建了两个ROI。这些区域连接到一个元组(Initial Components)中,构建初始组件。

  1. read_image (ModelImage, 'bin_switch/bin_switch_model')
  2. gen_rectangle1 (Region1, 78, 196, 190, 359)
  3. gen_rectangle1 (Sub1, 150, 196, 190, 321)
  4. difference (Region1, Sub1, InitialComponents)
  5. gen_rectangle1 (Region2, 197, 204, 305, 339)
  6. gen_rectangle1 (Sub2, 205, 232, 285, 314)
  7. difference (Region2, Sub2, InitialComponent)
  8. concat_obj (InitialComponents, InitialComponent, InitialComponents)
  9. dev_display (ModelImage)
  10. dev_display (InitialComponents)

步骤2:训练组件之间可能的关系

然后,必须确定组件之间的关系。在这里,他们通过训练得到。另一种在实践中非常常见的方法是手动定义可能的关系(第99页3.4.2节)。对于训练,将读取一个训练图像(参见图3.17,右)。由于初始组件之间只有两个不同的关系是有效的(一个用于设置' on ',另一个用于设置‘off’),显示设置为“off”的单一训练图像,以及显示设置为“on”的参考图像,足以进行训练。如果两个以上的关系成立,则需要更多的训练图像。使用参考图像、初始组件、训练图像和控制训练的几个参数,将训练应用于train_model_components。

  1. read_image (TrainingImage, 'bin_switch/bin_switch_training_1')
  2. train_model_components (ModelImage, InitialComponents, TrainingImage, \
  3. ModelComponents, 30, 30, 20, 0.7, -1, -1, rad(25), \
  4. 'speed', 'rigidity', 0.2, 0.5, ComponentTrainingID)

步骤3:创建组件模型

如果训练结果令人满意,则可以创建组件模型。为了使模型不那么严格,在创建之前,使用modify_component_model将小公差添加到获得的关系中。

  1. modify_component_relations (ComponentTrainingID, 'all', 'all', 1, rad(1))
  2. create_trained_component_model (ComponentTrainingID, 0, rad(360), 10, 0.7, \
  3. 'auto', 'auto', 'none', 'use_polarity', \
  4. 'false', ComponentModelID, RootRanking)

当从训练组件中创建组件模型时,不再需要培训组件,可以使用clear_training_components销毁它们。

clear_training_components (ComponentTrainingID)

步骤4:找到组件模型并推导出相应的关系

现在,将读取搜索图像,并使用find_component_model搜索组件模型的实例。对于每个匹配,使用get_found_component_model查询各个组件及其关系。根据组件之间的角度,算子visualize_bin_switch_match可视化了找到的开关的设置。

  1. read_image (SearchImage, 'bin_switch/bin_switch_' + ImgNo)
  2. find_component_model (SearchImage, ComponentModelID, 1, 0, rad(360), 0, \
  3. 0, 1, 'stop_search', 'prune_branch', 'none', 0.6, \
  4. 'least_squares', 0, 0.85, ModelStart, ModelEnd, \
  5. Score, RowComp, ColumnComp, AngleComp, ScoreComp, \
  6. ModelComp)
  7. dev_display (SearchImage)
  8. for Match := 0 to |ModelStart| - 1 by 1
  9. get_found_component_model (FoundComponents, ComponentModelID, \
  10. ModelStart, ModelEnd, RowComp, \
  11. ColumnComp, AngleComp, ScoreComp, \
  12. ModelComp, Match, 'false', RowCompInst, \
  13. ColumnCompInst, AngleCompInst, \
  14. ScoreCompInst)
  15. dev_display (FoundComponents)
  16. visualize_bin_switch_match (AngleCompInst, Match, WindowHandle)
  17. endfor

步骤5:销毁组件模型

当组件模型不再需要时,使用clear_component_model销毁它。

clear_component_model (ComponentModelID)

下面几节将更深入地介绍基于组件的匹配的各个步骤以及需要调整的参数。

3.4.2提取初始组件

与基于形状的匹配不同,模型不是由单个ROI生成的,而是由包含模型初始组件的多个连接区域生成的,即,模型中可以相对移动和旋转的部分。初始分量可以通过不同的方法提取:

  • 如果组件是近似已知的,则可以手动选择相应的ROIs,并将其连接到一个元组中(3.4.2.1节)。
  • 如果初始组件未知,则可以使用运算符gen_initial_components派生潜在的候选组件(3.4.2.2节)。

3.4.2.1初始组件的手动选择

如果初始组件近似已知,则对于每个分量,即,对于感兴趣对象的每个可移动部分,人工选择ROI (ROI的选择请参阅第20页的2.1.1节)。然后,将所有初始组件的ROI连接到一个元组中。手动选择初始组件的示例已经在93页3.4.1节的示例中显示,最初的组件是由ROI构建的,ROI是为开关的两个部分选择的,这些部分允许更改它们的关系。

3.4.2.2初始构件的自动提取

如果初始分量未知,即,如果还不清楚对象的哪些部分可以相互移动,则必须自动推导出潜在的ROI。这一点在HDevelop示例程序hdevelop\Matching\Component-Based\cbm_label_simple.hdev中得到了体现。在那里,必须找到 ’best before’标签,并确定其组件之间的关系。单个组件还不知道,所以在第一步中,只选择一个包含完整标签的ROI(见图3.19,左),然后将图像的域缩小到这个区域,以获得一个模板图像。从这个模板映像中,使用gen_initial_components派生初始组件(见图3.19,右)。

  1. read_image (Image, 'label/label_model')
  2. gen_rectangle1 (ModelRegion, 119, 106, 330, 537)
  3. reduce_domain (Image, ModelRegion, ModelImage)
  4. gen_initial_components (ModelImage, InitialComponents, 40, 40, 20, \
  5. 'connection', [], [])
  6. dev_display (Image)
  7. dev_display (InitialComponents)

除了模板图像外,操作者还期望几个控制组件分段的参数的值,特别是描述从图像中提取轮廓所需的最小和最大对比度的参数,以及必须返回的连接轮廓的最小大小。这些参数与用于基于形状的匹配的参数类似(参见69页的3.3.3节)。此外,一些控制内部图像处理的通用参数是可以被调整的。HDevelop示例程序hdevelop\Matching\Component-Based\cbm_param_visual.hdev以实例说明了控制参数不同值的影响。在图3.20中,例如,显示了gen_initial_components对比度过低的结果。注意,对于基于组件的匹配,模型中只包含那些属于对象的结构比其他匹配方法更重要。否则,噪声产生的轮廓也会成为初始分量。

3.4.3创建合适的组件模型

当从参考图像中选择或提取初始组件时,在第二步中,可以创建组件模型。为了创建模型,必须知道组件之间的关系。因此,创建模型可以通过不同的方式来实现:

  • 如果组件之间可能的关系已经知道,那么可以直接使用create_component_model创建组件模型(3.4.3.1节)。模型组件之间的关系将在第100页的3.4.3.2节中详细讨论。
  • 如果不知道可能的关系,则必须从一组显示关系的所有可能变化的训练图像中得到它们(101页3.4.3.3节)。

如果模型是使用训练创建的,那么在训练和模型的最终创建之间,它可能是满足

  • 可视化不同的训练结果(第102页3.4.3.4节)或
  • 修改培训结果(第105页3.4.3.5节)。

创建模型之后,您可能希望这样做

  • 将创建的模型存储到文件中,以便您可以在另一个应用程序中重用它(第105页3.4.3.6节),或者
  • 从已经存在的模型中查询信息(106页3.4.3.7节)。

3.4.3.1从已知关系中创建模型

如果关系,即模型组件之间可能的移动是已知的,您可以直接使用create_component_model创建组件模型,它根据明确的指定组件和关系创建组件模型进行匹配。hdevelop\Matching\Component-Based\cbm_modules_simple.hdev是一个例子。图3.21所示的复合对象的独立模块之间的关系为用户所知。

在选择组件的ROIs并将其串联之后,将应用操作符create_component_model。

  1. read_image (ModelImage, 'modules/modules_model')
  2. gen_rectangle2 (ComponentRegions, 318, 109, -1.62, 34, 19)
  3. gen_rectangle2 (Rectangle2, 342, 238, -1.63, 32, 17)
  4. gen_rectangle2 (Rectangle3, 355, 505, 1.41, 25, 17)
  5. gen_rectangle2 (Rectangle4, 247, 448, 0, 14, 8)
  6. gen_rectangle2 (Rectangle5, 237, 537, -1.57, 13, 10)
  7. concat_obj (ComponentRegions, Rectangle2, ComponentRegions)
  8. concat_obj (ComponentRegions, Rectangle3, ComponentRegions)
  9. concat_obj (ComponentRegions, Rectangle4, ComponentRegions)
  10. concat_obj (ComponentRegions, Rectangle5, ComponentRegions)
  11. create_component_model (ModelImage, ComponentRegions, 20, 20, rad(25), 0, \
  12. rad(360), 15, 40, 15, 10, 0.8, [4,3,3,3,3], 0, \
  13. 'none', 'use_polarity', 'true', ComponentModelID, \
  14. RootRanking)

注意,模型组件的位置和角度的变化并没有明确的关系,而是传递给运算符。这些描述组件的运动是彼此独立,但他们的位置是相对于在参考图像中的。也就是说,如果要对搜索图像进行转换,使其完整的复合对象的位置和方向近似于在参考图像中,则各个组件可能与其对应的模型组件不同,在行方向上VariationRow/2像素,在列方向上VariationColumn/2像素,方向变差VariationAngle/2。如果将单个值传递给变化参数,则它们对所有组件都有效。如果传递元组值,则它们必须包含每个组件的值。在图3.22中说明了图3.21组件的变化。特别是,灰色箭头表示单个组件的参考点允许的移动范围,灰色矩形表示允许的旋转。操作符create_component_model从这些变化中自动派生组件之间的关系,并使用它们创建组件模型。

3.4.3.2搜索树和模型组件之间的关系

手动选择的变化显示了相对于他们在模板图像中的位置允许单个组件的移动和旋转 ,而关系显示了相对于参考组件,组件允许的移动和旋转。

可以使用算子get_component_model_tree采用搜索树查询这些关系。搜索树指定搜索组件的顺序以及它们之间的相对搜索方式。它取决于所选择的根组件,即,首先搜索的组件(如何选择根组件在第107页的3.4.4.2节中进行了描述)。用于计算单个组件之间关系的参考组件是搜索树中组件的前身。例如,在图3.23所示的示例程序复合模型的搜索树中,最左边的组件是根组件,这些组件是按照暗淡的灰色线指示的方向进行搜索的。

如果一个组件模型是通过具有多个训练图像的训练获得的(请参见3.4.3.3节),您还可以使用get_component_relations查询由培训挖掘的组件之间的关系。然后,不使用搜索树作为计算的基础。相反,用于计算组件之间关系的参考组件始终是所选的根组件。因此,两个操作符返回的关系存在显著差异。注意get_component_relations主要是用来评估训练成功之前创建相应的组件模型,而get_component_model_tree被应用于创建模型之后可视化用于实际匹配的搜索空间(参见102页3.4.3.4节 和104页图3.27)。
在这两种情况下,关系都以区域和数值的形式返回。特别是获得了以下资料:

  • 所有组件的参考点位置用小圆表示。相应的位置坐标数值在参数Row 和 Column中返回。
  • 除根组件外的所有组件的方向关系,即,其相对于各参考分量的方向变化,由各分量的平均相对位置出发的半径固定的圆扇区表示。对应的角度数值在参数Phi中返回。
  • 除根组件外的所有组件的位置关系,即,指定元件的参考点相对于其参考元件的参考点的运动用矩形表示。对应的数值是矩形的参数Length1、Length2、AngleStart和AngleExtent。

如果模型是由人工选择的变量创建的,则导出的关系具有一定的规律性。具体来说,每个矩形都与从上一个到搜索组件的视图近似正交,与该视图正交的矩形的宽度取决于角度变化和两个组件之间的距离。也就是说,随着组件之间距离的增加,矩形的宽度也会增加(参见第100页的图3.23)。对于下一节所描述的通过训练得到的模型,其行为是不同的,因为这些关系是通过训练图像中各分量之间的任意关系得到的,而不是通过规则变化得到的。因此,矩形的任意方向和大小也是可能的(参见104页的图3.27)。

3.4.3.3从训练图像中创建模型

如果这些关系不是明确已知的,则必须使用显示所需各种关系的训练图像来确定它们。

例如,在HDevelop示例程序中hdevelop\Matching\Component-Based\cbm_label_simple.hdev读取若干训练图像并将其连接到一个元组中(TrainingImages)。这些训练图像显示了已经引入的“best before”标签,其各个部分之间有不同的关系(参见第96页3.4.2.2节)。

  1. gen_empty_obj (TrainingImages)
  2. for Index := 1 to 5 by 1
  3. read_image (TrainingImage, 'label/label_training_' + Index)
  4. concat_obj (TrainingImages, TrainingImage, TrainingImages)
  5. endfor

对于组件和关系的训练,应用操作符train_model_components。训练由一组不同的参数控制,这些参数在Reference Manual中有详细的描述。在训练过程中,通过对初始组件进行聚类,得到模型组件。例如,如果您将第97页(右)中的图3.19中的初始组件与图3.24(右)中的模型组件进行比较,您将看到在所有培训图像中具有相同关系的初始组件被合并。

  1. train_model_components (ModelImage, InitialComponents, TrainingImages, \
  2. ModelComponents, 40, 40, 20, 0.85, -1, -1, rad(15), \
  3. 'reliability', 'rigidity', 0.2, 0.5, \
  4. ComponentTrainingID)
  5. dev_display (Image)
  6. dev_display (ModelComponents)

训练结束后,使用create_trained_component_model创建基于训练组件的组件模型。在创建之前,modify_component_relations用于向关系中添加较小的公差值,从而使模型不那么严格。创建之后,不再需要训练组件,因此将被销毁。

  1. modify_component_relations (ComponentTrainingID, 'all', 'all', 15, rad(5))
  2. create_trained_component_model (ComponentTrainingID, -rad(30), rad(60), 10, \
  3. 0.8, 'auto', 'auto', 'none', \
  4. 'use_polarity', 'false', ComponentModelID, \
  5. RootRanking)
  6. clear_training_components (ComponentTrainingID)

注意,gen_initial_components 在96页3.4.2.2节被引入用于自动创生用于模型的原始组件,他也可以用来测试不同控制参数的值ContrastLow,ContrastHigh,MinSize,他们必须被调整来训练模型组件。因此,对于组件模型的训练,可以使用类似于inspect_shape_model用于基于形状的匹配的操作符(参见69页3.3.3节)。

3.4.3.4可视化训练结果

使用train_model_components的训练返回最终的模型组件,并训练它们之间的关系。不同的训练结果可以被可视化。特别是,你可以看到

  • 特定图像中的初始组件或最终模型组件,
  • 各组件之间的关系
  • 搜索树。

要可视化所有最终模型组件、所有初始组件或特定图像的特定初始组件,可以应用操作符get_training_components。在那里,您可以在其他组件中指定是否需要查询模型组件、初始组件或特定初始组件以及在哪个图像中应该搜索到组件。除了数值结果(Row, Column,Angle, and Score),还可以返回初始组件或模型组件的轮廓,并可以可视化。

  1. et_training_components (ModelComponents, ComponentTrainingID, \
  2. 'model_components', 'model_image', 'false', \
  3. Row, Column, Angle, Score)
  4. dev_display (Image)
  5. dev_display (ModelComponents)

HDevelop示例程序hdevelop\Matching\Component-Based\cbm_param_visual.hdev展示了为基于组件的匹配提供的不同可视化和分析工具的使用。例如,在图3.25中,一个特定的初始组件(“best before”标签的第一个组件“B”)是从模板图像中获得的,而在图3.26中它是从训练图像中获得的。结果是不同的,因为在训练图像中,模糊性还没有得到解决。

要检查训练的质量,可以使用get_component_relations查询训练返回的组件之间的关系。如何解释返回的区域和数值,见第100页的3.4.3.2节。

  1. count_obj (ModelComponents, NumComp)
  2. for i := 0 to NumComp - 1 by 1
  3. get_component_relations (Relations, ComponentTrainingID, i, \
  4. 'model_image', Row, Column, Phi, Length1, \
  5. Length2, AngleStart, AngleExtent)
  6. dev_display (Relations)
  7. endfor

如果训练效果不理想,可以用不同的条件(不同的参数、不同的训练图像等)重复训练。如果训练令人满意,您可以创建组件模型。创建组件模型之后,您可以使用get_component_model_tree可视化搜索树和相应的重引用。也就是说,您可以可视化实际用于后续搜索的搜索空间(假设您为搜索树的可视化和搜索选择了相同的根组件)。

  1. create_trained_component_model (ComponentTrainingID, -rad(30), rad(60), 10, \
  2. 0.8, 'auto', 'auto', 'none', \
  3. 'use_polarity', 'false', ComponentModelID, \
  4. RootRanking)
  5. for i := 0 to |RootRanking| - 1 by 1
  6. get_component_model_tree (Tree, Relations, ComponentModelID, \
  7. RootRanking[i], 'model_image', StartNode, \
  8. EndNode, Row, Column, Phi, Length1, Length2, \
  9. AngleStart, AngleExtent)
  10. dev_display (Tree)
  11. dev_display (Relations)
  12. endfor

使用get_component_relations获得的训练结果的关系与使用get_component_model_tree创建的模型的关系的区别如图3.27所示。特别地,get_component_relations计算所有组件相对于根组件的关系,而get_component_model_tree计算单个组件相对于在搜索树中它们的前身的关系。

3.4.3.5修改训练结果

有时,训练返回的结果并不完全是想要的结果,因此需要修改。除了新的训练具有不同的参数或更合适的训练图像外,还有两种情况是训练后可以进一步修改的。特别是,您可以修改

  • 用于从初始组件派生模型组件的聚类
  • 模型组件之间的关系。

在训练过程中,刚性模型组件由初始组件通过一个聚类派生而来,该聚类通过参数AmbiguityCriterion、MaxContourOverlap和ClusterThreshold控制。在第一次培训之后,您可以应用inspect_clustered_components来测试这些参数的不同值。如果发现一组合适的值与第一次训练中使用的值不一致,可以使用cluster_model_components将新的值集添加到训练结果中,如HDevelop示例程序 hdevelop\Matching\Component-Based\cbm_param_visual.hdev所示。

除了对模型组件进行修改外,有时还可以改变模型组件之间的关系。这种修改可以与modify_component_relations一起应用,通常用于向关系中添加较小的公差值(参见图3.28),以降低匹配的严格程度。例子已经在93页的3.4.1节和101页的3.4.3.3节中显示。

3.4.3.6模型重用

通常,从搜索的模型(联机部分)中分离创建模型(脱机部分)是很有用的。然后,可以使用write_component_model将创建的组件模型存储到文件中。使用read_component_model,可以再次从文件中读取它,以便在线处理。此外,write_training_components可以用来将训练结果存储到文件中,read_training_components可以用来再次从文件中读取它们。

3.4.3.7模型查询信息

在匹配应用程序的不同步骤中,可能需要或适合从模型中查询信息。

训练结束后,如102页3.4.3.4节所述,可以查询不同的培训结果。特别是,您可以使用get_training_components查询特定图像中的初始组件或模型组件,以及使用get_component_relations查询训练结果中包含的模型组件之间的关系。

此外,可以使用第105页3.4.3.5节介绍的采用算子inspect_clustered_components进行训练来获得刚性模型组件。

创建模型之后,当从文件中读取已经存在的组件模型时,您可以使用get_component_model_tree查询搜索树和组件模型的关联关系。另外,您可以使用get_component_model_params查询模型的参数。返回的参数描述了返回实例必须具有的最小得分(MinScoreComp)、关于模型组件是否适合作为根组件的排序(RootRanking)以及单个组件的形状模型的句柄(ShapeModelIDs)。RootRanking可以为以后的搜索选择合适的根组件(见3.4.4.2部分)。可以使用单个形状模型的句柄,例如,使用get_shape_model_params查询每个组件形状模型的参数(请参阅69页的3.3.3节)。

3.4.4模型实例的搜索

实际匹配由操作符find_component_model执行。下面,我们将展示如何为该操作符选择合适的参数来适应和优化匹配任务。特别是,我们展示了如何

  • 将搜索空间限制在感兴趣的区域(3.4.4.1节),
  • 通过参数RootComponent指定根组件(章节3.4.4.2),
  • 通过参数AngleStartRoot和AngleExtentRoot限制根组件搜索的方向范围(章节3.4.4.3),
  • 通过参数MinScore指定对象的可见性(第108页3.4.4.4节),
  • 通过调整参数NumMatches和MaxOverlap来搜索模型的多个实例(第108页第3.4.4.5节),
  • 在没有通过参数找到组件的情况下,调整搜索行为IfRootNotFound、IfComponentNotFound和PosePrediction(第108页3.4.4.6节)和
  • 通过参数MinScoreComp、SubPixelComp、NumLevelsComp和GreedinessComp(第109页3.4.4.7节)调整内部应用的基于形状的匹配,该匹配用于搜索单个组件。

在匹配结束时,必须使用clear_component_model从内存中清除模型和进一步的缓冲数据。如果您想要重用一个模型,您必须在从内存中清除它之前将它存储到一个文件中。然后,您可以再次从文件中读取它,详情请参见28页2.2节.

3.4.4.1将搜索范围限制在感兴趣的区域

与基于相关性的匹配或基于形状的匹配类似,您可以限制根组件的搜索空间,从而通过将操作符find_component_model应用于ROI而不是整个图像来加快匹配。在78页的3.3.4.1节中更详细地解释了基于形状的匹配的相应步骤。对于基于组件的匹配,只需将find_shape_model替换为find_component_model。注意,尽管基于组件的匹配基于基于形状的匹配,但是您不能使用set_shape_model_origin修改模型组件的引用点。

3.4.4.2指定根组件(RootComponent)

组件模型的组件组织在一个搜索树中,该搜索树指定了搜索模型的各个组件的顺序(还请参阅第98页的3.4.3.1节)。也就是说,
首先,在参数RootComponent中指定的根组件在所有允许的位置和方向中搜索。然后,按照搜索树给出的顺序搜索其他组件。在此过程中,每个组件相对于搜索树中先前位置的组件进行搜索。因此,只需要根组件的完整搜索空间,而其他组件是递归搜索的。

作为根组件,应该选择最可能在搜索图像中找到的组件。另一个标准是搜索的运行时间,每个潜在的根组件都需要搜索。要获得具有最佳预期运行时间的根组件,只需将模型创建期间返回的根排序传递给参数RootComponent。

  1. find_component_model (SearchImage, ComponentModelID, RootRanking, \
  2. -rad(30), rad(60), 0.5, 0, 0.5, 'stop_search', \
  3. 'prune_branch', 'none', 0.6, 'least_squares', 4, \
  4. 0.9, ModelStart, ModelEnd, Score, RowComp, \
  5. ColumnComp, AngleComp, ScoreComp, ModelComp)

3.4.4.3限制根组件的方向范围(AngleStartRoot, An- gleExtentRoot)

根组件在AngleStartRoot和AngleExtentRoot指定的允许方向范围内进行搜索。我们建议尽可能限制允许的旋转范围,以加快搜索过程。如果需要,方向的范围将被裁剪到创建模型时指定的范围。

3.4.4.4指定对象的可见性(MinScore)

通过参数MinScore,您可以指定必须有多少组件模型是可见的,才能作为匹配返回。这类似于基于形状匹配的对应参数(见80页3.3.4.3节)。由于组件模型的可见性取决于所包含组件的可见性(参见109页的3.4.4.7部分),因此如果没有找到单个组件,请参阅3.4.4.6部分。

3.4.4.5搜索对象的多个实例(NumMatches, MaxOverlap)

通过参数NumMatches,可以指定应该返回的组件模型实例的最大数量。通过参数MaxOverlap,您可以指定姿态重叠的程度。这个参数是合适的,例如,拒绝组件模型的实例,这些实例仅在一个或几个组件的位置上不同于得分较高的实例。这两个参数与基于形状匹配的相应参数相似(见82页第3.3.4.5节)。

3.4.4.6针对没有找到组件的情况调整行为(IfComponentNotFound, IfRootNotFound ,PosePrediction)

有时由于遮蔽而找不到组件。例如,在HDevelop 例程hdevelop\Applications\Position-Recognition-2D\cbm_dip_switch.hdev中,在其中一个搜索图像中,发现了dip开关模型的两个实例,但是对于一个实例,一些组件被遮挡(参见图3.29)。也就是说,在调用find_component_model时,参数RowComp、ColumnComp、AngleComp、ScoreComp和ModelComp中返回的元素数量不符合预期组件的数量(考虑到在状态中发现的组件的数量)。在110页的3.4.5节中描述了如何检查缺少哪些找到的实例的特定组件。

在这里,我们将展示如何在没有找到组件的情况下调整搜索行为。特别是,你可以

  • 在没有找到根组件的情况下,调整搜索行为,
  • 在没有找到任何其他组件的情况下,调整搜索的行为
  • 调整是否应该忽略未找到的组件的位置和方向,或者是否应该根据找到的组件的位置和方向进行估计。

对于在搜索图像中没有找到根组件的情况,必须调整参数IfRootNotFound。如果参数设置为‘stop_search’,则搜索将中止,即,对于模型的这个实例,不搜索其他组件。如果它被设置为'select_new_root',其他组件将按照根排序给出的顺序进行测试。注意,后一个过程比中止搜索要慢得多。

如果没有找到至少一个其他组件,则必须调整IfComponentNotFound参数。它控制如何处理相对于未找到的组件进行搜索的组件。如果IfComponentNotFound设置为“prune_branch”,则不会搜索组件,因此也不会找到组件。如果设置为'search_from_upper',则会相对于另一个组件进行搜索。特别是,与搜索树中先前位置的组件不同,在未找到组件之前的组件将用作相对搜索的引用。如果IfComponentNotFound设置为“search_from_best”,则相对于期望相对搜索的运行时最少的组件来搜索组件。

对于没有找到所有组件的情况,您可以进一步选择是否2D位姿,即,只返回发现组件的位置和方向(PosePrediction设置为'none')或如果没有找到组件的位置和方向的值通过基于相邻组件估计得到(PosePrediction设置为“from_neighbors”)或发现所有组件(PosePrediction设置为“from_all”)。注意,如果返回一个估计的位置和方向,则ScoreComp的相应返回值为0.0。

3.4.4.7调整用于查找组件的基于形状的匹配(SubPixelComp ,MinScoreComp ,NumLevelsComp ,GreedinessComp)

对单个组件的内部搜索基于基于形状的匹配。因此,参数MinScoreComp、SubPixelComp、NumLevelsComp和greediesscomp对应用于基于形状匹配的参数MinScore、SubPixel、NumLevels和greediesscomp(见第77页第3.3.4节)。每个参数必须包含用于所有组件的单个值,或者值的数量必须与组件的数量相对应。NumLevelsComp的值数量也可以是组件数量的两到两倍。有关更多信息,请参考find_component_model的参考手册条目。

3.4.5使用基于组件的匹配的具体结果

组件模型的每个实例由几个组件组成,这些组件可以更改它们的空间位置。因此,基于组件的匹配结果要比基于形状的匹配结果复杂一些。特别是,返回的位置和方向并不包含模型每个找到的实例的单一值,而是包含所有返回组件的值。所有组件返回值的参数是RowComp、ColumnComp、AngleComp和ScoreComp。后者返回单个组件的得分。从中,可以得到组件模型(score)的每个找到的实例的得分。

为了知道哪个组件为找到的模型实例中的数组RowComp、ColumnComp、AngleComp和ScoreComp特定的位置索引,提供了参数ModelStart、ModelEnd和ModelComp。需要ModelStart和ModelEnd来了解返回了多少实例,以及返回的组件属于哪个实例。ModelComp需要知道返回了哪些特定组件,因此也需要知道没有找到哪些特定组件。

特别是,组件模型的返回实例的数量可以从元组ModelStart和ModelEnd的长度派生出来。在HDevelop示例程序hdevelop\Applications\Position-Recognition-2D\cbm_dip_switch.hdev中,对于109页图3.29所示的搜索图像,已经找到了两个模型实例,即,元组ModelStart和ModelEnd都由两个值组成。

元组的实际值表示引用组件模型的相同实例的元组RowComp、Colum- nComp、AngleComp和ScoreComp的索引位置的间隔。在示例程序中,ModelStart为[0,13],ModelEnd为[12,21]。也就是说,索引位置为0到12的值引用组件模型的第一个实例和索引位置的值13到21引用第二个模型实例。由于组件模型由13个初始组件组成,我们看到对于第一个模型实例,所有组件都已找到,而对于第二个模型实例,13个组件中只有9个被找到。

现在我们知道返回实例的数量,对于每个实例,我们知道返回组件的数量以及它们的位置、方向和得分。但是我们还不知道,对于第二个模型实例,模型的13个初始组件中缺少了哪一个。对于这个知识,我们需要参数ModelComp来指示找到了哪些特定组件(参见图3.30)。在这个例子中,ModelComp为[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,0,1,2,7,8,9,10,11,12]。也就是说,对于第一个模型实例,组件0到12,即组件模型的所有组件都已找到。对于第二个模型实例,已经找到组件0到2和组件7到12。因此,缺少组件3到6。

匹配完成后,可以使用get_found_component_model查询每个找到的模型实例的组件,这样就可以将结果可视化,如第109页图3.29和图3.31中的dip开关所示。除了通过将找到的组件的区域叠加在搜索图像上实现可视化之外,有时还可以应用其他特定于应用程序的可视化步骤。这里,例如,应用了结果的文本解释过程(visualize_bin_switch_match)。

  1. NumFound := |ModelStart|
  2. for Match := 0 to |ModelStart| - 1 by 1
  3. get_found_component_model (FoundComponents, ComponentModelID, \
  4. ModelStart, ModelEnd, RowComp, \
  5. ColumnComp, AngleComp, ScoreComp, \
  6. ModelComp, Match, 'false', RowCompInst, \
  7. ColumnCompInst, AngleCompInst, \
  8. ScoreCompInst)
  9. dev_display (FoundComponents)
  10. visualize_dip_switch_match (RowCompInst, ColumnCompInst, \
  11. AngleCompInst, RowRef, ColumnRef, \
  12. AngleRef, WindowHandle, Match)
  13. endfor
  14. clear_component_model (ComponentModelID)

3.5局部形变匹配

与基于形状的匹配类似,局部变形匹配提取轮廓,并将轮廓与之前创建的模型的形状进行匹配。但与基于形状的匹配不同,轻微的轮廓变形对于基于形状的匹配是不能够找到的,但对于局部变形匹配则可以返回变形结果。注意,物体的实际位置仅限于确定其位置,而方向和比例尺作为变形的一部分是相互连接的。

以下部分显示

  • 局部可变形匹配的一个示例(3.5.1节)
  • 如何选择合适的ROI从参考图像中提取模板图像(第116页第3.5.2节),
  • 如何创建合适的模型(第116页3.5.3节)
  • 如何优化搜索(第119页3.5.4节)
  • 如何处理特定于本地可变形匹配的结果(第122页3.5.5节)。

3.5.1一个例子

在本节中,我们将快速概述局部可变形匹配的匹配过程。启动HDevelop示例程序hdevelop\Matching\Deformable\find_local_deformable_model.hdev,该例子定位于不同变形的“MVTec”标识(见图 3.32)。

步骤1:准备模板

首先,准备好模板。特别是,create_mvtec_logo_broadened从图像中提取“MVTec”标识,并创建具有稍微宽一些的标识的综合图像。得到的彩色图像(图3.32,左)转换为灰度值图像,从中得到ROI,即,模板图像(图3.33,114页左)被导出。

  1. create_mvtec_logo_broadened (LogoImage, 0, 200, Width, Height)
  2. rgb1_to_gray (LogoImage, GrayImage)
  3. gen_rectangle1 (Rectangle, 82, 17, 177, 235)
  4. reduce_domain (GrayImage, Rectangle, ImageReduced)

步骤2:创建模型

然后使用模板图像通过create_local_deformable_model创建徽标的模型。模型的轮廓可以用get_deformable_model_contours查询,例如,用它覆盖稍后的匹配,以直观地检查变形(参见第112页的图3.32,右)。

  1. create_local_deformable_model (ImageReduced, 'auto', 0.0, 0.0, 'auto', 1, 1, \
  2. 'auto', 1, 1, 'auto', 'none', \
  3. 'use_polarity', 'auto', 'auto', [], [], \
  4. ModelID)
  5. get_deformable_model_contours (ModelContours, ModelID, 1)

步骤3:再次找到该对象

创建的模型用于在搜索图像中查找徽标实例。出于演示的目的,本例使用合成搜索图像来显示带有各种随机变形的徽标。再次将彩色图像转换为相应的灰度值图像(如图3.33中所示)后,使用find_local_deformable_model进行匹配。

  1. rgb1_to_gray (SearchImage, GrayImage)
  2. find_local_deformable_model (GrayImage, ImageRectified, VectorField, \
  3. DeformedContours, ModelID, 0, 0, 1, 1, 1, 1, \
  4. 0.5, 1, 1, 4, 0.9, ['image_rectified', \
  5. 'vector_field','deformed_contours'], \
  6. ['deformation_smoothness','expand_border', \
  7. 'subpixel'], [Smoothness,0,1], Score, Row, \
  8. Column)

默认情况下,操作符返回图像中对象的位置。使用ResultType参数,您还可以指定一些返回的图标对象。在示例程序中,所有可用的图标对象,即,一个修正版本的部分搜索图像,该图像对应于用于创建模型的ROI的边界框(见图3.33,对吧),描述匹配模型实例变形的向量场,和对变形模型实例的轮廓进行了查询。

步骤4:可视化变形

为了可视化发现的模型实例的变形,过程gen_warped_mesh创建一个规则的网格,并使用返回向量字段中包含的信息对其进行变形。为此,首先使用vector_field_to_real将矢量场转换为两个实值图像DRow和DCol。对于模型的每个点,或者更准确地说是包围框的模板图像周围的每个点,DRow包含相应的行坐标,DCol包含搜索图像的相对应列坐标。然后,创建一个具有模型大小的常规网格。水平和垂直网格线是使用tuple_gen_sequence和tuple_gen_const操作符在单独的循环中创建的。使用图像DRow和DCol,对于网格线的每个点,get_grayval_inline查询对应的“变形”点,即,搜索图像中该点的对应坐标。这些坐标用于创建表示变形的水平和垂直网格线的多边形。

  1. procedure gen_warped_mesh (VectorField, WarpedMesh, Step)
  2. gen_empty_obj (WarpedMesh)
  3. count_obj (VectorField, Number)
  4. for Index := 1 to Number by 1
  5. select_obj (VectorField, ObjectSelected, Index)
  6. vector_field_to_real (ObjectSelected, DRow, DCol)
  7. get_image_size (VectorField, Width, Height)
  8. for ContR := 0.5 to Height[0] - 1 by Step
  9. Col1 := [0.5:Width[0] - 1]
  10. tuple_gen_const (Width[0] - 1, ContR, Row1)
  11. get_grayval_interpolated (DRow, Row1, Col1, 'bilinear', GrayRow)
  12. get_grayval_interpolated (DCol, Row1, Col1, 'bilinear', GrayCol)
  13. gen_contour_polygon_xld (Contour, GrayRow, GrayCol)
  14. concat_obj (WarpedMesh, Contour, WarpedMesh)
  15. endfor
  16. for ContC := 0.5 to Width[0] - 1 by Step
  17. Row1 := [0.5:Height[0] - 1]
  18. tuple_gen_const (Height[0] - 1, ContC, Col1)
  19. get_grayval_interpolated (DRow, Row1, Col1, 'bilinear', GrayRow)
  20. get_grayval_interpolated (DCol, Row1, Col1, 'bilinear', GrayCol)
  21. gen_contour_polygon_xld (Contour, GrayRow, GrayCol)
  22. concat_obj (WarpedMesh, Contour, WarpedMesh)
  23. endfor
  24. endfor
  25. return ()

网格与变形后的logo轮廓一起显示,如图3.34所示。

  1. dev_display (SearchImage)
  2. dev_display (WarpedMesh)
  3. dev_display (DeformedContours)

返回的修正后的图像与模板图像之间的差异如图所示图3.35。

步骤5:销毁模型

当本地可变形模型不再需要时,使用clear_deformable_model销毁它。

clear_deformable_model (ModelID)

下面几节将更深入地介绍局部可变形匹配的各个步骤以及需要调整的参数。

3.5.2选择模型ROI

作为局部变形匹配的第一步,指定模板图像的感兴趣区域必须按照描述进行选择,例如,在第20页的2.1.1节中。该区域可以有任意形状,即,它也可以包含孔或由几个没有连接的部分组成。因此,可以创建只包含对象的“健壮”部分的ROI。必须选择ROI,使其包含对象的所有显著结构,同时也包含对象外部的一些像素,因为获取模型需要它们的直接环境(邻域)。此外,您可以使用子采样加快后面的搜索(请参见3.5.3.2节)。因此,ROI不应该太“薄”,否则它将在更高的金字塔级别上消失!根据经验,如果ROI是

个像素宽,那么您是安全的。也就是说,8像素的宽度允许使用4个金字塔级别。在选择合适的ROI后,将缩小后的图像作为模板图像用于模型的创建。

3.5.3建立合适的局部变形模型

从参考图像中导出模板图像后,可以创建局部变形模型。需要注意的是,局部形变匹配包含了不同的方法来寻找图像中的训练对象。根据所选择的方法,以下操作符之一用于创建模型:

  • create_local_deformable_model为使用模板图像为局部可变形匹配创建模型。
  • create_local_deformable_model_xld为使用XLD轮廓为局部可变形匹配创建模型。注意,在第一次匹配之后,强烈建议使用set_local_deformable_model_metric来确定模型的极性信息(详情见第25页第2.1.3.2节)。

在这里,我们将进一步了解如何调整相应的参数。特别是,你可以

  • 通过调整参数Contrast指定哪些像素属于模型的一部分(3.5.3.1节),
  • 使用子采样加快搜索速度,即,通过调整参数NumLevels,减少模型点个数,即,通过调整参数Optimization(3.5.3.2节),
  • 通过调整参数AngleExtent、AngleStart、AngleStep、ScaleMin、ScaleMax和ScaleStep(第118页3.5.3.3节),允许特定的方向和比例范围,
  • 通过调整参数,指定在以后的搜索中与模型进行比较的像素MinContrast和Metric(第118页3.5.3.4节),和
  • 在ParamName和ParamValue中调整一些额外的(通用的)参数,这只有在非常罕见的情况下才需要(第118页3.5.3.5节)。

请注意,在调整参数时,您也可以让HALCON协助您:

  • 使用自动参数建议:你可以让HALCON建议这些参数的合适的值,可以通过在算子中设置相应的参数值为'auto'用于创建模型中或者通过应用determine_deformable_model_params来从模板图像自动确定本地可变形模型值,然后分别决定是否使用建议值模型的建立。注意,这两种方法只返回大致相同的值,用于创建模型的操作符返回的值更精确。
  • 应用inspect_shape_model:由于局部形变匹配使用XLD轮廓来构建模型,这与基于形状的匹配类似,因此可以使用inspect_shape_model来尝试参数NumLevels和Contrast的不同值。该操作符返回具有多个金字塔级别的形状模型的结果表示,因此允许您直观地检查感兴趣的对象是否由模型充分表示。如果多个参数值的组合不能得到满意的对象表示,则可能是模板图像,即,模型的ROI选择不当。第19页2.1节描述了如何选择合适的ROI。

注意,在模型创建之后,仍然可以修改模型。在第119页的3.5.3.6节中,展示了检查和修改已经创建的模型的可能性。

3.5.3.1指定作为模型一部分的像素(Contrast)

对于该模型,这些像素被选择其对比度,即当调用create_local_deformable_model时,灰度值差超过参数Contrast指定的阈值。参数Contrast类似于基于形状匹配的对应参数,详见第71页3.3.3.1节。唯一不同的是,这里的小结构没有被抑制在对比度内,而是与单独的泛型参数“min_size”一起,后者是通过ParamName和ParamValue设置的,如3.5.3.5节所述。

3.5.3.2利用子采样和减少点来加速搜索(NumLevels, Optimization)

为了加快匹配过程,可以使用子采样(参见第30页的2.3.2节)。在这里,我们创建了一个图像金字塔,由原始的全尺寸图像和一组下采样图像组成。然后在不同的金字塔级别创建和搜索模型。

您可以通过参数NumLevels指定使用多少金字塔级别。通过参数Optimization可以进一步减少模型点。这可能有助于在特别大的模型中加速匹配。这两个参数与72页3.3.3.2节详细描述的基于形状匹配的对应参数相似。

3.5.3.3允许一定的方向(AngleExtent, AngleStart, AngleStep)和比例(Scale*Min, Scale*Max, Scale*Step)

与基于形状的匹配类似,可以使用AngleExtent, AngleStart, AngleStep,ScaleRMin, ScaleRMax, ScaleCMin, and ScaleCMax用于调整搜索模型的方向和缩放范围(参见73页的3.3.3.3节和74页的3.3.3.4节)。

注意,与基于形状的匹配所调整的范围不同,这里的参数可以相互预置,而不是作为搜索算法的一种建议,因此不是很严格。实际用于搜索的范围大于指定的范围,因此也可以找到指定范围之外的模型。实际使用范围由调整后的参数导出,进一步依赖于使用的金字塔层次以及模型和图像的内容。较大的范围用于处理典型的局部变形匹配的畸变。例如,对于模型的小变形,即使没有指定缩放范围,也可以找到模型,这使得搜索速度更快。

3.5.3.4指定与模型比较的像素(MinContrast, Metric)

参数MinContrast允许您指定搜索图像中的某个点至少必须具有哪个对比度才能与模型进行比较,而Metric允许您指定极性是否和如何,即,必须观察对比度的方向。

这些参数类似于75页3.3.3.5节中描述的基于形状匹配的相应参数。唯一的区别是,对于局部可变形匹配的Metric,允许观察模型子部分中的极性。子部分是一组相邻的模型点。对于局部形变匹配的不同计算,模型被分成一组大小近似相同的子部分(参见第130页3.6.3.5节)。当将Metric设置为“ignore_part_polar”时,不同的子部分可能有不同的极性,只要各个子部分中的点的极性相同。‘ignore_part_polar’是ignore_global_polar和ignore_local_polar之间的一种折衷,‘ignore_global_polar’不能处理局部变化的极性,ignore_local_polar需要非常精细的结构检查,从而大大减慢了搜索速度。

3.5.3.5调整通用参数(ParamName, ParamValue)

通常,不需要调整通过ParamName和ParamValue设置的泛型参数。但在少数情况下,它可能有助于调整模型子部分的分割,这是不同的计算局部变形匹配所需要的,或抑制模型轮廓的小连接组件。

子部分的尺寸可以通过将参数ParamName设置为“part_size”,ParamValue 设置为“small”,'medium', 或'big'来调整。模型轮廓的小连接部件可以通过将参数ParamName设置为“min_size”实现。在ParamValue中指定的相应数值描述了对象连接部分至少必须包含的点的数量,以便进行以下计算。这种效果对应于在参数对比范围内可以应用于基于形状匹配的小结构的抑制,如第71页3.3.3.1节所述。

3.5.3.6对局部变形模型进行检查和修改

如果您希望可视化地检查已经创建的可变形模型,可以使用get_deformable_model_contours来获得以指定金字塔级别表示模型的XLD轮廓。请注意,模型的XLD轮廓位于图像的原点,因此可能需要进行转换以获得适当的可视化(请参阅第35页的2.4.2节)。

要检查模型的当前参数值,可以使用get_deformable_model_params查询它们。如果在模型创建过程中使用了自动参数选择,或者模型是在另一个程序中创建的,保存到write_deformable_model文件中,并在当前程序中使用read_deformable_model从该文件中读取,那么这可能是必要的。另外,您可以使用get_deformable_model_origin查询模型原点的坐标。

创建模型之后,在搜索图像中的对象之前,可以进一步修改模型。特别是,您可以应用set_deformable_model_origin来更改其引用点。但与基于形状的匹配类似,在修改参考点时,估计位置的精度可能会降低(见85页3.3.4.7节)。因此,如果可能的话参考点不应更改。相反,应该从一开始就选择适合模型创建的ROI(参见第21页的2.1.2节)。

3.5.4优化搜索过程

实际匹配使用find_local_deformable_model。接下来,我们将展示如何选择合适的参数来适应和优化匹配任务。特别是,我们展示了如何

  • 将搜索空间限制在感兴趣的区域(3.5.4.1节),
  • 通过参数AngleStart、AngleExtent、ScaleMin、ScaleMax限制方向和尺度的范围来限制搜索空间(3.5.4.2节),
  • 将搜索空间限制在对象允许遮挡的特定数量,即,通过参数MinScore指定对象的可见性(章节3.5.4.3),
  • 指定使用的搜索启发式,即通过调整参数Greediness来确定彻底交换的速度(3.5.4.4节),
  • 通过调整参数NumMatches和MaxOverlap来搜索模型的多个实例(3.5.4.5节),
  • 限制搜索过程的金字塔级别(NumLevels)数量(页面3.5.4.6节),
  • 指定匹配应该返回的图标结果的类型(ResultType,第121页3.5.4.6节),
  • 并在ParamName和ParamValue中调整一些额外的(通用的)参数(第121页3.5.4.8节)。

匹配结束时,必须使用clear_deformable_model从内存中清除模型和进一步的缓冲数据。如果您想要重用一个模型,您必须在从内存中清除它之前将它存储到一个文件中。然后,您可以再次从文件中读取它,详情请参见28页2.2节.

3.5.4.1将搜索范围限制在感兴趣的区域

限制搜索空间从而加快匹配速度的最明显方法是将算子 find_local_deformable_model应用于ROI,而不是整个图像。相应的程序在78页的3.3.4.1节中详细解释了基于形状的匹配。对于局部可变形匹配,只需将find_shape_model替换为find_local_deformable_model。

3.5.4.2限制方向和尺度范围(AngleStart, AngleExtent,Scale*Min, Scale*Max)

在创建模型时,您已经为允许的方向和比例范围指定了一个建议(见第118页3.5.3.3节)。在调用find_local_deformable_model时,可以使用参数AngleStart, AngleExtent、ScaleMin和ScaleMax进一步限制这些范围。如果可以通过其他信息来限制这些范围,这是很有用的,这些信息可以通过适当的图像处理操作来获得。

在创建模型时使用更大范围的另一个原因可能是,您还希望将模型用于其他匹配任务。

3.5.4.3指定对象的可见性(MinScore)

使用参数MinScore可以指定模型的可见性。这种机制的一个典型应用是允许一定程度的遮挡。该参数类似于基于形状的匹配的对应参数,该参数在第80页的3.3.4.3节中有更详细的描述。

3.5.4.4交易彻底性vs速度(Greediness)

参数Greediness可以影响搜索算法本身,从而用足够的交易来换取速度。该参数类似于基于形状匹配的对应参数,该参数在第81页的3.3.4.4节中有更详细的描述。

3.5.4.5搜索对象的多个实例(NumMatches, MaxOverlap)

要搜索对象的多个实例,只需将参数NumMatches设置为希望找到的最大实例数。如果选择值0,则返回所有匹配项。

定位多个实例,操作符find_local_deformable_model返回连接在输出元组中的单个模型实例的结果(还请参阅124页的3.5.5.4节)。注意,对多个对象的搜索只比对单个对象的搜索稍微慢一点。

第二个参数MaxOverlap允许您指定两个匹配项可以重叠多少(作为一个分数)。该参数类似于82页3.3.4.5节中描述的基于形状匹配的对应参数。

3.5.4.6限制金字塔级别(NumLevels)的数量

您在创建模型时已经指定的参数NumLevels允许您在搜索过程中使用不同的(在大多数情况下是更严格的)值。通过使用值0设置参数NumLevels,而在搜索时使用创建模型时指定的值。

3.5.4.7指定匹配返回的图标对象(ResultType)

默认情况下,每一次匹配都会返回一个位置和一个分数。如果您还想获得一些标志性的结果,可以将ResultType参数设置为“image_rec”、“vector_field”和“deformed_contours”。使用“image_rec”,您将得到搜索图像中与用于创建模型的ROI (rec-)的包围框相对应的部分的校正版本,使用“vector_field”可以得到描述匹配模型实例(VectorField)变形的向量字段,使用“deformed_contours”可以得到变形模型实例(DeformedContours)的轮廓。个别结果类型将在3.5.5节中详细介绍。

3.5.4.8调整通用参数(ParamName, ParamValue)

除了与基于形状的匹配所使用的参数或多或少对应的参数外,局部变形匹配还允许调整一些通过ParamName和ParamValue设置的通用参数。通常,不需要调整它们。但是,如果匹配的精度足够低,则可以通过降低或停用亚像素精度,或通过更改模型创建过程中设置的方向或比例的离散化步骤来加速匹配。

此外,您可以调整变形的预期“smoothness”。特别是,如果变形在局部发生变化,即,如果期望变形在一个较小的邻域内是相当不同的,那么'deformation_smooth '的值可能被设置为一个较小的值,而对于期望变形之间具有“平滑”转换的对象,该参数可能被设置为一个较高的值。

此外,您还可以扩展可选返回的校正图像的边界(请参阅3.5.4.7节)。默认情况下,被修正的搜索图像部分对应于用于创建模型的ROI的包围框。如果需要更大的部分,例如,如果搜索图像中可见的相邻部分也需要进一步处理图像,则可以分别使用参数'expand_border'、'expand_border_top'、'ex pand_border_bottom'、'expand_border_left'或'expand_border_right'来扩展经过修正的图像的边界。例如,在示例程序中,如果模型中只包含字母“MVT”,而还需要字母“ec”,那么参数“expand_border_right”可以设置为50,以将图像部分扩展50像素。注意,校正仅对与模型ROI对应的图像部分可靠,对于搜索图像中的邻近部分是通过一种推断方法得到的。因此,扩展边界越大,对图像边界的结果越不准确。

有关更多信息,请参考参考文献手册中find_local_deformable_model的描述。

3.5.5使用局部形变匹配的具体结果

局部变形匹配的结果与其他匹配方法不同。虽然它也返回位置和分数,但它不返回方向,甚至不返回刻度。相反,可以返回一组图标对象,以帮助检查找到的对象实例的变形。根据选择的ResultType值,返回以下图标对象:

  • RectifiedImage:搜索图像中与用来创建模型的ROI的包围框相对应的经过修正的部分(章节3.5.5.1)。
  • VectorField:描述模型实例变形的向量场(3.5.5.2节)。
  • DeformedContours:变形模型实例的轮廓(章节3.5.5.3)。

与基于形状的匹配类似,局部变形匹配可以返回模型的多个实例。如何使用这些多个实例见第135页的3.6.5.1节。

3.5.5.1整流图像

可以由局部变形匹配返回的第一个图标对象是搜索图像中与用于创建模型的ROI的包围框相对应的经过修正的部分(见图3.36)。

如第一个例子所介绍,它可以用来表示校正后的图像与参考图像的相应部分之间的区别(见第112页3.5.1节)。另一种用途可能是需要对图像进行进一步的处理。注意,如果需要对搜索图像进行更大的部分进行进一步处理,则有可能扩展ImageRectified的边界如第121页3.5.4.8节所述。

3.5.5.2向量场

匹配返回的另一个图标对象是可以使用的向量场,例如,可视化变形。为此,可以将VectorField转换为网格,如第一个示例(第113页)所示。注意,直接显示矢量场是不合理的,与光流返回的矢量场相比,不返回相对坐标,而是绝对坐标。特别是,optical_flow_mg返回的向量场描述了这些点从一个图像到另一个相同大小的图像的相关运动。可以用vector_field_to_real查询的向量字段的组件包含每个点在行和列方向上的相对移动。相反,通过局部变形匹配返回的向量场描述了模型上点的运动,或更准确地说,从包围模板图像的边框框到通常大于模型的搜索图像。因此,向量场不包含每个点的相对运动,而是包含每个模型点对应的搜索图像的绝对坐标。

除了可视化的目的,矢量场还可以用来得到一个校正图,它也可以用于其他应用。例如,如果模型实例的变形不是来自变形的对象,而是来自严重的摄像机畸变,则可以使用返回的向量场来补偿其他图像中的摄像机畸变。为此,模型必须是一个合成模型(请参阅第23页的2.1.3节),或者必须从使用相机拍摄的图像中创建,并且没有明显的畸变。然后,扭曲的摄像机生成的搜索图像中的匹配返回的向量场可以转换为带有convert_map_type的映射。然后,这张地图可以用来校正用同一相机拍摄的其他图像。

3.5.5.3变形轮廓

最后,可以返回变形轮廓。与模型轮廓相似,DeformedContours可以用于可视化目的(见图3.37),也可以用于可视化检查模型和找到的模型实例之间的差异。对于后者,您可以用模型轮廓覆盖匹配结果,也可以用变形轮廓覆盖模型。虽然模型轮廓在默认情况下位于图像的原点,因此必须按照第39页2.4.3.1节的描述进行转换以获得适当的可视化效果,但变形轮廓已经位于匹配的位置。

3.5.5.4多个匹配的处理

如果搜索并找到该对象的多个实例,结果将以元组的形式连接起来。例如,Score是单个模型实例的一个值,现在是一个元组,其中元素的数量与找到的模型实例的数量相对应。对特定实例的值的访问类似于第82页3.3.4.5节中描述的基于形状的匹配过程。

对于单个模型实例,标志性的输出对象DeformedContours已经作为元组返回。对于多个实例,值只是连接在一起。要为特定的匹配访问它们,您必须知道单个模型实例返回的元素数量。这可以通过调用count_obj来获得模型轮廓,模型创建后可以使用get_deformable_model_contours查询模型轮廓。例如,如果模型由五个轮廓,在返回的元组变形轮廓,前五值属于第一个实例,未来五值属于第二个实例,等。一个例子为每个实例的访问值校准透视变形匹配详细描述3.6.4.5节在134页。

3.6透视变形匹配

与基于形状的匹配一样,透视变形匹配提取轮廓,并将轮廓与之前创建的模型的形状进行匹配。但与基于形状的匹配不同,透视变形匹配可以找到有效变形轮廓。对于透视变形匹配,提供了一个未校准的版本和一个校准版本。以下部分显示

  • 透视变形匹配的一个示例(3.6.1节),
  • 如何选择合适的ROI从参考图像中提取模板图像(第127页第3.6.2节),
  • 如何创建合适的模型(第128页3.6.3节),
  • 如何优化搜索(第132页第3.6.4节),
  • 如何处理特定于透视变形匹配的结果(第135页3.6.5节)。

3.6.1一个例子

在这一节中,我们将快速概述透视变形匹配的匹配过程。启动HDevelop示例程序hdevelop\Applications\
Traffic-Monitoring\detect_road_signs.hdev,它独立于路标的方向来定位路标。实际上,该程序搜索一个注意标志和一个死路标志。在接下来的例子中,我们展示了注意符号的处理范例。

步骤1:选择参考图像中的对象

首先,读取彩色参考图像,然后使用access_channel访问一个清楚显示注意符号的通道(参见图3.38,左)。由于搜索图像中的注意符号预期要比参考图像中的注意符号小得多,因此使用zoom_image_factor对参考图像进行缩放,以更好地适应预期的大小(见图3.38,中间)。透视变形模型的创建基于XLD轮廓,与基于形状的匹配相似。因此,inspect_shape_model(见第69页第3.3.3节)可用于获取参数NumLevels和Contrast的合适值,这是创建形状模型以及创建透视图可变形模型所需要的。具有多个金字塔级别的形状模型的返回表示可以用于直观地检查潜在模型(请参见图3.38,右)。

  1. read_image (ImageAttentionSign, 'road_signs/attention_road_sign')
  2. access_channel (ImageAttentionSign, Image, Channel[0])
  3. zoom_image_factor (Image, ImageZoomed, 0.1, 0.1, 'weighted')
  4. inspect_shape_model (ImageZoomed, ModelImages, ModelRegions, 3, 20)

步骤2:创建模型

如何从参考图像中获得合适的模板图像在第19页2.1节中描述。在这种情况下,不需要进一步降低限制的ROI。模型从模板图像create_planar_uncalib_deformable_model中获得。

  1. reate_planar_uncalib_deformable_model (ImageZoomed, 3, 0.0, 0.0, 0.1, \
  2. ScaleRMin[0], ScaleRMax[0], 0.05, \
  3. 1.0, 1.0, 0.5, 'none', \
  4. 'use_polarity', 'auto', 'auto', [], \
  5. [], ModelID)

步骤3:再次找到该对象

为了加快匹配速度,搜索空间首先被限制在一个矩形区域,然后在这个区域内,限制在由一组blob组成的ROI(见图3.39,左)。这组blob由过程determine_area_of_interest获得,该过程利用可用的颜色信息并应用blob分析。

  1. gen_rectangle1 (Rectangle1, 28, 71, 69, 97)
  2. for Index := 1 to 16 by 1
  3. read_image (Image, 'road_signs/street_' + Index$'.02')
  4. determine_area_of_interest (Image, Rectangle, AreaOfInterest)
  5. reduce_domain (Image, AreaOfInterest, ImageReduced)

在得到的ROI中,使用操作符find_planar_uncalib_deformable_model应用实际匹配。请注意,搜索是在已经用于创建模型的相同图像通道中应用的。

  1. for Index2 := 0 to |Models| - 1 by 1
  2. access_channel (ImageReduced, ImageChannel, Channel[Index2])
  3. find_planar_uncalib_deformable_model (ImageChannel, Models[Index2], \
  4. 0, 0, ScaleRMin[Index2], \
  5. ScaleRMax[Index2], \
  6. ScaleCMin[Index2], \
  7. ScaleCMax[Index2], 0.85, 1, \
  8. 0, 2, 0.4, [], [], HomMat2D, \
  9. Score)

对每个找到的模型实例进行匹配的结果是一个二维投影变换矩阵(homography)和一个表示匹配质量的分数。使用同质性,成功匹配的结果是可视化的。具体来说,模型的轮廓被查询并投影到搜索图像中,详见第51页的2.4.5节(参见126页3.39页,右)。

  1. if (|HomMat2D|)
  2. get_deformable_model_contours (ModelContours, Models[Index2], 1)
  3. projective_trans_contour_xld (ModelContours, ContoursProjTrans, \
  4. HomMat2D)
  5. endif
  6. endfor
  7. endfor

步骤4:销毁模型

当不再需要透视图可变形模型时,将使用clear_deformable_model销毁该模型。

clear_deformable_model (Models[Index1])

下面几节将更深入地介绍透视变形匹配的各个步骤以及需要调整的参数。

3.6.2选择模型ROI

作为透视图变形匹配的第一步,必须按照描述选择指定模板图像的感兴趣区域,例如,在第20页的2.1.1节中。该区域可以有任意形状,即,它也可以包含孔或由几个没有连接的部分组成。因此,可以创建只包含对象的“健壮”部分的ROI。必须选择ROI,使其包含对象的所有显著结构,同时也包含对象外部的一些像素,因为获取模型需要它们的直接环境(邻域)。此外,您可以使用子采样来加速后面的搜索(请参阅第129页的3.6.3.2节)。因此,ROI不应该太“薄”,否则它将在更高的金字塔级别上消失!根据经验,如果ROI是

像素宽,那么您是安全的。也就是说,8像素的宽度允许使用4个金字塔级别。在选择合适的ROI后,将缩小后的图像作为模板图像用于模型的创建。

3.6.3创建合适的透视图变形模型

从参考图像中导出模板图像后,可以创建透视变形模型。需要注意的是,透视变形匹配包含了不同的方法来寻找图像中的训练对象。根据所选择的方法,以下操作符之一用于创建模型:

  • create_planar_uncalib_deformable_model为未校准的透视图变形匹配创建一个模型,该匹配使用模板图像派生模型。
  • create_planar_uncalib_deformable_model_xld为未校准的每个透视可变形匹配创建模型,该匹配使用XLD轮廓来派生模型。注意,首先匹配,强烈建议使用set_planar_uncalib_deformable_model_metric来确定模型的极性信息(详细信息请参阅第25页的2.1.3.2节)。
  • create_planar_calib_deformable_model为使用模板图像派生模型的校准透视反形式化匹配创建了一个模型。
  • perspec create_planar_calib_deformable_model_xld为校准的透视变形匹配创建模型,使用XLD轮廓推导出模型。注意,在第一次匹配之后,强烈建议使用set_planar_calib_deformable_model_metric来确定模型的极性信息(详细信息请参阅第25页的2.1.3.2节)。

在这里,我们将进一步了解如何调整相应的参数。特别是,你可以

  • 通过调整参数Contrast来指定哪些像素是模型的一部分(3.6.3.1节),
  • 使用子采样加快搜索速度,即,通过调整参数NumLevels,减少模型点个数,即,通过调整参数Optimization( 3.6.3.2节),
  • 通过调整参数AngleExtent、AngleStart、AngleStep、ScaleMin、ScaleMax和ScaleStep(章节3.6.3.3),允许特定的方向和比例范围,
  • 通过调整参数MinContrast 和 Metric,指定在以后的搜索中与模型进行比较的像素(130页3.6.3.4节),
  • 在ParamName和ParamValue中调整一些额外的(通用的)参数,只有在非常罕见的情况下才需要这些参数(130页3.6.3.5节),和
  • 指定仅用于校准匹配的摄像机参数和参考位姿(CamParam和ReferencePose,参见142页3.7.3.3节)。

请注意,在调整参数时,您也可以让HALCON协助您:

  • 使用自动参数建议:您可以通过将相应的参数设置为操作符中的值“auto”,让HALCON为其中许多参数建议合适的值用于创建模型,或通过使用determine_deformable_model_params自动的确定从模板图像中用于透视变形模板的值,然后分别决定是否使用建议的值来创建模型。注意,这两种方法只返回大致相同的值,用于创建模型的操作符返回的值更精确。
  • 应用inspect_shape_model:由于透视图变形匹配使用XLD轮廓来构建模型,这与基于形状的匹配类似,您可以使用inspect_shape_model来尝试参数NumLevels和Contrast的不同值。该操作符返回具有多个金字塔级别的形状模型的结果表示,因此允许您直观地检查感兴趣的对象是否由模型充分表示。如果多个参数值的组合不能得到满意的对象表示,则可能是模板图像,即,模型的ROI选择不合适,第19页2.1节描述了如何选择合适的ROI。

注意,在模型创建之后,仍然可以修改模型。在131页的3.6.3.7节中,展示了检查和修改已经创建的模型的可能性。

3.6.3.1指定作为模型一部分的像素(Contrast)

对于该模型,这些像素被选择其对比度,即,当调用create_planar_uncalib_deformable_model或create_planar_calib_deformable_model时,灰度值差超过参数Contrast指定的阈值。参数Contrast类似于基于形状匹配的对应参数,详见第71页3.3.3.1节。唯一的区别是,这里的小结构不是在对比度内按下的,而是与单独的泛型参数“min_size”一起按下的,后者是通过ParamName和ParamValue设置的,如3.6.3.5节所述。

3.6.3.2利用子采样和点约简加快搜索速度(NumLevels, Optimization)

为了加快匹配过程,可以使用子采样(参见第30页的2.3.2节)。在这里,我们创建了一个图像金字塔,由原始的全尺寸图像和一组下采样图像组成。然后在不同的金字塔级别创建和搜索模型。

您可以通过参数NumLevels指定使用多少金字塔级别。通过参数Optimization可以进一步减少模型点。这可能有助于在特别大的模型中加速匹配。这两个参数与72页3.3.3.2节详细描述的基于形状匹配的对应参数相似。

3.6.3.3允许一定的方向范围(AngleExtent, AngleStart, AngleStep)和比例(Scale*Min, Scale*Max, Scale*Step)

与基于形状的匹配类似,可以使用参数AngleExtent, AngleStart, AngleStep,ScaleRMin, ScaleRMax, ScaleCMin, 和 ScaleCMax用于调整搜索模型的方向和缩放范围(参见73页的3.3.3.3节和74页的3.3.3.4节)。

注意,与基于形状的匹配所调整的范围不同,这里的参数可以相互预置,而不是作为搜索算法的一种建议,因此不是很严格。实际用于搜索的范围大于指定的范围,因此也可以找到指定范围之外的模型。实际使用范围由调整后的参数导出,进一步依赖于使用的金字塔层次以及模型和图像的内容。较大的范围用于处理透视变形匹配中典型的透视变形。例如,对于模型的小角度畸变,即使没有指定比例范围,也可以找到模型,这使得搜索速度更快。

3.6.3.4指定与模型比较的像素(MinContrast, Metric)

MinContrast参数允许您指定搜索图像中的一个点为了与模型进行比较至少必须具有哪个对比度,而Metric允许您指定极性是否和如何,即,必须观察对比度的方向。

这些参数类似于75页3.3.3.5节中描述的基于形状匹配的相应参数。唯一的区别是,透视变形匹配的另一个值的度量是可用的,允许观察极性的子部分的模型。子部分是一组相邻的模型点。对于不同角度的形式化匹配计算,将模型划分为一组大小近似相同的子部分(另见3.6.3.5节)。当将Metric设置为“ignore_part_polar”时,不同的子部分可能有不同的极性,只要各个子部分中的点的极性相同。这是有帮助的,例如,如果由于在三维空间的运动,不同的反射对象是预期的。由于这些反射通常不会太小,所以“ignore_part_polar”是“ignore_global_polar”之间的折衷,“ignore_global_polar”不能处理局部变化的极性和
“ignore_local_polar”,它需要非常精细的结构化检查,因此大大减慢了搜索速度。

3.6.3.5调整通用参数(ParamName, ParamValue)

通常,不需要调整通过ParamName和ParamValue设置的泛型参数。但在少数情况下,可能有助于调整模型分裂为子部分,这是不同计算透视形变匹配所需的,或抑制模型轮廓的小连接组件。

将ParamName设置为“part_size”,ParamValue设置为“small”,“medium', 或 'big'.

通过将ParamName设置为“min_size”,可以对模型轮廓的小连接组件进行压制。在ParamValue中指定的对应数值描述了一个对象的连接部分必须包含的点的数量,这些点至少在下面的计算中需要考虑。这种效果对应的是可以在参数对比中进行基于形状匹配的小结构的预设,如第71页3.3.3.1节所述。

3.6.3.6指定相机参数和参考位姿(CamParam, ReferencePose)

对于校准的匹配,必须指定内部摄像机参数(CamParam)和参考位姿(referenceencePose)。我们建议使用解决方案指南III-C(第68页3.2节)中描述的摄像机校准来获得这两个参数。其他方法来确定对象的构成平面组成一个手动测量模型的扩展,这是一种相当复杂而且常常不准确的立体视觉(看到解决方案指南III-C,第五章139页),或三维激光三角测量,例如,使用一张光(看到解决方案指南III-C,第六章177页)。

3.6.3.7检查和修改透视图变形模型

如果您希望可视化地检查已经创建的可变形模型,可以使用get_deformable_model_contours来获得在特定金字塔级别中表示模型的XLD轮廓。如果模型是由create_planar_calib_deformable_model_xld生成的,则在世界坐标系中默认以公制单位返回轮廓。在这里,为了可视化匹配,必须通过返回的姿势转换轮廓。在所有其他情况下,模型的轮廓默认情况下在图像坐标系中以像素单位返回。对于校准后的匹配,您可以指定在使用set_deformable_model_param操作符调用get_deformable_model_contours时返回轮廓的坐标系统。

要检查模型的当前参数值,可以使用get_deformable_model_params查询它们。如果在模型创建过程中使用了自动参数选择,或者模型是在另一个程序中创建的,用write_deformable_model保存为文件,用read_deformable_model在当前程序中从这个文件中读取,那么这可能是必要的。另外,您可以使用get_deformable_model_origin查询模型原点的坐标。

创建模型之后,在搜索图像中的对象之前,可以进一步修改模型。特别是,您可以应用set_deformable_model_origin来更改它的参考点,从而在校准匹配的情况下更改它的引用位置。但与基于形状的匹配相似,在修改参考点时,估计位置的精度可能会降低
(见85页3.3.4.7节)。因此,如果可能,不应改变参考点。相反,应该从一开始就选择适合模型创建的ROI(参见第21页的2.1.2节)。

您仍然需要修改的参考点的情况下,例如,如果原点应该放置在一个特定对象的一部分,例如,对象的一个角落或一个钻洞,同时你想应用一个校准匹配,我们在这里简要地描述了引用位姿、模型位姿和手动应用于引用点的偏移量之间的关系。特别是在为校准匹配创建模板模型时,通过摄像机校准得到的参考位姿会被偏移量自动修正,使其原点与校正后的模板图像(即得到的模型坐标系的坐标轴与初始参考位姿的坐标轴平行(见图3.40)。如果您使用set_deformable_model_origin对由此获得的模型位姿的原点应用偏移量,偏移量将在内部校正模板图像的图像坐标中设置。为了确定行方向和列方向所需的像素数,它是方便的从模板模型中去查询被修正的物体轮廓通过算子get_deformable_model_contours。设置好手动偏移量后,得到的图像点自动投影到目标平面上,作为修改后姿态的原点,对该姿态进行相应的调整,以适应后续的所有操作。

3.6.4优化搜索过程

实际匹配由以下操作符之一应用:

  • find_planar_uncalib_deformable_model搜索未校准的透视变形模型的最佳匹配。它返回一个二维投影变换矩阵(单应性)和描述匹配质量的分数。
  • find_planar_calib_deformable_model搜索最佳匹配校准透视变形模型。它返回对象的3D姿态,6个均方差,分别为位姿参数的36个协方差,和描述匹配质量的分数。

下面,我们将展示如何为这些操作符选择合适的参数来适应和优化匹配任务。特别是,我们展示了如何

  • 将搜索空间限制在感兴趣的区域(3.6.4.1节),
  • 通过参数AngleStart、AngleExtent、ScaleMin和ScaleMax限制方向和尺度范围,限制搜索空间(3.6.4.2节),
  • 将搜索空间限制在对象允许的遮挡的特定数量,即,通过参数MinScore指定对象的可见性(章节3.6.4.3),
  • 指定使用的搜索启发式,即调整参数Greediness来决定交换速度的彻底性(3.6.4.4节),
  • 通过调整参数NumMatches and MaxOverlap来搜索模型的多个实例(3.6.4.5节),
  • 限制搜索过程的金字塔级别(NumLevels)的数量(3.6.4.6节)和
  • 在ParamName和ParamValue中调整一些额外的(通用的)参数(第135页3.6.4.7节)。

匹配结束时,必须使用clear_deformable_model从内存中清除模型和进一步的缓冲数据。如果您想要重用一个模型,您必须在从内存中清除它之前将它存储到一个文件中。然后,您可以再次从文件中读取它,详情请参见28页2.2节。

3.6.4.1将搜索范围限制在感兴趣的区域

限制搜索空间从而加快匹配速度的明显方法是将算子 find_planar_uncalib_deformable_model或find_planar_calib_deformable_model应用于ROI,而不是整个图像。在78页的3.3.4.1节中,对基于形状的匹配进行了更多详细解释。对于透视图可变形匹配,只需分别用find_planar_uncalib_deformable_model或find_planar_calib_deformable_model替换find_shape_model即可。

3.6.4.2限制方向和尺度范围(AngleStart, AngleExtent,Scale*Min, Scale*Max)

在创建模型时,您已经为允许的方向和比例范围指定了一个建议值(参见第129页的3.6.3.3节)。在调用find_planar_uncalib_deformable_model或find_planar_calib_deformable_model时,可以进一步限制这些参数AngleStart, AngleExtent, ScaleMin, 和ScaleMax的范围。如果可以通过其他信息来限制这些范围,这是很有用的,这些信息可以通过适当的图像处理操作来获得。

在创建模型时使用更大范围的另一个原因可能是,您还希望将模型用于其他匹配任务。

3.6.4.3指定对象的可见性(MinScore)

使用参数MinScore可以指定模型的可见性。这种机制的一个典型应用是允许一定程度的遮挡。该参数类似于基于形状的匹配的对应参数,该参数在第80页的3.3.4.3节中有更详细的描述。

3.6.4.4交换彻底性vs速度(Greediness)

参数贪婪可以影响搜索算法本身,从而用足够来换取速度。该参数类似于基于形状匹配的对应参数,该参数在第81页的3.3.4.4节中有更详细的描述。

3.6.4.5搜索对象的多个实例(NumMatches, MaxOverlap)

要搜索对象的多个实例,只需将参数NumMatches设置为希望找到的最大实例数。如果选择值0,则返回所有匹配项。

定位多个实例,find_planar_uncalib_deformable_model和find_planar_calib_deformable_model操作符返回输出元组中连接在一起的单个模型实例的结果。也就是说,Score,是单个模型实例的一个值,现在作为元组返回,其中元素的数量与找到的模型实例的数量相对应。对于已经作为元组返回的单个模型实例的结果,元素的数量乘以找到的实例的数量。这些结果包括未校准匹配或三维位姿的投影变换矩阵(HomMat2D)和校准匹配的标准差或协方差(CovPose)。如何访问特定匹配的值,见3.6.5.1节。注意,对多个对象的搜索只比对单个对象的搜索稍微慢一点。

第二个参数MaxOverlap允许您指定两个匹配项可以重叠多少(作为一个分数)。该参数类似于82页3.3.4.5节中描述的基于形状匹配的对应参数。

3.6.4.6限制金字塔级别(NumLevels)的数量

您在创建模型时已经指定的参数NumLevels允许您在搜索过程中使用不同的(在大多数情况下是更严格的)值。如果将参数设置为0,则在搜索时使用创建模型时指定的NumLevels值。

NumLevels还可以包含第二个值,这样您不仅可以指定用于搜索的最高金字塔级别,还可以指定最低金字塔级别。如果搜索在比第一个金字塔级别(对应于原始的全尺寸图像)更高的金字塔级别中止,那么搜索将变得更快。另一方面,搜索的健壮性和准确性也会下降。如果在质量较差的图像中也应该找到对象,例如,如果对象是散焦的或有噪声的,则可以通过负向指定第二个值来激活增加的容忍模式。然后,返回仍然提供匹配的最低金字塔级别的匹配。

3.6.4.7调整通用参数(ParamName, ParamValue)

除了与基于形状匹配的参数相对应的那些参数外,透视变形匹配允许调整通过ParamName和一些通用的参数集
ParamValue。通常,不需要调整它们。但是,如果匹配的精度足够低,则可以通过降低或停用亚像素精度,或通过更改模型创建过程中设置的方向或比例的离散化步骤来加速匹配。为了避免误匹配,还可以限制角度和比例的扭曲。进一步的信息请参考参考手册中find_planar_uncalib_deformable_model的描述。

3.6.5使用透视图变形匹配的具体结果

对于未校准的情况,透视可变形匹配返回一个二维投影变换矩阵(HomMat2D),对于校准的情况,返回一个三维位姿(pose)和一个标准差或协方差(CovPose),对于这两种情况,返回一个评估返回对象位置质量的得分(score)。可利用二维投影变换矩阵和三维位姿可以将参考图像的结构转换为搜索图像,如第51页二维投影变换矩阵的2.4.5节和第54页三维位姿的2.4.6节所述。与基于形状的匹配类似,透视变形匹配可以返回模型的多个实例。如何使用这些多个实例见3.6.5.1节。

3.6.5.1处理多个匹配

如果搜索并找到该对象的多个实例,结果将以元组的形式连接起来。特别是Score,它是单个模型实例的一个值,现在是一个元组,其中元素的数量与找到的模型实例的数量相对应。对特定实例的值的访问类似于第82页3.3.4.5节中描述的基于形状的匹配过程。

参数HomMat2D, Pose,和CovPose已经作为元组返回给单个模型实例。对于多个实例,值只是连接在一起。要为特定的匹配访问它们,您必须知道单个模型实例返回的元素数量,对于单个投影变换矩阵是9个,对于单个3D姿态是7个,或者是6个(“默认”)或者36个元素(通用参数'cov_pose_mode'设置为'协方差'),分别表示单个实例的标准差或协方差。然后,例如,在元组包含3 d校准匹配返回的姿势,头前七个值属于第一种情况下,接下来的七个值属于第二个实例,等。一个示例,用于访问每个实例的值,HDevelop示例程序hdevelop\Applications\Position-Recognition-3D\locate_engine_parts.hdev,它定位图3.41所示的引擎部件。在本例中,通过使用tuple_select_range选择元组的特定子集,可以访问单个模型实例的3D姿态。

  1. find_planar_calib_deformable_model (Image, ModelID, rad(0), rad(360), 1, \
  2. 1, 1, 1, 0.65, 0, 0, 3, 0.75, [], \
  3. [], Pose, CovPose, Score)
  4. for Index1 := 0 to |Score| - 1 by 1
  5. tuple_select_range (Pose, Index1 * 7, ((Index1 + 1) * 7) - 1, \
  6. PoseSelected)
  7. pose_to_hom_mat3d (PoseSelected, HomMat3D)
  8. endfor

3.7 基于描述符的匹配

与透视变形匹配相似,基于描述符的匹配能够发现透视变形的对象。同样,匹配既可以应用于校准相机,也可以应用于未校准相机。与透视变形匹配不同,模板不是由轮廓的形状构建的,而是由一组所谓的兴趣点构建的。这些点首先由检测器提取,然后描述,即根据它们的位置和它们的局部灰度值邻域,用描述符进行分类。

以下部分显示

  • 基于描述符匹配的一个示例(第3.7.1节),
  • 如何选择合适的ROI从参考图像中提取模板图像(第139页第3.7.2节),
  • 如何创建合适的模型(第139页3.7.3节),
  • 如何优化搜索(第142页3.7.4节)
  • 如何处理基于描述符匹配的特定结果(146页3.7.5节)。

3.7.1一个例子

在这一节中,我们将快速概述基于(校准的)描述符匹配的匹配过程。启动HDevelop程序hdevelop\Applications\Object-Recognition-2D\locate_cookie_box.hdev,它定位一个按不同方向排列的cookie box标签。

步骤1:选择参考图像中的对象

首先,读取参考图像,并将图像缩小为矩形ROI。也就是说,派生出的模板图像只包含cookie框特定一侧的标签。

  1. read_image (Image, 'packaging/cookie_box_01')
  2. gen_rectangle1 (Rectangle, 224, 115, 406, 540)
  3. reduce_domain (Image, Rectangle, ImageReduced)

在进行校准匹配时,需要相机参数和标签相对于相机的参考位姿。为了得到精确的匹配,这些应该被获得,例如,通过解决方案指南III-C(第68页3.2节)中描述的摄像机校准。在这个例子中,位姿是由对应的点得到的,特别是由图像坐标和产生ROI的矩形的角点的估计世界坐标得到的。

步骤2:创建模型

摄像机参数和参考位姿输入create_calib_descriptor_model,该模型用于创建校准的描述符模型。在操作符中,选择检测器,并指定检测器和描述符的参数。在这种情况下,检测器的参数用[]指定,即,选择默认值。为了能够重用创建的描述符模型,它通过算子write_descriptor_file被存储到文件中。

  1. create_calib_descriptor_model (ImageReduced, CamParam, Pose, \
  2. 'harris_binomial', [], [], ['depth', \
  3. 'number_ferns','patch_size','min_scale', \
  4. 'max_scale'], [11,30,17,0.4,1.2], 42, \
  5. ModelID)
  6. write_descriptor_model (ModelID, 'cookie_box_model.dsm')

步骤3:再次找到该对象

find_calib_descriptor_model现在在搜索图像中定位cookie箱标签。返回的三维位姿描述了模型的世界坐标与找到匹配项的世界坐标之间的关系。图3.42显示了带有可视化结果的搜索图像。

  1. for Index := 1 to 10 by 1
  2. read_image (Image, 'packaging/cookie_box_' + Index$'.02')
  3. find_calib_descriptor_model (Image, ModelID, [], [], [], [], 0.25, 1, \
  4. CamParam, 'num_points', Pose, Score)
  5. endfor

步骤4:可视化匹配

结果以不同的方式呈现出来。首先,使用get_descriptor_model_points查询找到的模型实例的兴趣点,并可以立即使用gen_cross_contour_xld作为交叉显示。

  1. get_descriptor_model_points (ModelID, 'search', 0, Row, Col)
  2. gen_cross_contour_xld (Cross1, Row, Col, 6, 0.785398)

然后,通过过程dis_3d_coord_system可视化三维位姿的三维坐标系。

disp_3d_coord_system (WindowHandle, CamParam, Pose, 0.07)

最后,将显示cookie box标签轮廓的矩形。为此,矩形必须经过不同的转换步骤。特别是,从参考图像到世界坐标系(WCS)的转换之后,在WCS中进行三维仿射转换,然后在WCS中进行从WCS到搜索图像的转换。

由于HALCON中的区域无法通过3D转换进行转换,因此矩形的角点必须转变。在这里,用image_points_to_world_plane获得矩形角点的世界坐标。

  1. image_points_to_world_plane (CamParam, Pose, RowsRoi, ColumnsRoi, 'm', \
  2. XOuterBox, YOuterBox)

要使用affine_trans_point_3d应用下面的三维仿射变换,匹配返回的三维位姿必须使用pose_to_hom_mat3d转换为一个三维同构变换矩阵。

  1. pose_to_hom_mat3d (Pose, HomMat3D)
  2. affine_trans_point_3d (HomMat3D, XOuterBox, YOuterBox, [0,0,0,0], \
  3. XTrans, YTrans, ZTrans

然后利用project_3d_point将三维仿射变换得到的三维坐标投影到搜索图像中,从而对矩形进行重构和显示。

  1. project_3d_point (XTrans, YTrans, ZTrans, CamParam, RowTrans, \
  2. ColTrans)
  3. gen_contour_polygon_xld (Contour, RowTrans, ColTrans)
  4. close_contours_xld (Contour, Contour)
  5. dev_display (Contour)

步骤5:销毁模板

当描述符模型不再需要时,使用clear_descriptor_model销毁它。

clear_descriptor_model (ModelID)

下面几节将更深入地介绍基于描述符的匹配的各个步骤以及需要调整的参数。

3.7.2选择模型ROI

作为基于描述符的匹配的第一步,指定模板图像的相关区域必须按照描述进行选择,例如,在第20页的2.1.1节中。该区域可以有任意形状,即,它也可以包含孔或由几个没有连接的部分组成。因此,可以创建只包含对象的“健壮”部分的ROI。必须选择ROI,以便潜在的重要兴趣点不直接位于该区域的边界处,作为直接的环境需要兴趣点(邻域)来获得模型。选择一个合适的ROI后,将缩小后的图像作为模板图像用于模型的创建。

3.7.3创建合适的描述符模型

从参考图像派生出模板图像后,可以使用以下方法创建描述符模型

  • create_uncalib_descriptor_mode用于未校准的基于描述符的匹配或
  • 用于校准的基于描述符的匹配的create_calib_descriptor_model。

除了相机参数和参考位姿,这是只需要校准的情况下,需要调整的参数是相同的两个算子。在这里,我们将进一步了解如何调整它们。特别是,我们展示了如何

  • 选择并调整检测器(3.7.3.1节),
  • 调整描述符(3.7.3.2节)和
  • 指定校准匹配所需的摄像机参数和参考位姿(第142页3.7.3.3节)。

注意,在模型创建之后,仍然可以修改模型。在142页的3.7.3.4节中,展示了检查和修改已经创建的模型的可能性。

3.7.3.1选择并调整检测器(DetectorType、DetectorParamName、DetectorParamValue)

构建模型的兴趣点由所谓的检测器从图像中提取出来。通过参数DetectorType选择检测器的类型。可用的类型有“lepetit”、“harris”和“harris_binomial”,它们对应于HALCON 点操作符points_lepetit、points_harris和points_harris_binomial。‘lepetit’可以快速提取重要的点,但是提取的点没有‘harris’提取的点健壮。特别是,如果模板或搜索图像非常暗或对比度很低,不推荐使用“lepetit”。'harris_binomial'是“lepetit”和“harris”之间的一个很好的折中,因为它比“harris”更快,

或者每个检测器类型都有一组通用参数,这些参数可以使用参数DetectorParamName 和 DetectorParamValue进行调整。第一个用于指定泛型参数的名称,第二个用于指定相应的值。在创建模型之前,我们需要对所选的点操作符进行测试。也就是说,对模板图像应用相应的点操作符,并使用gen_cross_contour_xld可视化返回的点。为了得到一个好的结果,模板图像中应该均匀分布大约50到450个点。如果您已经为所选的点操作符找到了合适的参数设置,那么您还可以分别为create_calib_descriptor_model或create_uncalib_descriptor_model中的模型设置这些参数。注意,在大多数情况下,检测器的默认值(DetectorParamName和DetectorParamValue设置为[])就足够了。

3.7.3.2调整描述符(DescriptorParamName, DescriptorParamValue)

当前实现的描述符使用随机ferns对提取的点进行分类,即,建立兴趣点的位置特征描述和局部灰度值邻域。描述符可以通过参数DescriptorParamName和DescriptorParamValue进行调整。第一个用于指定必须调整的泛型参数的名称,第二个用于指定相应的值。

这些参数可以分为控制描述符大小的参数,从而控制检测的鲁棒性、速度和内存消耗,以及控制仿真的参数,特别是模型视图被训练的空间范围。描述符的大小由以下参数控制:

  • 'depth'指定分类ferns的深度。在选择较高的深度时,可以更好地识别兴趣点。另一方面,更高的深度会导致运行时增加。
  • 'number_fern '指定使用的ferns结构的数量。使用许多fern结构可以获得更好的健壮性,但也增加运行时间。
  • 'patch_size'指定用于描述单个兴趣点的二次邻域的边长。同样,过大的值会不利地影响运行时。

ferns的深度和数量的选择取决于您的具体要求。如果需要快速的在线匹配,推荐深度大且较少的ferns。如果需要一个健壮的匹配结果,则需要大量的ferns,而且深度大可能会增加鲁棒性,但也可能显著增加匹配的运行时间。如果内存消耗是关键的,建议使用深度较小的ferns。对于许多应用程序,需要在不同的需求之间进行权衡。

仿真,即模型的训练由以下参数控制:

  • 'tilt'设置为'on' 或'off',用于在仿真阶段打开或关闭投影变换,从而增强模型的鲁棒性或加快训练速度。
  • “min_rot”和“max_rot”定义了模型法向量旋转角度的范围。
  • “min_scale”和“max_scale”定义了模型的缩放范围。

旋转角度和比例尺限制在较小的范围内,可以显著加快训练的速度。但需要注意的是,在后续的应用匹配中,只有当模型的角度和尺度在训练范围内,才能找到模型。进一步注意,小图像的训练更快。因此,可以通过选择小参考图像和小模板图像并进行设置'tilt'为 'off'来加速训练。还要注意,参考图像和搜索图像应该具有相同的大小。

在HDevelop示例程序hdevelop\Applications\Object-Recognition-2D\detect_brochure_pages.hdev中给出了一个限制模型方向和规模的例子。它创建了一个未校准的描述符模型,用于匹配不同的小册子页面。取向是局限于一个角度范围+ / - 90°('default' is +/- 180°),刻度范围改变比例因子在0.2和1.1之间('default' is between 0.5 and 1.4)

  1. create_uncalib_descriptor_model (ImageReduced, 'harris_binomial', [], \
  2. [], ['min_rot','max_rot','min_scale', \
  3. 'max_scale'], [-90,90,0.2,1.1], 42, \
  4. ModelID)

3.7.3.3指定相机参数和参考位姿(CamParam, ReferencePose)

为了校准匹配,还必须指定摄像机参数(CamParam)和参考位姿(referenceencePose)。我们建议使用解决方案指南III-C(第68页3.2节)中描述的摄像机校准来获得这两个参数。其他方法来确定对象的构成平面组成一个手动测量模型的扩展,这是一个相当复杂且不准确的立体视觉(参见解决方案指南III-C,第五章139页),或三维激光三角测量,例如,使用一张光(看到解决方案指南III-C,第六章177页)。

3.7.3.4检查和修改描述符模型

如果您想查看一个已经创建的模型,您可以使用设置为“model”的get_descriptor_model_points获取其中包含的感兴趣点的坐标。

get_descriptor_model_points (ModelID, 'model', 'all', Row_D, Col_D)

要检查模型的当前参数值,可以使用get_descriptor_model_params查询它们。如果在模型创建过程中使用了自动参数选择,或者模型是在另一个程序中创建的,使用write_descriptor_model保存到文件中,并使用read_descriptor_model在当前程序中从该文件读取,则可能需要这样做。此外,您可以使用get_descriptor_model_origin查询模型原点的坐标。

创建模型之后,在搜索图像中的对象之前,可以进一步修改模型。特别是,您可以应用set_descriptor_model_origin来更改其原点。但请注意,这是不推荐的,因为匹配结果的准确性可能会降低,这一点在85页的3.3.4.7节中对于基于形状的匹配有更详细的说明。如果您仍然需要修改参考点,并且希望应用校准匹配,请参阅131页3.6.3.7节中透视变形匹配的相应描述。在这里,介绍了参考位姿、模型位姿和手动应用于参考点的偏移量之间的关系。

注意,在匹配之后,还可以使用get_descriptor_model_points查询特定匹配的兴趣点。然后,Set必须设置为“search”而不是“model”。在这里,查询第一个找到的模型实例(索引0)的兴趣点。

get_descriptor_model_points (ModelIDs[Index2], 'search', 0, Row, Col)

另外,在匹配之后,get_descriptor_model_results可以用来查询在搜索过程中累积的选定的数值结果,例如单个搜索点与模型点之间的对应分数(ResultNames设置为“point_classification”)。

3.7.4优化搜索过程

为了找到模型中存储和描述在相同或类似对象的未知图像中的相同兴趣点,应用以下操作符:

  • find_calib_descriptor_model搜索校准描述符模型的最佳匹配。它返回对象的3D姿态和描述匹配质量的得分。
  • find_uncalib_descriptor_model搜索未校准的描述符模型的最佳匹配。它返回一个二维投影变换矩阵(单应性)和描述匹配质量的分数。

除了摄像机参数(CamParam)外,未校准的和校准的相机需要相同的参数进行调整。请注意,假设创建模型和搜索的设置相同,摄像机参数仍然与已经指定的相同(请参阅139页的3.7.3节)。如果使用不同的摄像机进行搜索,我们建议应用解决方案指南III-C(第68页3.2节)中描述的一种新的摄像机校准。在下面,我们将展示如何

  • 将搜索空间限制在感兴趣的区域(3.7.4.1节),
  • 调整搜索检测器,仅在非常罕见的情况下推荐(3.7.4.2节),
  • 调整搜索描述符(3.7.4.3节),
  • 通过调整参数MinScore来指定对象的相似性(145页3.7.4.4节),
  • 通过调整参数NumMatches来搜索对象的多个实例(第145页3.7.4.5节),以及
  • 通过调整参数ScoreType选择分数类型(第145页3.7.4.6节)。

匹配结束时,必须使用clear_descriptor_model从内存中清除模型和进一步缓冲的数据。如果您想要重用一个模型,您必须在从内存中清除它之前将它存储到一个文件中。然后,您可以再次从文件中读取它,详情请参见28页2.2节.

3.7.4.1将搜索范围限制在感兴趣的区域

限制搜索空间从而加快匹配速度的明显方法是将find_uncalib_descriptor_model或find_calib_descriptor_model操作符应用于ROI,而不是整个图像。第78页第3.3.4.1节详细解释了形状匹配的相关步骤。对于基于描述符的匹配,只需分别用find_uncalib_descriptor_model或find_calib_descriptor_model替换find_shape_model即可。

3.7.4.2调整搜索检测器(DetectorParamName, DetectorParamValue)

控制检测的参数,即,从图像中提取兴趣点,通过DetectorParamName和DetectorParamValue进行调整。它们对应于在模型创建过程中已经指定的检测器参数(参见第139页的3.7.3节)。在大多数情况下,它们不应该为搜索而更改。也就是说,您只需将一个空tuple([])传递给参数。

在少数情况下,特别是当参考图像和搜索图像之间有显著的光照变化时,您可以更改参数值。例如,如果搜索图像非常暗,并且选择“lepetit”作为检测器,那么可以将“min_score”设置为一个较小的值。

一般来说,为了测试是否有必要改变某些参数值,您可以对创建模板的参考图像(见140页也部分3.7.3.1)和搜索图像应用对应于探测器的点操作符。同样的,为了得到一个好的匹配结果,需要提取大约50到450个均匀分布的点。如果点算子对参考和搜索图像需要不同的参数,可能需要相应地改变相应检测器参数的值。

3.7.4.3调整搜索描述符(DescriptorParamName, DescriptorParamValue)

通过参数DescriptorParamName和DescriptorParamValue调整控制搜索图像兴趣点与模型兴趣点之间对应关系。可以设置两个通用参数:

  • 参数'min_score_descr'可以设置为大于0.0的值(但最好是小于0.1)来增加最小分类分数,以确定各个点是否被认为是潜在的匹配。从而减少了进一步计算的点数,提高了匹配的速度。但是请注意,这种加速是以降低鲁棒性为代价获得的,特别是在提取点的数量较低的情况下。
  • 参数“guided_matching”可以通过将其从“on”设置为“off”来关闭。如果开启引导匹配(默认),则增强了模型位置估计的鲁棒性。具体来说,点是从搜索图像中提取出来的,并由描述符进行分类。分类所接受的点用于计算初始二维投影(未标定情况)或均匀三维(标定情况)变换矩阵。然后将所有模型点投影到搜索图像中。如果投影模型点靠近原始提取点之一,即,与分类无关,该点分别作为二维投影变换矩阵或三维位姿进行匹配返回的同应性的最终计算。由于通常不需要分类,可以使用更多的点进行计算,因此得到的单应性更强。另一方面,在某些情况下,匹配的运行时间可能增加10%。因此,如果健壮性不如速度重要,那么可以关闭‘guided_matching’。

HDevelop示例程序hdevelop\Applications\Object-Recognition-2D\detect_brochure_pages.hdev是一个将“min_score_descr”设置为更高值(0.003)以加快匹配的例子。由于图像中的点足够多,匹配仍然足够健壮。

  1. find_uncalib_descriptor_model (ImageGray, ModelIDs[Index2], \
  2. 'threshold', 800, \
  3. ['min_score_descr', \
  4. 'guided_matching'], [0.003,'on'], \
  5. 0.25, 1, 'num_points', HomMat2D, \
  6. Score)

3.7.4.4指定对象的相似性(MinScore)

参数MinScore指定必须作为匹配返回的潜在匹配的最小分数。分数是衡量匹配质量的值,即,表示模型与搜索图像之间的对应关系或“相似性”。注意,对于基于描述符的匹配,输出参数得分可以使用不同类型的得分(参见3.7.4.6节)。但是对于输入参数
MinScore,总是使用'inlier_ratio'类型的分数。它计算出对应于模型点数的点数与模型点数的比值。在大多数情况下,MinScore应该设置为至少0.1。为了加快搜索速度,应该选择尽可能大的值,但当然仍然要尽可能小,以便搜索成功,例如,匹配不太可能达到1.0的值。

3.7.4.5搜索对象的多个实例(NumMatches)

要搜索对象的多个实例,只需将参数NumMatches设置为希望找到的最大实例数。如果选择值0,则返回所有匹配项。

定位多个实例,find_uncalib_descriptor_model和find_calib_descriptor_model操作符返回输出元组中的单个模型实例的结果。也就是说,Score(通常是单个模型实例的一个值)现在作为元组返回,其中元素的数量与找到的模型实例的数量相对应。投影变换矩阵(HomMat2D)或3D位姿(pose)的元素个数,已经是单个模型实例的元组,是单个实例的元素个数乘以找到的实例个数。如何访问特定匹配的值,见3.7.5.1节。注意,搜索多个对象只比搜索单个对象稍微慢一点。

3.7.4.6选择合适的分数类型(分数类型)

参数ScoreType用于选择将在参数得分中返回的得分类型。可用的类型有“num_points”和“inlier_ratio”:

  • 对于“num_points”,返回每个实例对应的点数。由于任何四个对应定义了两个图像之间数学上正确的单应性,这个数字应该至少是10,以假设一个可靠的匹配结果。
  • 对于“inlier_ratio”,返回与模型点数量对应的点数量的比值。虽然该参数的值可能介于0.0和1.0之间,但是匹配不太可能达到1.0的比例。然而,内线比率小于0.1的对象应该被忽略。

通常,这两种得分类型都会被选中,但是也可以在元组中传递这两种类型。然后,单个找到的模型实例的结果也以元组的形式返回。

3.7.5使用基于描述符匹配的具体结果

基于描述符的匹配返回未校准情况下的二维投影变换矩阵(HomMat2D),对于校准的情况是一个3D位姿(pose),对于这两种情况都是一个评分(score),用于评估返回对象位置的质量。利用二维投影变换矩阵和三维位姿可以将参考图像的结构转换为搜索图像,如第51页2.4.5节的二维投影变换矩阵和第54页2.4.6节所述的三维位姿。分数可以按照3.7.4.6节的描述进行解释。与基于形状的匹配类似,基于描述符的匹配可以返回模型的多个实例。如何使用这些多个实例见3.7.5.1节。

3.7.5.1处理多个匹配

如果搜索并找到该对象的多个实例,结果将以元组的形式连接起来。特别是Score,它通常是单个模型实例的一个值(关于异常,请参阅145页的3.7.4.6节),现在是一个元组,其中元素的数量与找到的模型实例的数量相对应。对特定实例的值的访问类似于第82页3.3.4.5节中描述的基于形状的匹配过程。

参数HomMat2D或Pose已经作为元组返回给单个模型实例。对于多个实例,值只是连接在一起。要为特定的匹配访问它们,您必须知道单个模型实例返回的元素数,即单个投影变换矩阵返回的元素数为9,单个3D位姿返回的元素数为7。然后,例如,返回的元组的3 d姿势,前七个的值属于第一种情况下,接下来的七个值属于第二个实例,等。一个例子为每个实例的访问值是校准的角度详细描述见透视变形匹配134页3.6.4.5节。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
HALCON 20.11:深度学习笔记(11)
ThinkPHP源码分析系列—ADSL方法
UML建模相关概念
const使用详解
rxjs Observable 两大类操作符简介
Linux 下 Pylearn2的使用简介
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服