解决方案指导------匹配(Matching)(2)

第二章

总论

匹配的一般程序是准备参考图像,例如,通过预处理(如有必要),准备模板,创建模型,修改已经存在的模型(如有必要),存储到文件(如果它需要被重用),查询信息(这是必要的,例如,当重用先前存储模型),限制搜索空间,加快以下匹配,搜索模型在,(可能预处理)搜索图片中,进一步处理匹配结果,从内存中清除模型。

下面,我们将同时讨论适用于许多匹配方法的不同一般主题。特别是,

  • 第2.1节展示了如何准备模板,
  • 第28页2.2节展示了如何重用模型,
  • 第30页2.3节展示了如何加速搜索,
  • 第33页2.4节展示了如何进一步处理匹配结果。

2.1 准备模板

对参考图像进行可选的预处理后,匹配的第一步是准备感兴趣对象的模板。由此导出一个模型,在后面的步骤中,该模型用于在搜索图像中定位对象的实例。在大多数情况下,模型是从参考图像派生出来的,而参考图像又被简化为所谓的模板图像。如何使用感兴趣区域(ROI)获得这个模板图像,在2.1.1节中进行了描述。ROI对进一步匹配过程的影响见第21页的2.1.2节。对于一些匹配方法,可以使用合成模型代替模板图像。它可以是综合创建的模板图像,也可以是XLD轮廓(请参阅第23页的2.1.3节)。

2.1.1 将参考图像简化为模板图像

要从参考图像创建模型(这是大多数匹配方法的常见方法),必须将参考图像简化为只包含派生模型所需的参考图像的结构的模板图像。

为此,您可以在参考图像中选择一个区域,该区域显示应该作为模板的图像部分,或者分别作为模型的派生部分。选择区域后,利用算子reduce_domain将参考图像的域缩小为ROI。得到的图像是我们的模板图像,它是为实际模型生成提供的特定于方法的操作符之一的输入。

请注意,区域以及模型可以具有任意形状(有关HALCON中区域的确切定义,请参阅快速指南第18页的2.1.2.2节)。可以以不同的方式创建区域,如解决方案指南I中,第33页的第3章和第45页的第4章所述。

综上所述,可以选择一个区域,例如,通过以下方法:

  • 区域可以通过明确的定义其参数来指定。也就是说,HALCON提供了多个操作符来创建区域,从标准形状(如矩形(gen_rectangle2)或椭圆(gen_ellipse)到自由形状(如gen_region_polygon_fill)。这些操作符可以在HDevelop菜单Operators >Regions>Creation中找到。要使用操作符,您需要创建形状的参数,例如,矩形的位置、大小和方向,或者圆的位置和半径。如果这些参数不是明确已知的,则可以使用draw操作符,例如,这些操作符允许您在显示的图像上绘制形状,然后返回形状参数。这些操作符是可用的,在HDevelop菜单Operators >Graphics>Drawing。
  • 可以使用图像处理(例如blob分析)指定区域。然后对图像进行分割,如使用threshold算子,对得到的区域进行进一步处理,来选择具有特定特征的部分(常用的算子有connection、fill_up、select_shape)。在HDevelop中,您可以使用对话框Visualization>Feature检测来确定适当的特性和值。功能检查。利用集合理论可以创建更复杂的区域,即通过使用union2和difference算子加减标准区域。例如,也可以像第22页的2.1.2.2节所示那样创建环状ROI。

在创建ROI之前,通常可以通过预处理来优化参考图像。注意,在使用基于形状的匹配时,可以使用HDevelop Assistant指导您完成匹配过程,该过程还包括参考图像的预处理和ROI的创建。如何使用匹配助手在HDevelop用户指南(第269页7.3节)中有描述。

请注意,ROI之外的灰色值也会对模型生成产生影响。具体来说,影响大约是2^{NumLevels}像素,其中n是金字塔层数。因此,参考图像中选择的ROI之外的灰度值应该与搜索图像中出现的相似。

2.1.2 感兴趣区域的影响

创建模型时所使用的ROI决定了模型的质量,从而极大地影响了后续搜索的成功。如果选择的ROI不恰当,那么在搜索图像中就不会识别出模型的实例,或者识别出错误的图像结构。因此,如果匹配不成功或结果不准确,您应该非常仔细地检查ROI,并尝试增强它,以便模型表示对象,而不是图像中可能包含的混乱。对于基于轮廓的方法,如基于形状的匹配和局部或透视图变形匹配,您可以使用操作符inspect_shape_model来直观地检查潜在的模型。为了创建一个高质量的模型,您必须注意ROI中心的正确选择,即,“参考点”(见第2.1.2.1节),以及如何正确选择ROI的轮廓(见22页第2.1.2.2节)。

2.1.2.1参照点

ROI一方面影响模型的质量,从而影响后续匹配的普遍成功。另一方面,匹配返回的数值结果也会受到影响。特别是,ROI的中心点在默认情况下充当模型估计位置、旋转和缩放的所谓参考点。注意,如果没有选择ROI,参考点位于图像的中心(见图2.1)。

参考点也会影响后续搜索的成功,因为只有当参考点在图像中,或者更准确地说,在图像的域中,才会找到对象(参见78页3.3.4.1节)。也就是说,如果一个引用点被放置在远离实际对象的地方(如图2.1所示,左),那么以后的匹配可能会失败,尽管对象本身已经完全包含在搜索图像中,仅仅因为没有包含引用点。因此,选择适当的ROI是非常重要的即使模板对象在图像中是唯一的对象。

注意,对于某些方法,在创建模型之后,您可以修改引用点。但由于修改的参考点可能会导致估计位置的准确性下降(见第85页第3.3.4.7节),如有可能,参考点不应更改!此外,即使您修改了引用点,测试中,如果引用点位于搜索图像的区域内,那么将总是从原始参考点开始执行,即初始选定ROI的中心点。因此,为模板图像选择合适的ROI从一开始就很重要。

2.1.2.2 ROI的轮廓

模型的质量和匹配结果的准确性受模型的轮廓,特别是它的形状、大小和方向的强烈影响。

为了保证模型的高质量,应该选择ROI,以便将噪声或杂波最小化。这可以通过“masking”对象中包含杂波的部分来实现。在图2.2中,例如,需要电容模型进行基于形状的匹配。为了尽可能地排除杂波,使用两个圆形区域之间的差值来创建环形ROI,而不是圆形ROI。

draw_circle (WindowHandle, ROI1Row, ROI1Column, ROI1Radius)
gen_circle (ROI1, ROI1Row, ROI1Column, ROI1Radius)
gen_circle (ROI2, ROI1Row, ROI1Column, ROI1Radius - 8)
difference (ROI1, ROI2, ROI)
reduce_domain (ModelImage, ROI, ImageROI)

此外,模型中包含的轮廓点数量也会影响目标定位的准确性。也就是说,多轮廓点的模型比少轮廓点的模型能更准确地找到(见图2.3)。

此外,根据模型中包含的轮廓线的不同,匹配结果的准确性会因方向的不同而不同。如果,模型主要由水平轮廓组成,如图2.4a所示,可以得到较好的垂直精度,但水平精度较差。图2.4b中的模型包含垂直和水平方向的轮廓。因此,可以在两个方向上获得足够的精度。各方向精度较高的最佳模式是圆形结构,如图2.4c所示。因此,请仔细选择模型,使它符合足够的轮廓,垂直于你想要检查或测量的方向匹配后。

匹配返回的旋转角度的精度,一方面取决于轮廓点与旋转中心的距离,另一方面取决于轮廓相对于旋转中心的方向(见图2.5)。特别是远离旋转中心的点可以更准确的确定。也就是说,在模型轮廓数量相同的情况下,如果旋转中心位于轮廓的中心且轮廓被拉长,则可以更准确地确定轮廓的方向。

2.1.3 合成模型作为模板图像的替代品

对于一些匹配方法,可以使用合成模型代替模板图像。有三种使用合成模型的方法:

  • 创建一个合成模板图像,
  • 直接使用XLD轮廓作为模型(这只能应用于特定的匹配方法,如第25页2.1.3.2节所列),或
  • 使用DXF模型派生XLD轮廓,然后可以直接将其用作模型(仅适用于第25页2.1.3.2节中列出的特定匹配方法)或用于创建合成模板图像。

2.1.3.1合成模板图像

合成模板图像主要适用于基于关联的匹配和所有基于轮廓的二维方法,即基于形状的、基于组件的、局部可变形的和透视图可变形的匹配。

根据应用的不同,因为没有包含完美的、易于提取对象实例的映像可用,可能很难从参考图像中创建合适的模型。图2.6中描述了电容器位置的一个例子。这个任务一开始似乎很简单,因为电容器在黑暗的背景下由突出的亮圈表示。但是从圆形ROI推导出的形状模型是错误的,因为图像在圆的内外都含有杂波,即不属于物体的高对比度点。对于环型ROI,该方法能够较好地“屏蔽”包含杂波的部分。然而,由于圆的部分缺失,模型中仍然存在一些杂波点,模型仍然不完善。

这种情况下,通常最好使用合成模板映像。下面将解释如何为电容器创建这样的映像。为了主观的看到这个例子,启动HDevelop程序solution_guide\matching \synthetic_circle.hdev。

步骤1: 创建XLD轮廓

首先,我们使用运算符gen_ellipse_contour_xld创建一个圆形区域。您可以通过使用HDevelop对话框Visualization>Zoom 窗口检查图像来确定合适的半径,或在HDevelop的图形窗口中使用ROI工具更方便地创建区域。

RadiusCircle := 43
SizeSynthImage := 2 * RadiusCircle + 10
gen_ellipse_contour_xld (Circle, SizeSynthImage / 2, SizeSynthImage / 2, 0, \
                          RadiusCircle, RadiusCircle, 0, 6.28318, \
                          'positive', 1.5)

注意,合成图像应该大于区域,因为在创建基于形状的匹配的图像金字塔时,也会使用区域外的像素,在本例中,这就是所选的匹配方法(对于图像金字塔,请参见第30页的2.3.2节)。

步骤2:创建一个图像并插入XLD轮廓

然后,我们使用运算符gen_image_const创建一个空图像,并使用运算符paint_xld插入XLD轮廓。在图2.7a中描述了结果图像。

gen_image_const (EmptyImage, 'byte', SizeSynthImage, SizeSynthImage)
paint_xld (Circle, EmptyImage, SyntheticModelImage, 128)

步骤3:创建模型

通过合成图像创建模型。

create_scaled_shape_model (SyntheticModelImage, 'auto', 0, 0, 0.01, 0.8, \
                            1.2, 'auto', 'none', 'use_polarity', 30, 10, \
                            ModelID)

图2.7b为对应的模型区域,图2.7c为搜索结果。注意图像本身,即,其域在本例中充当ROI。

2.1.3.2 从XLD轮廓创建模型

对于基于形状的匹配以及局部和透视图的变形匹配,您不必创建一个合成模板图像来从XLD轮廓派生模型,因为您可以直接使用XLD轮廓作为模型。然后,例如,对于基于形状的匹配,您不需要提供图像,选择ROI和调用其中一个操作符create_shape_model、create_scaled_shape_model或create_aniso_shape_model来构建模型。相反,只需调用其中一个操作符create_shape_model_xld、create_scaled_shape_model_xld或create_aniso_shape_model_xld,来将XLD轮廓作为输入。通过HDevelop示例程序examples\hdevelop\Matching\Shape-Based\create_shape_model_xld.dev给出了一个从圆形XLD轮廓创建形状模型的例子:

gen_circle_contour_xld (ContCircle, 300, 300, MeanRadius, 0, 6.28318, \
                        'positive', 1)
create_shape_model_xld (ContCircle, 'auto', 0, 0, 'auto', 'auto', \
                        'ignore_local_polarity', 10, ModelID)

对局部和透视变形匹配进行了相应的处理。在这里,分别应用算子create_local_deformable_model_xld实现局部可变形匹配和create_planar_uncalib_deformable_model_xld或create_planar_calib_deformable_model_xld操作符实现透视图可变形匹配。

注意,当从XLD轮廓创建模型时,没有关于模型极性的可用信息(请参见图2.8,左)。因此,在创建模型时,必须设置参数度量,以便在本地忽略极性。由于这会导致搜索速度非常慢,HALCON提供了为找到的模型实例确定极性的方法。也就是说,在搜索图像只进行一次缓慢搜索的极性是代表搜索图片集的极性,项目模型轮廓内发现的位置搜索图像(见图2.8,右),和使用算子set_shape_model_metric 用于基于形状的匹配,set_local_deformable_model_metric用于局部变形匹配,和set_planar_uncalib_deformable_model_metric或set_planar_calib_deformable_model_metric,分别用于透视变形匹配。然后,极性信息存储在模型中,并为接下来的搜索传递参数可以将Metric设置为更合适的值,例如“use_polarity”。强烈建议使用此过程进行快速和健壮的搜索。

find_shape_model (Image, ModelID, 0, 0, 0.7, 0, 0, 'least_squares', 0, 0.9, \
                  Row, Column, Angle, Score)
... accessing the indices of the matches
... that represent suitable drill holes
vector_angle_to_rigid (0, 0, 0, Row[HoleIndices[0]], Column[HoleIndices[0]], \
                        Angle[HoleIndices[0]], HomMat2D)
set_shape_model_metric (Image, ModelID, HomMat2D, 'use_polarity')
for Index := 2 to 9 by 1
      read_image (Image, 'brake_disk/brake_disk_part_' + Index$'02d')
      find_shape_model (Image, ModelID, 0, 0, 0.7, 0, 0, 'least_squares', 0, \
                        0.9, Row, Column, Angle, Score)
endfor

关于基于形状匹配的模型极性的更多信息,请参阅第75页的第3.3.3.5节。

2.1.3.3 从DXF文件中获得模型

匹配所需的模型也可以从DXF文件派生出来。特别是,您可以使用算子read_contour_xld_dxf从DXF文件提取XLD轮廓,然后使用XLD轮廓来创建一个合成图像或,如果选择的匹配方法允许(见第25页2.1.3.2节 ),则直接使用XLD轮廓作为模型。

HDevelop示例程序examples\ hdevelopment \Applications\ Position-Recognition-2D\ pm_multiple_dxf_models.dev给出了一个使用从DXF文件中提取的XLD轮廓创建基于形状匹配的合成模板图像的示例。在目录examples\hdevelop\Matching\Deformable下通过HDevelop示例程序create_planar_calib_deformable_model_xld.dev和create_planar_uncalib_deformable_model_xld.dev(见图2.9)给出了使用直接从DXF文件中提取的XLD轮廓作为模型创建透视图可变形模板的示例

2.2 模板再使用

如果您想在其他HALCON应用程序中重用创建的模型或训练结果,您所需要做的就是将相关信息存储在文件中,然后再次读取它们。

HDevelop示例程序solution_guide\matching\reuse_model.hdev以实例说明了如何重用模型来实现基于形状的一致缩放匹配。首先,创建模型。

create_scaled_shape_model (ImageROI, 'auto', -rad(30), rad(60), 'auto', 0.6, \
                           1.4, 'auto', 'none', 'use_polarity', 60, 10, \
                           ModelID)

然后,使用算子write_shape_model将模型存储在一个文件中。对于该模型,HALCON自动保存XLD轮廓、参考点和调用create_scaled_shape_model时使用的参数。

write_shape_model (ModelID, ModelFile)

注意模型区域,即在存储模型时不保存图像的域。因此,如果您也想重用它,可以使用write_image存储模板图像。

odelRegionFile := 'model_region_nut.png'
write_image (ImageROI, 'png', 0, ModelRegionFile)

在示例程序中,形状模型被清除以表示另一个应用程序的启动。

clear_shape_model (ModelID)

现在使用算子read_shape_model从文件中读取模型、XLD轮廓和参考点。然后,分别使用get_shape_model_contours和get_shape_model_origin访问XLD轮廓和引用点。在稍后调用find_scaled_shape_model之后,需要对匹配结果进行形式化。此外,用于创建模型的参数可以使用get_shape_model_params操作符访问,因为其中一些参数需要作为find_scaled_shape_model的输入。

read_shape_model (ModelFile, ReusedModelID)
get_shape_model_contours (ReusedShapeModel, ReusedModelID, 1)
get_shape_model_origin (ReusedModelID, ReusedRefPointRow, ReusedRefPointCol)
get_shape_model_params (ReusedModelID, NumLevels, AngleStart, AngleExtent, \
                        AngleStep, ScaleMin, ScaleMax, ScaleStep, Metric, \
                        MinContrast)

以前存储的模板图片可以用read_image读取,相应的域可以通过get_domain访问。

read_image (ImageModelRegion, 'model_region_nut.png')
get_domain (ImageModelRegion, DomainModelRegion)

现在,可以像在应用程序中创建模型一样使用该模型。

find_scaled_shape_model (SearchImage, ReusedModelID, AngleStart, \
                         AngleExtent, ScaleMin, ScaleMax, 0.65, 0, 0, \
                         'least_squares', 0, 0.8, RowCheck, ColumnCheck, \
                          AngleCheck, ScaleCheck, Score)
for i := 0 to |Score| - 1 by 1
    vector_angle_to_rigid (ReusedRefPointRow, ReusedRefPointCol, 0, \
                           RowCheck[i], ColumnCheck[i], AngleCheck[i], \
                           MovementOfObject)
    hom_mat2d_scale (MovementOfObject, ScaleCheck[i], ScaleCheck[i], \
                     RowCheck[i], ColumnCheck[i], MoveAndScalingOfObject)
    affine_trans_contour_xld (ReusedShapeModel, ModelAtNewPosition, \
                              MoveAndScalingOfObject)
    dev_display (ModelAtNewPosition)
endfor
clear_shape_model (ModelID)

请注意,存储在模型中并且在读取模型之后可以查询的信息文件取决于所选择的方法。与基于形状的匹配类似,许多方法提供操作符来查询模型的起源以及用于创建或修改模型的几个参数。一些方法还提供操作符来查询模型的轮廓,或者在基于描述符的情况下匹配定义模型的兴趣点。

2.3加快搜索速度

你可以通过以下方式加速搜索

  • 限制搜索空间(2.3.1节)和
  • 使用子采样(章节2.3.2)。

2.3.1限制搜索空间

在寻找对象的过程中,一个重要的概念就是所谓的搜索空间。毫不夸张地说,这个术语指定了在哪里搜索对象。根据匹配方法的不同,这个空间不仅包含图像的两个维度,还包括其他参数,如可能的比例和方向范围,或者对象的多少必须是可见的问题。限制搜索空间越多,搜索速度就越快。

最明显的限制搜索空间的方法是将用于在图像中寻找模型的算子应用于ROI,而不是整个图像,这种方法适用于所有匹配方法。

可以用来限制搜索空间的其他参数取决于特定的匹配方法。一些方法已经非常严格,另一些方法允许对象的不同变化,如旋转或缩放,因此强烈建议限制搜索空间。基于形状的匹配,例如,允许任意方向和比例的变化,以及模型实例在搜索图像中的遮挡。
因此,对于基于形状的匹配,也要考虑方向和尺度的范围以及可见性,即限制图像中模型实例允许的遮挡量,以加快搜索速度(见第77页3.3.4节)。

2.3.2关于二次抽样

除了基于描述符的匹配方法外,所有的匹配方法都可以使用所谓的图像金字塔来加速搜索。在一些方法中,图像金字塔是为搜索图像和模板图像创建的,金字塔由原始的、全尺寸的图像和一组下采样图像组成。例如,如果原始图像(第一层金字塔)的大小是600x400,那么第二层图像的大小是300x200,第三层图像的大小是150x100,依此类推。然后,首先在最高的金字塔级别上搜索该对象,即在最小的图像中。这种快速搜索的结果被用于限制下一层金字塔图像的搜索,下一层金字塔图像的结果被用于下一个较低的层次,直到达到最低层次。采用这种迭代方法,搜索速度快,精度高。图2.10描绘了一个示例图像金字塔的四个层次以及相应的模型区域。

注意,当图像被下采样时,会发生不同的“事件”。首先,特定的结构在较高的金字塔层次中消失。如图2.10所示,薄结构比厚结构消失得快。请注意,“薄结构”包括实际模型的不同结构以及它们之间的距离。因此,模型的小结构可能会消失,但是如果它们之间的距离很小,它们也可以合并。此外,在较高的金字塔层次中,结构边界模糊,对比度降低。在图2.11中,这种效果显示在一个像素宽的直线上。

对于更复杂的模式,这可能导致模式的消失,甚至可能导致新模式的创建。由结构模糊引起的模式消失的例子有图2.10中的小字符,图2.12中一个像素宽的高对比度线构成的规则网格,以及图2.13中由距离为一个像素的高对比度矩形组成的模式。后一个例子还表明,可以在金字塔中创建新的模式。在将模式模糊到同类区域之前,将创建一个不同的规则模式。此外,也有可能出现新的结构,因为感兴趣的区域被选择得太大,因此,在第一层金字塔中不属于模型的轮廓会成为更高级别模型的一部分。

结构的模糊及结构是否仍然包含在更高的金字塔级别除了尺寸决定之外,对比度也有影响。经过下采样之后,足够尺寸的高对比度结构仍然有足够的对比度能够被识别,而同样尺寸的低对比度的结构则不能从背景中区分出来,例如,在图2.1中,“MVTec”标识的大而明亮的“V”在明亮的背景前消失,处于同一层金字塔级别当中仍然包含大的高对比度字符。因此,为了从子采样获得的加速中获益,图像应该具有尽可能多的对比度。

2.4 使用匹配结果

匹配的主要目标是在图像中定位目标对象,即首先获取图像中模型实例的位置,在大多数情况下还获取图像中模型实例的方向。此外,许多方法返回额外的信息,如对象的尺度或评估返回对象位置的质量的得分。在下面的部分中:

  • 列出了不同匹配方法的独特结果(2.4.1节),
  • 介绍了HALCON可以处理的不同类型的转换,以及进一步处理匹配结果通常需要的转换(第35页2.4.2节)。
  • 最常见结果的不同用途,即估计的位置和方向,描述(第39页第2.4.3节),
  • 介绍了尺度的使用(第49页2.4.4节),
  • 介绍了二维投影变换矩阵(二维单应性)的使用(第51页2.4.5节),
  • 介绍了3D姿势的使用(第54页的2.4.6节),
  • 简短讨论了返回的分数(第56页的2.4.7节)。

2.4.1 单个匹配方法的结果

要在图像中定位对象,匹配必须返回搜索对象的位置和方向等信息。根据选择的匹配方法,这些信息以不同的表示形式可用。也就是说,对于一个严格的2D匹配,位置和方向分别被重新旋转,即位置由行值和列值组成,方向由描述角度的单个值组成。与此相反,未校准的透视方法在投影变换矩阵(二维单应矩阵)中返回位置和方向,而校准的透视方法以三维姿态返回位置和方向。除了位置和方向外,许多方法还返回进一步的信息,如找到的对象的尺度或关于匹配信息的质量,这就是得分。

下面列出了各个匹配方法的结果。下面几节将介绍如何进一步处理它们。

2.4.2 关于转换

HALCON为不同类型的转换提供操作符。对于严格的2D匹配方法,可以使用2D仿射转换,例如,平移、旋转或缩放2D对象(请参阅2.4.2.1节)。对于未校准的透视图匹配方法,提供了应用于透视图的二维投影转换(参见第37页的2.4.2.2节)。最后,对于校准的透视图匹配方法,可以使用三维仿射转换(参见第38页的2.4.2.3节)。

2.4.2.1二维仿射变换

“仿射变换”是数学中描述一组变换的术语。图2.15显示了发生的类型,例如,在基于形状的匹配中:对象可以沿着两个轴平移(移动)、旋转和缩放。在图2.15d中,所有三个转换都是按顺序应用的。

注意,对于旋转和缩放,存在一个不动点,围绕它执行转换。它对应于第21页第2.1.2.1节中描述的参考点。在图2.15b中,例如,IC绕其中心旋转,在图2.15e中,IC绕其右上角旋转。这一点叫做不动点,因为它在变换中保持不变。

转换可以看作是一个数学指令,它定义了如何计算转换后目标点的坐标。幸运的是,你不必担心数学考试部分。HALCON提供了一组操作符,允许您以简单的方式指定和应用转换。

HALCON通过提供affine_trans_pixel、affine_trans_region、affine_trans_image和affine_trans_contour_xld操作符来转换像素、区域、图像和XLD轮廓。图2.15b的转换相当于:

affine_trans_region (IC, TransformedIC, ScalingRotationTranslation, \
                     'nearest_neighbor')

参数ScalingRotationTranslation是描述所需转换的所谓齐次转换矩阵。您可以通过逐步添加简单的转换来创建这个矩阵。首先,用hom_mat2d_identity创建一个单位矩阵。

hom_mat2d_identity (EmptyTransformation)

然后,用hom_mat2d_scale添加IC中心的缩放。

hom_mat2d_scale (EmptyTransformation, 0.5, 0.5, RowCenterIC, ColumnCenterIC, \
                  Scaling)

类似地,使用hom_mat2d_rotate和hom_mat2d_translate添加旋转和位移。

hom_mat2d_rotate (Scaling, rad(90), RowCenterIC, ColumnCenterIC, \
                  ScalingRotation)
hom_mat2d_translate (ScalingRotation, 100, 200, ScalingRotationTranslation)

请注意,在这些操作符中,坐标轴标记为x和y,而不是行和列!图2.15a阐明了这种关系。

变换矩阵也可以通过一种“逆向工程”来构造。换句话说,如果转换的结果已知对象的某些点,则可以确定相应的转换矩阵。例如,已知变换后的IC中心位置及其方向,可以通过运算符vector_angle_to_rigid得到相应的矩阵,然后用这个矩阵计算变换后的区域。

vector_angle_to_rigid (RowCenterIC, ColumnCenterIC, 0, \
                       TransformedRowCenterIC, TransformedColumnCenterIC, \
                       rad(90), RotationTranslation)
affine_trans_region (IC, TransformedIC, RotationTranslation, \
                     'nearest_neighbor')

如果需要转换像素、图像或轮廓,过程类似,但是您将分别应用运算符affine_trans_pixel、affine_trans_image或affine_trans_contour_xld,而不是affine_trans_region(参见第39页的2.4.3.1节)。

2.4.2.2 二维投影变换

二维投影变换矩阵描述一个透视投影,如图2.16所示。它由3*3个值组成。注意,如果最后一行包含值[0,0,1],则它对应于一个齐次变换矩阵,即,它描述了一个二维仿射变换,它是二维投影变换的一个特例。

HALCON提供了几个操作符来应用投影变换。与仿射变换类似,通过投影变换可以变换不同的HALCON结构例如像素(projective_trans_pixel)、区域(projective_trans_region)、图像(projective_trans_image)和XLD轮廓(projective_trans_contour_xld)。但现在,透视变形也被考虑到了。第51页的2.4.5节更详细地描述了一个二维投影变换的例子。

注意,在匹配前后,投影变换矩阵比仿射变换矩阵更容易处理,因为您不需要从对应的点创建一个变换矩阵,也不需要添加几个变换步骤。相反,投影变换矩阵是由一个算子直接返回的,该算子用于透视畸变对象的未校准匹配,并且可以直接应用上述其中一个变换。

2.4.2.3 三维仿射变换

关于三维仿射变换的详细信息可以在解决方案指南III-C中找到。在这里,我们简要总结了将校准后的透视图匹配方法的结果与从参考图像中获得的结构叠加所需要的信息。

HALCON的三维仿射变换主要是一个三维点到另一个三维点的变换。因此,与二维仿射或二维投影变换相比,它不能变换区域、图像或XLD轮廓。因此,您想要转换的任何2D结构,例如,为了显示匹配结果,在应用转换之前,必须将其分割为多个点。此外,这些点必须在世界坐标系(WCS)中可用(图2.17中的步骤1)。

要将参考图像中的一个点转换为WCS,需要摄像机参数和模型的参考位姿,它们描述了物体和摄像机之间的关系。两者通常都是通过摄像机校准获得的(请参阅解决方案指南III-C,第68页3.2节)。然后可以使用image_points_to_world_plane将图像点转换为WCS。或者,您可以使用contour_to_world_plane_xld将轮廓线转换为z = 0的平面,然后使用get_contour_xld获取轮廓线的各个点。注意,后一个操作符只返回x和y坐标的元组。因此,必须使用gen_tuple_const创建z坐标的另一个元组。这个元组必须具有与其他两个元组相同的元素数量,并且所有元素必须设置为0。

如果单个点在WCS中可用,则可以使用affine_trans_point_3d使用3D齐次转换矩阵对它们进行转换(图2.17中的步骤2)。在经过标定的透视匹配环境中,匹配结果是一个三维位姿,可以使用pose_to_hom_mat3d将其转换成相应的三维均匀变换矩阵。它描述了模型的世界坐标与在特定匹配中找到的模型实例的世界坐标之间的关系。它描述了模型的世界坐标与在特定匹配中找到的模型实例的世界坐标之间的关系。

使用affine_trans_point_3d转换3D点之后,可以使用project_3d_point将它们从WCS投影到搜索图像中(第38页图2.17中的步骤3)。这些图像点可以用来重建和显示初始结构,使用gen_contour_polygon_xld来重建轮廓。第54页2.4.6节将更详细地描述三维仿射变换的示例。

2.4.3 使用估计的二维位置和方向

对于一个严格的二维匹配的模型实例,估计的位置和方向(2D位姿)可以以不同的方式使用。它们可以用,例如,

  • 要显示找到的实例(第2.4.3.1节用于单个匹配,第3.3.5.1节用于多个匹配),
  • 调整其他检查任务的roi,例如测量(第42页2.4.3.2节),或
  • 对搜索图像进行转换,使对象定位在模板图像中(第46页第2.4.3.3节)。

所有这些应用程序都可以通过几行代码来实现,使用第35页2.4.2.1节中解释的仿射转换。

对于大多数匹配方法,匹配返回的位置和方向是与模型相关的。也就是说,返回的不是绝对位置,而是到参考点的距离。参考点由用于创建模型的ROI中心定义(参见图2.18a)。默认情况下,模型的参考点移动到坐标(0,0)。但即便如此,由于HALCON中的不同任务需要不同的图像坐标系统(像素精确区域的位置与亚像素精确XLD轮廓的位置相差0.5像素,见第44页),匹配返回的估计位置不能直接使用,而是为创建用于应用上述应用程序的转换矩阵而优化。此外,在模板图像中,对象被视为未旋转的,即其角度为0,即使它看起来是旋转的,如图2.18b所示。

2.4.3.1 显示匹配项

在很多情况下,特别是在匹配应用程序的开发过程中,在搜索图像中显示匹配结果是非常有用的。这可以通过不同的方法来实现。如果模型是由轮廓表示的,我们建议将XLD轮廓叠加到搜索图像上,因为XLD轮廓可以比区域更精确、更快地转换。此外,通过显示模型的轮廓,不仅可以显示找到的模型实例的位置和方向,而且还可以可视化与模型形状的偏差。

如果没有可用的轮廓,我们建议覆盖用于在搜索图像上创建模型的ROI。在某些情况下,附加的点可视化是合适的。例如,对于基于描述符的匹配,可以像第139页3.7.3节中描述的那样查询模型或找到的模型实例的兴趣点,并使用gen_cross_contour_xld进行显示。

下面我们将展示如何在搜索图像上叠加XLD轮廓或ROI。HDevelop程序示例solution_guide\matching\first_example_shape_match.hdev示例展示了可视化基于形状的匹配结果所需的步骤。

步骤1:访问包含模型的XLD轮廓

首先,使用create_shape_model创建模型。然后,使用get_shape_model_contours访问模型的XLD版本。

create_shape_model (ImageROI, NumLevels, 0, rad(360), 'auto', 'none', \
                    'use_polarity', 30, 10, ModelID)
get_shape_model_contours (ShapeModel, ModelID, 1)

步骤2:确定仿射变换

匹配使用操作符find_shape_model应用。只有匹配成功,可视化才是合理的。从而对匹配结果进行了检验。如果匹配失败,操作符将在Score等参数中返回空元组。如果匹配成功,则可以使用vector_angle_to_rigid算子从XLD轮廓的初始位置和方向以及匹配的位置和方向构造相关的反射仿射变换。注意,模型的初始XLD轮廓位于图像的原点,而不是在参考图像中模型的位置。因此,前两个参数设置为0。

find_shape_model (SearchImage, ModelID, 0, rad(360), 0.7, 1, 0.5, \
                  'least_squares', 0, 0.7, RowCheck, ColumnCheck, \
                  AngleCheck, Score)
if (|Score| == 1)
         vector_angle_to_rigid (0, 0, 0, RowCheck, ColumnCheck, AngleCheck, \
                                MovementOfObject)

步骤3:转换XLD

现在,使用操作符affine_trans_contour_xld对模型的XLD轮廓进行转换,并显示转换后的轮廓。第3.3节第67页的图3.3显示了搜索图像和重叠的XLD轮廓。

      affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, \
                                MovementOfObject)
      dev_display (ModelAtNewPosition

轮廓或区域投影的一般步骤是相同的。也就是说,在这两种情况下,都使用操作符vector_angle_to_rigid来获得描述模型与找到的模型实例之间关系的齐次变换矩阵(2D 单应矩阵)。作为输入,它需要轮廓的初始位置或转换的区域,模型的初始角度
(默认值为0),找到模型实例的位置,以及找到模型实例的角度。然后,运算符affine_trans_contour_xld或affine_trans_region分别使用返回的二维单应性变换轮廓或区域,使其位置和表示与找到的模型实例的位置和方向相对应。然后可以使用dev_display显示转换后的区域或轮廓。

轮廓投影与区域投影的主要区别在于轮廓或区域的初始位置。轮廓或区域的初始位置总是描述参考点的“相对”位置,即它到默认参考点的距离。参考点的默认位置为(0,0),即它是图像的原点,而不是模型在参考图像中的位置。但根据必须转换的结构,“相对”位置可能会发生变化。但根据必须转换的结构,“相对”位置可能会发生变化。而形状模型的XLD轮廓是由模型导出的,因此其参考点也是模型的参考点,在创建模型之前自然地定义了一个区域。因此,它的参考点描述的是模型在参考图像中的位置,而不是后来创建的模型的参考点。也就是说,操作符area_center为各自区域获得的值必须作为前两个参数传递给vector_angle_to_rigid,而不是(0,0)。

此外,如果您已经更改了模型的基准点(参见第21页的2.1.2节),则作为初始位置插入的值将以以下方式更改:如果您在更改基准点之后从模型查询XLD轮廓,则不会发生任何更改。初始位置仍然是(0,0),只有模型的另一部分作为参考点。如果你在查询XLD轮廓后改变参考点或如果你想改变一个地区,也自然是访问改变参考点之前,您必须添加初始参考点的值作为参考点的值。

2.4.3.2 调整其他检查任务的ROI

匹配结果可用于对齐其他图像处理步骤的ROI。即将它们相对于作为模型的图像部分进行定位。这种方法是适用的,例如,如果要检查的对象允许移动,或者如果要同时检查该对象的多个实例。

HDevelop示例程序solution_guide\matching\align_measurement.hdev,例如通过测量多个刀片的“牙齿”的宽度和距离,使用基于形状的匹配来检查多个刀片。

首先,创建一个形状模型,稍后将用于校准测量ROI。图2.19a为形状模型的模型ROI,形状模型由两个统一区域组成,图2.19b为对应的形状模型。

然后,检查任务的实现步骤如下:

步骤1:定位模型叶片的测量ROI

两个矩形测量ROI是用gen_rectangle2生成的,它们被放置在作为模型的刀片的牙齿上(见图2.19c)。

Rect1Row := 244
Rect1Col := 73
DistColRect1Rect2 := 17
Rect2Row := Rect1Row
Rect2Col := Rect1Col + DistColRect1Rect2
RectPhi := rad(90)
RectLength1 := 122
RectLength2 := 2
gen_rectangle2 (MeasureROI1, Rect1Row, Rect1Col, RectPhi, RectLength1, \
                RectLength2)
gen_rectangle2 (MeasureROI2, Rect2Row, Rect2Col, RectPhi, RectLength1, \
                RectLength2)

为了以后能够与模型的XLD轮廓一起对它们进行转换,使用move_region将它们移动到XLD模型上,XLD模型的参考点是图像的原点(图2.20a), area_center对该模型进行查询。请注意,在移动区域之前,必须关闭裁剪,否则将在图像“外部”移动的区域部分进行裁剪。模型ROI中心与矩形测量ROI中心之间的差值定义了测量ROI的新参考位置(见图2.20b)。

rea_center (ModelROI, Area, CenterROIRow, CenterROIColumn)
get_system ('clip_region', OriginalClipRegion)
set_system ('clip_region', 'false')
move_region (MeasureROI1, MeasureROI1Ref, -CenterROIRow, -CenterROIColumn)
move_region (MeasureROI2, MeasureROI2Ref, -CenterROIRow, -CenterROIColumn)
set_system ('clip_region', OriginalClipRegion)
DistRect1CenterRow := Rect1Row - CenterROIRow
DistRect1CenterCol := Rect1Col - CenterROIColumn
DistRect2CenterRow := Rect2Row - CenterROIRow
DistRect2CenterCol := Rect2Col - CenterROIColumn

步骤2:找到所有的刀片

现在,使用find_shape_model在搜索图像中搜索形状模型的所有实例。

find_shape_model (SearchImage, ModelID, 0, 0, 0.8, 0, 0.5, 'least_squares', \
                  0, 0.7, RowCheck, ColumnCheck, AngleCheck, Score)

步骤3:确定仿射变换

对于每个实例,即对于每个找到的剃须刀片,模型与找到的模型实例之间的转换用vector_angle_to_rigid进行计算,然后用affine_trans_contour_xld应用于XLD模型,使其位于搜索图像中找到的模型实例之上。

for i := 0 to |Score| - 1 by 1
    vector_angle_to_rigid (0, 0, 0, RowCheck[i], ColumnCheck[i], \
                           AngleCheck[i], MovementOfObject)
    affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, \
                              MovementOfObject)

步骤4:在相应的位置创建度量对象

然后,应用affine_trans_pixel计算测量ROI的相应位置,在这些位置上创建测量对象。

affine_trans_pixel (MovementOfObject, DistRect1CenterRow, \
                    DistRect1CenterCol, Rect1RowCheck, Rect1ColCheck)
affine_trans_pixel (MovementOfObject, DistRect2CenterRow, \
                    DistRect2CenterCol, Rect2RowCheck, Rect2ColCheck)
RectPhiCheck := RectPhi + AngleCheck[i]
gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, RectPhiCheck, \
                        RectLength1, RectLength2, Width, Height, \
                        'bilinear', MeasureHandle1)
gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, RectPhiCheck, \
                        RectLength1, RectLength2, Width, Height, \
                        'bilinear', MeasureHandle2)

注意,必须使用运算符affine_trans_pixel而不是affine_trans_point_2d,因为后者使用不同的坐标系。特别是,它使用了标准的图像参考系,其中一个位置对应于一个像素的中心(见图2.21,右)。相反,affine_trans_pixel、affine_trans_contour_xld、affine_trans_region和affine_trans_image操作符使用图2.21(左)所示的坐标系。

在示例应用程序中,单个刀片只被平移,而不是相对于模型位置旋转。因此,您可以使用算子translate_measure来转换测量对象本身,而不是对测量ROI应用完整的仿射转换,然后创建新的测量对象。示例程序包含相应的代码。通过修改程序顶部的一个变量,可以在这两个方法之间进行切换。

第五步:测量“牙齿”的宽度和距离

现在,实际的测量是使用measure_pair操作符执行的。

measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', \
               RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, \
               Amp21, Width1, Distance1)
measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', \
               RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, \
               Amp22, Width2, Distance2)

步骤6:检查测量结果

最后,对测量结果进行了检验。如果牙齿太短或完全缺失,此时就不会提取边缘,从而导致提取的边缘对数量不正确。在这种情况下,可以通过检查牙齿的距离来确定错误的位置。图2.19d显示了示例的检查结果。

NumberTeeth1 := |Width1|
if (NumberTeeth1 < 37)
    for j := 0 to NumberTeeth1 - 2 by 1
        if (Distance1[j] > 4.0)
            RowFault := round(0.5 * (RowEdge11[j + 1] + RowEdge21[j]))
            ColFault := round(0.5 * (ColEdge11[j + 1] + ColEdge21[j]))
            disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)

请注意,示例程序不能显示错误,如果它发生在第一颗或最后一颗牙齿。

2.4.3.3 调整搜索结果

前面的部分展示了如何使用匹配结果来确定所谓的正向转换。它用于将模型中的对象转换为搜索图像,或者分别将参考图像中指定的ROI转换为搜索图像。

您还可以确定将对象从搜索图像转换回参考图像的逆变换。通过这种转换,您可以对搜索图像(或其部分)进行调整,即将其转换为与参考图像中所匹配的对象相同的位置。如果下面的图像处理步骤对旋转不是不变的,例如OCR或变化模型,这种方法是有用的。

注意,通过对齐,图像只是旋转和平移。要消除透视或镜头畸变,例如,如果相机以斜角观察场景,则必须首先校正图像(更多信息请参阅91页的3.3.6节)。

逆变换

逆变换可以通过几个步骤来确定和应用。例如,HDevelop程序solution_guide\matching\rectify_results.hdev的任务是提取CD封面上的序列号(参见图2.22)。该匹配采用基于形状的匹配实现。

步骤1:计算逆变换

可以使用操作符hom_mat2d_invert轻松地进行逆变换。

vector_angle_to_rigid (CenterModelROIRow, CenterModelROIColumn, 0, \
                       RowMatch, ColumnMatch, AngleMatch, \
                       MovementOfObject)
hom_mat2d_invert (MovementOfObject, InverseMovementOfObject)

注意,与前几节不同,转换是根据参考点的绝对坐标计算的,因为结果必须转换成参考图像中显示的那样。

步骤2:校正搜索图像

使用运算符affine_trans_image对搜索图像进行逆变换。图2.22d显示了不同CD得到的经过校正的图像。未定义的像素用灰色标记。

affine_trans_image (SearchImage, RectifiedSearchImage, \
                    InverseMovementOfObject, 'constant', 'false')

Step 3: 提取数据

序列号在原始ROI中定位正确,可以通过blob分析进行提取。图2.22e显示了结果,它可以,例如,用作OCR的输入。

reduce_domain (RectifiedSearchImage, NumberROI, RectifiedNumberROIImage)
threshold (RectifiedNumberROIImage, Numbers, 0, 128)
connection (Numbers, IndividualNumbers)

不幸的是,操作符affine_trans_image转换整个图像,即使它的域受到操作符reduce_domain的限制。因此,在时间关键的应用程序中,可能需要在转换搜索图像之前对其进行裁剪。

图像裁剪

下面将描述图像裁剪所需的步骤。此外,它们在图2.23中可视化。

步骤1:裁剪搜索图像

首先,通过运算符smallest_rectangle1计算出围绕转换后数字ROI的最小轴平行矩形。然后,使用crop_rectangle1将搜索图像裁剪到这一部分。图2.23b显示了叠加在灰色矩形上的结果图像,便于与后续图像进行比较。

affine_trans_region (NumberROI, NumberROIAtNewPosition, \
                     MovementOfObject, 'nearest_neighbor')
smallest_rectangle1 (NumberROIAtNewPosition, RowRect1, ColumnRect1, \
                     RowRect2, ColumnRect2)
crop_rectangle1 (SearchImage, CroppedSearchImage, RowRect1, ColumnRect1, \
                 RowRect2, ColumnRect2)

步骤2:创建一个扩展仿射转换

实际上,裁剪可以解释为一种附加的仿射变换,特别是通过裁剪矩形左上角的负坐标进行传输(见图2.23a)。因此,我们将这个转换添加到使用操作符hom_mat2d_translate描述对象移动的转换中。然后,我们用运算符hom_mat2d_invert逆变换这个扩展变换。

hom_mat2d_translate (MovementOfObject, -RowRect1, -ColumnRect1, \
                     MoveAndCrop)
hom_mat2d_invert (MoveAndCrop, InverseMoveAndCrop)

步骤3:转换裁剪后的图像

使用反向扩展变换,裁剪后的图像可以很容易地通过运算符affine_trans_image(图2.23c)进行校正,然后降至原始数字ROI(图2.23d),从而提取数字。

affine_trans_image (CroppedSearchImage, RectifiedROIImage, \
                    InverseMoveAndCrop, 'constant', 'true')
reduce_domain (RectifiedROIImage, NumberROI, RectifiedNumberROIImage)

2.4.4使用估计的二维尺度

上一节描述的转换仅包含平移和旋转。对于一些匹配方法,搜索的对象可以在搜索图像中进行额外的缩放。例如,透视图,变形匹配返回一个投影变换矩阵(二维单应矩阵)或三维姿势。也就是说,缩放是隐式返回的,并且已经作为转换矩阵的一部分可用。相反,对于基于形状的匹配,缩放会显式返回,而且还不是转换矩阵的一部分。通常,缩放可以类似地用于位置和方向。但是,没有像vector_angle_to_rigid这样方便的操作符来创建包含缩放的仿射转换。因此,必须单独添加缩放。

HDevelop 例程hdevelop\Matching\Shape-Based\find_aniso_shape_model.hdev演示了如何向转换矩阵添加缩放。该例程的任务是找到在行和列方向上显示独立尺寸变化的SMD电容器。也就是说,需要一个各向异性的标度。

步骤1:创建模型并访问模型轮廓

首先,要获得一个模型,需要创建一个包含圆角矩形的合成模板图像,如第23页的2.1.3节所述(见图2.24,左)。从这个图像中一个各向异性的模板通过算子create_aniso_shape_model派生出。通过get_shape_model_contours查询实际匹配后将投影到搜索图像中的模型轮廓。

gen_contour_polygon_rounded_xld (Contour, [50,100,100,50,50], [50,50,150, \
                                 150,50], [6,6,6,6,6], 1)
gen_image_const (Image, 'byte', 200, 150)
paint_xld (Contour, Image, ImageModel, 128)
create_aniso_shape_model (ImageModel, 'auto', -rad(10), rad(20), 'auto', \
                          0.9, 1.7, 'auto', 0.9, 1.1, 'auto', 'none', \
                          'use_polarity', 'auto', 20, ModelID)
get_shape_model_contours (ModelContours, ModelID, 1)

步骤2:找到模型

然后,应用与find_aniso_shape_model的实际匹配,在搜索图像中找到了该模型的几个实例。

read_image (Image, 'smd/smd_capacitors_' + J$'02d')
find_aniso_shape_model (Image, ModelID, -rad(10), rad(20), 0.9, 1.7, \
                        0.9, 1.1, 0.7, 0, 0.5, 'least_squares', 0, 0.8, \
                        Row, Column, Angle, ScaleR, ScaleC, Score)

步骤3:转换模型轮廓

对于每个找到的模型实例,使用hom_mat2d_identity创建一个转换矩阵。然后,使用hom_mat2d_scale添加缩放。在这里,插入先前创建的转换矩阵、匹配返回的缩放因子和缩放参考点。在这种情况下,行方向和列方向的比例因子是不同的。在均匀缩放的情况下,两个值是相同的。一般来说,与旋转相似(比较第39页的2.4.3节),缩放是围绕ROI的中心执行的——如果您没有更改参考点的话。如图2.25所示,ROI的中心与IC的中心不重合。在HDevelop程序中,缩放是在平移和旋转之前进行的。

因此,缩放的参考点对应于模型轮廓的参考点,模型轮廓的参考点默认为(0,0)。如果在平移和旋转之后执行缩放,例如,如果使用vector_angle_to_rigid创建一个包含平移和旋转的仿射变换,那么必须使用匹配的位置作为参考点。一个例子是solution_guide\match \multiple_scale .hdev。

在变换矩阵中加入旋转和平移后,利用affine_trans_contour_xld将模型轮廓变换并投影到搜索图像中相应的SMD电容上(见第50页右侧图2.24)。

for I := 0 to Num - 1 by 1
    hom_mat2d_identity (HomMat2D)
    hom_mat2d_scale (HomMat2D, ScaleR[I], ScaleC[I], 0, 0, HomMat2D)
    hom_mat2d_rotate (HomMat2D, Angle[I], 0, 0, HomMat2D)
    hom_mat2d_translate (HomMat2D, Row[I], Column[I], HomMat2D)
    affine_trans_contour_xld (ModelContours, ContoursTrans, HomMat2D)
endfor

2.4.5使用估计的二维单应矩阵

在应用一种未校准的透视匹配方法时,与纯二维匹配方法相比,不返回位置、方向和比例尺,只返回投影变换矩阵。它们可以用于应用投影变换,例如,通过将参考图像的结构叠加到搜索图像中的匹配上来可视化匹配结果。注意,不同HALCON结构如,像素、区域、图像或XLD轮廓可以通过这种方式进行转换(参见第37页的2.4.2.2节)。

根据选择的匹配方法,通常会转换不同的结构。对于未标定的透视变形匹配,例如,将模型轮廓转换为可视化匹配,而对于未标定的基于描述符的匹配,用于创建模型的区域可以进行转换和可视化。

在HDevelop示例程序hdevelop\Applications\Traffic-Monitoring\detect_road_signs.hdev中给出了一个在未校准的透视图可变形匹配中进行投影转换的示例(参见图2.26)。

步骤1:找到透视变形模式

其中,使用find_planar_uncalib_deformable_model在图像中搜索路标模型,该模型返回投影变换矩阵HomMat2D。

find_planar_uncalib_deformable_model (ImageChannel, Models[Index2], 0, \
                                      0, ScaleRMin[Index2], \
                                      ScaleRMax[Index2], \
                                      ScaleCMin[Index2], \
                                      ScaleCMax[Index2], 0.85, 1, 0, 2, \
                                      0.4, [], [], HomMat2D, Score)

步骤2:转换模型轮廓

匹配之后,使用get_deformable_model_contours从模型中查询轮廓。默认情况下,返回的轮廓位于参考图像的原始位置。因此,为了使匹配的位置可视化,必须使用返回的投影变换矩阵对轮廓进行变换。通过算子projective_trans_contour_xld实现。

get_deformable_model_contours (ModelContours, Models[Index2], 1)
projective_trans_contour_xld (ModelContours, ContoursProjTrans, \
                              HomMat2D)
dev_display (ContoursProjTrans)

HDevelop示例程序hdevelop \Applications\ Object-Recognition-2D\ detect_brochure_pages.hdev是一个未校准的基于描述符匹配后进行投影转换的例子(参见图2.27)。

步骤1:找到描述符模型

其中,投影变换矩阵HomMat2D由find_uncalib_descriptor_model返回。

find_uncalib_descriptor_model (ImageGray, ModelIDs[Index2], \
                               'threshold', 800, \
                               ['min_score_descr', \
                               'guided_matching'], [0.003,'on'], \
                               0.25, 1, 'num_points', HomMat2D, \
                               Score)

步骤2:访问并可视化感兴趣的点

使用get_descriptor_model_points查询兴趣点。与只能查询模型的透视图变形模型的轮廓不同,描述符模型的点也可以查询特定匹配(设置为“搜索”)。因此,它们不再需要被转换。

get_descriptor_model_points (ModelIDs[Index2], 'search', 0, Row, \
                             Col)
gen_cross_contour_xld (Cross, Row, Col, 6, 0.785398)

步骤3:转换模型区域及其角点

可以使用投影变换,例如,用于创建模型的变换区域也应该为匹配可视化,或者如果该区域的变换角点是使用需要的结果来检查区域边缘之间的角度。

projective_trans_region (Rectangle, TransRegion, HomMat2D, \
                         'bilinear')
projective_trans_pixel (HomMat2D, RowRoi, ColRoi, RowTrans, \
                        ColTrans)
angle_ll (RowTrans[2], ColTrans[2], RowTrans[1], ColTrans[1], \
          RowTrans[1], ColTrans[1], RowTrans[0], ColTrans[0], \
          Angle)
Angle := deg(Angle)
if (Angle > 70 and Angle < 110)
    dev_display (TransRegion)
    dev_display (Cross)
endif

2.4.6使用估计的三维姿态

应用一种标定的透视图匹配方法时,将返回三维位姿,该位姿在世界坐标下解析模型与找到的模型实例之间的关系。要使用这种姿态,例如,通过将参考图像的结构叠加在搜索图像的匹配上来可视化匹配结果,需要进行三维仿射变换(参见第38页的2.4.2.3节)。

根据所选择的匹配方法,搜索图像可能需要不同于参考图像的结构。对于校准的透视图,变形匹配通常使用模型的轮廓来可视化匹配。也就是说,轮廓必须从参考图像转换为搜索图像。对于校准后的基于描述符的匹配,模型的兴趣点可以直接查询到搜索结果,即,不需要对模型表示形式进行转换。但是,如果用于创建模型的区域也应该进行转换,则可能需要进行转换。

在HDevelop示例程序hdevelop\Applications\Position-Recognition-3D\locate_car_door.hdev中给出了一个在校准的透视可变形匹配环境中进行三维仿射变换的例子(参见图2.28)。在这里,使用find_planar_calib_deformable_model在图像中搜索车门的一部分,该图像返回3D 姿势。

find_planar_calib_deformable_model (ImageReducedSearch, ModelID, -0.2, \
                                    0.5, 1, 1, 0.8, 1, 0.6, 1, 1, 3, \
                                    0.6, [], [], Pose, CovPose, Score)

为了实现匹配的可视化,需要在搜索图像的匹配上叠加模型轮廓。这个转换分三个步骤实现。

步骤1:用于可视化的预处理

首先,算子set_deformable_model_param用于设置轮廓返回“world”的坐标系统。调用算子get_deformable_model_contours时,将在世界坐标系(WCS)中返回轮廓。在本例中,这一步是在实际匹配之前实现的。

set_deformable_model_param (ModelID, \
                            'get_deformable_model_contours_coord_system', \
                            'world')
get_deformable_model_contours (ModelContours, ModelID, 1)

步骤2:对轮廓点进行三维仿射变换

在WCS中,三维仿射变换根据匹配返回的三维姿态对轮廓的各个点进行变换。在应用这个变换之前,必须使用pose_to_hom_mat3d将3D位姿转换为一个三维同构变换矩阵HomMat3D。

for Index1 := 0 to |Score| - 1 by 1
    tuple_select_range (Pose, Index1 * 7, ((Index1 + 1) * 7) - 1, \
                        PoseSelected)
pose_to_hom_mat3d (PoseSelected, HomMat3D)

此外,由于三维仿射变换不能应用于二维轮廓,现在WCS的x-y平面上可用的轮廓必须分割成点。这是通过算子get_contour_xld实现的,它返回x坐标的元组和y坐标的元组。为了获得三维坐标,创建了具有相同数量元素的z坐标的元组,其中所有值都为0。

gen_empty_obj (FoundContour)
for Index2 := 1 to NumberContour by 1
    select_obj (ModelContours, ObjectSelected, Index2)
    get_contour_xld (ObjectSelected, Y, X)
    Z := gen_tuple_const(|X|,0.0)

这些3D点现在使用affine_trans_point_3d通过三维仿射变换进行转换。

affine_trans_point_3d (HomMat3D, X, Y, Z, Xc, Yc, Zc)

步骤3:将点投影到搜索图像中,重构轮廓

然后利用project_3d_point将转换后的三维点投影到搜索图像中,利用gen_contour_polygon_xld重构轮廓。

              project_3d_point (Xc, Yc, Zc, CamParam, R, C)
              gen_contour_polygon_xld (ModelWorld, R, C)
              concat_obj (FoundContour, ModelWorld, FoundContour)
       endfor
       dev_display (FoundContour)
endfor

在HDevelop示例程序hdevelop\Applications\Object-Recognition-2D\locate_cookie_box.hdev中给出了基于校准描述符匹配的三维仿射变换的一个例子,在137页的3.7.1节中有更详细的描述。其中,利用image_points_to_world_plane将受影响的图像点,特别是用于构建描述符模型的矩形ROI的角点转换为WCS。

2.4.7关于分数

不同匹配方法返回的分数具有不同的含义。对于基于灰度值的匹配,只返回灰度值与最佳匹配的平均偏差(至少对于操作符best_match_*),不返回任何得分。对于基于相关性的匹配,分数由模式与图像之间的归一化互相关决定。

使用轮廓的方法,特别是基于形状的匹配和局部或透视变形匹配分数是0和1之间的数字,表示在搜索图像中可见的显示模型的多少是。也就是说,如果模型的一半被遮挡,分数不能大于0.5。注意,除了对应轮廓点的纯数量外,还存在其他因素对分数的影响,如轮廓的方向(参见第22页第2.1.2.2节和第80页第3.3.4.3节)。

对于基于组件的匹配,分数有相似的含义,但是这里必须区分两种类型的分数。一方面,返回单个组件的得分。在这里,分数再次主要显示了组件在图像中有多少是可见的。另一方面,返回整个组件模型的得分。这是通过对单个组件的评分值的加权平均值确定的。权重是根据各个组件中的模型点的数量来执行的。

根据所选的分数类型,基于描述符匹配分数值的不同含义是可用的(参见140页的3.7.3.2节)。

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值