Halcon例程学习,基于形状的模板匹配align_measurements学习

一、代码主要思路为

  1. 初始化和模型创建

    • 首先,通过读取一个示例图像razors1,选择一个包含剃须刀片的区域作为模板,并计算该区域的质心。这一步是为后续的形状模型创建准备模板对象。
    • 使用选定的区域,通过create_generic_shape_model创建一个通用形状模型(Generic Shape Model)。接着,设置模型的一些参数,如金字塔层数(num_levels)、优化方法(optimization)、对比度阈值(contrast_high)等,并使用train_generic_shape_model对模型进行训练。这样,模型就学会了剃须刀片的典型特征。
  2. 测量区域定义

    • 定义了两个矩形区域(MeasureROI1MeasureROI2),这些区域对应于剃须刀片上需要测量的部分,例如刀刃间的距离或宽度。这些测量区域会在找到的每个刀片上应用,以检查其尺寸是否符合标准。
  3. 形状匹配和测量

    • 读取另一张待检测的图像razors2,并在其中查找与模型匹配的对象。通过find_generic_shape_model执行形状匹配,寻找图像中与模型相似的剃须刀片。
    • 对于每个找到的匹配项,代码计算一个仿射变换矩阵,将模型轮廓和测量区域映射到匹配对象的位置。这里提供了两种方式来获取变换矩阵,并展示了如何通过变换后的测量区域来测量剃须刀片的特性,比如刀片间的距离。
    • 使用measure_pairs函数对每把刀片上的测量区域进行边缘检测,进而计算出刀片间“牙齿”的数量和间距,以此来判断刀片的质量是否合格。如果发现间距异常(超过4.0单位),则标记该位置为缺陷,并在图像上显示红色矩形提示。
  4. 结果展示和交互

    • 在匹配和测量过程中,使用了多个stop命令,这通常是在Halcon的交互式开发环境(HDevelop)中用于暂停程序执行,以便用户可以查看当前处理结果并进行交互。
    • 最后,程序输出一条结束信息,并通过dev_update_on重新启用窗口更新,允许用户查看最终的处理结果。

通过形状匹配技术自动定位图像中的剃须刀片,然后通过预定义的测量区域对刀片的关键尺寸进行精确测量,从而实现对产品质量的自动检测和缺陷识别。

二、具体代码注释如下

* ------------------------------------------------------------------------------------------------
* This example program uses shape-based matching to align ROIs for the measure
* tool, which then inspects individual razor blades.
* The program can be run in two modes:
*   (1) with the full affine transformation
*   (2) using translate_measure
* Modify the next line to switch between the modes.
*本示例程序使用基于形状的匹配来对齐测量工具的ROI,以检查个别剃刀片。
* 该程序可以在两种模式下运行:
*   (1) 使用完整的仿射变换
*   (2) 使用translate_measure
* 修改下一行以在模式之间切换
USING_TRANSLATE_MEASURE := 0
* ------------------------------------------------------------------------------------------------
* General configuration of HDevelop.
* HDevelop的通用配置
dev_update_off ()
read_image (ModelImage, 'razors1')
* 获取图像指针及其参数
get_image_pointer1 (ModelImage, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'white', WindowHandle)
dev_set_part (0, 0, Height - 1, Width - 1)
dev_display (ModelImage)
dev_set_color ('cyan')
dev_set_draw ('margin')
dev_set_line_width (2)
stop ()
* -------------------  Start of the application  ----------------
* Select the model object.
* 选择模型对象
Row1 := 46
Column1 := 57
Row2 := 79
Column2 := 94
* 创建两个矩形ROI区域
gen_rectangle1 (ROIPart1, Row1, Column1, Row2, Column2)
gen_rectangle1 (ROIPart2, Row1 + 364, Column1 + 13, Row2 + 364, Column2 + 13)
* 将两个region合并为一个region
union2 (ROIPart1, ROIPart2, ModelROI)
area_center (ModelROI, Area, CenterROIRow, CenterROIColumn)
dev_display (ModelImage)
dev_display (ModelROI)
stop ()
* 
* Create the model.
* 创建模型
* 将图像减少到ROI区域
reduce_domain (ModelImage, ModelROI, ImageROI)
create_generic_shape_model (ModelID)
* 设置模型参数金字塔层数为4,优化方法为none,对比度阈值为30
set_generic_shape_model_param (ModelID, 'num_levels', 4)
set_generic_shape_model_param (ModelID, 'optimization', 'none')
set_generic_shape_model_param (ModelID, 'contrast_high', 30)
* 基于提供的ImageROI,训练出一个能够识别具有相似形状特征的对象的模型
train_generic_shape_model (ImageROI, ModelID)
* 要从模型中获取轮廓信息存储在ModelContours中
get_generic_shape_model_object (ModelContours, ModelID, 'contours')
* 生成一个恒等变换矩阵
hom_mat2d_identity (HomMat2DModelContours)
* 行平移CenterROIRow,列平移CenterROIColumn,生成平移后矩阵HomMat2DModelContours
hom_mat2d_translate (HomMat2DModelContours, CenterROIRow, CenterROIColumn, HomMat2DModelContours)
* 将ModelContours经HomMat2DModelContours矩阵变换,生成ModelContoursTranslated
affine_trans_contour_xld (ModelContours, ModelContoursTranslated, HomMat2DModelContours)
dev_clear_window ()
dev_set_color ('blue')
dev_display (ModelContoursTranslated)
stop ()
* 
* Create variables describing the measurement ROIs and display them.
* 创建描述测量ROI的变量并显示它们
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)
dev_display (ModelImage)
dev_set_color ('yellow')
dev_display (MeasureROI1)
dev_display (MeasureROI2)
* Translate measurement ROIs to lie on XLD model (without clipping).
* 平移测量ROI以位于XLD模型上(无剪切)
* 获取裁剪区域的设置信息
get_system ('clip_region', OriginalClipRegion)
* 设置不开启裁剪区域
set_system ('clip_region', 'false')
move_region (MeasureROI1, MeasureROI1Ref, -CenterROIRow, -CenterROIColumn)
move_region (MeasureROI2, MeasureROI2Ref, -CenterROIRow, -CenterROIColumn)
* 设置裁剪区域的设置为OriginalClipRegion
set_system ('clip_region', OriginalClipRegion)
DistRect1CenterRow := Rect1Row - CenterROIRow
DistRect1CenterCol := Rect1Col - CenterROIColumn
DistRect2CenterRow := Rect2Row - CenterROIRow
DistRect2CenterCol := Rect2Col - CenterROIColumn
if (USING_TRANSLATE_MEASURE != 0)
    * Measure objects are created only once in advance and then translated later.
    * 仅在提前创建测量对象,然后再进行平移
    * 创建测量区域
    gen_measure_rectangle2 (Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
    gen_measure_rectangle2 (Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
endif
stop ()
* 
* Find the objects in another image.
* 在另一张图像中找到对象
read_image (SearchImage, 'razors2')
dev_display (SearchImage)
* Set the search parameters.
* 设置搜索参数
set_generic_shape_model_param (ModelID, 'min_contrast', 10)
set_generic_shape_model_param (ModelID, 'angle_start', 0.0)
set_generic_shape_model_param (ModelID, 'angle_end', 0.0)
set_generic_shape_model_param (ModelID, 'max_overlap', 0.0)
set_generic_shape_model_param (ModelID, 'min_score', 0.8)
set_generic_shape_model_param (ModelID, 'greediness', 0.7)
* 查找图像中与预定义的通用形状模型匹配的对象
find_generic_shape_model (SearchImage, ModelID, MatchResultID, NumMatchResult)
if (NumMatchResult > 0)
    * For visualization: Display results from left to right 
    * (increasing column values) instead of displaying the matches
    * in order of increasing scores.
    * 为了可视化:从左到右显示结果(增加列值)而不是按得分顺序显示匹配项
    * 从所有找到的结果中提取具体信息
    get_generic_shape_model_result (MatchResultID, 'all', 'column', Column)
    * 将列排序
    Indices := sort_index(Column)
    for I := 0 to NumMatchResult - 1 by 1
        * Determine the affine transformation.
        * For demonstration purpose we do this in different ways.
        * Way 1: Using vector_angle_to_rigid.
        * 为了可视化:从左到右显示结果(增加列值)而不是按得分顺序显示匹配项
        get_generic_shape_model_result (MatchResultID, Indices[I], 'row', RowCheck)
        get_generic_shape_model_result (MatchResultID, Indices[I], 'column', ColumnCheck)
        get_generic_shape_model_result (MatchResultID, Indices[I], 'angle', AngleCheck)
        vector_angle_to_rigid (0, 0, 0, RowCheck, ColumnCheck, AngleCheck, MovementOfObject)
        affine_trans_contour_xld (ModelContours, ModelAtNewPosition, MovementOfObject)
        dev_display (ModelAtNewPosition)
        * Way 2: Directly extract the found instance.
        * 直接提取找到的实例
        get_generic_shape_model_result (MatchResultID, Indices[I], 'hom_mat_2d', MovementOfObject)
        get_generic_shape_model_result_object (ModelAtNewPosition, MatchResultID, Indices[I], 'contours')
        * 
        * Measure width and distance of the teeth.
        * 测量齿的宽度和距离
        * Display the moved ROIs.
        * 显示移动后的ROI
        affine_trans_region (MeasureROI1Ref, MeasureROI1AtNewPosition, MovementOfObject, 'constant')
        affine_trans_region (MeasureROI2Ref, MeasureROI2AtNewPosition, MovementOfObject, 'constant')
        dev_display (MeasureROI1AtNewPosition)
        dev_display (MeasureROI2AtNewPosition)
        affine_trans_pixel (MovementOfObject, DistRect1CenterRow, DistRect1CenterCol, Rect1RowCheck, Rect1ColCheck)
        affine_trans_pixel (MovementOfObject, DistRect2CenterRow, DistRect2CenterCol, Rect2RowCheck, Rect2ColCheck)
        if (USING_TRANSLATE_MEASURE != 0)
            * Translate the already created measure objects.
            * 平移已经创建的测量对象
            * 将MeasureHandle1移动到(Rect1RowCheck, Rect1ColCheck)
            translate_measure (MeasureHandle1, Rect1RowCheck, Rect1ColCheck)
            translate_measure (MeasureHandle2, Rect2RowCheck, Rect2ColCheck)
            * 测量两个平行边缘之间距离
            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)
        else
            * Create new measure objects and destroy them after the measurement.
            * 创建新的测量对象并在测量后销毁它们
            RectPhiCheck := RectPhi + AngleCheck
            gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1)
            gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2)
            * 
            * Perform the measurement.
            * 开始测量
            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)
        endif
        * 
        * Check for too short or missing teeth.
        * 检查过短或消失的齿
        NumberTeeth1 := |Width1|
        NumberTeeth2 := |Width2|
        dev_set_color ('red')
        * 第一组牙的齿数小于37
        if (NumberTeeth1 < 37)    
            * // 遍历第一组牙齿间的所有距离
            for J := 0 to NumberTeeth1 - 2 by 1
                * 检查当前间隙是否大于4
                if (Distance1[J] > 4.0)
                    * 确定位于两点之间的行列坐标
                    RowFault := round(0.5 * (RowEdge11[J + 1] + RowEdge21[J]))
                    ColFault := round(0.5 * (ColEdge11[J + 1] + ColEdge21[J]))
                    * 用4*4的窗口标记缺陷位置
                    disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
                    * 打开新窗口
                    dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
                     *设置放大窗口的显示区域,以异常点为中心的20x20像素区域
                    dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
                    * 显示原图
                    dev_display (SearchImage)
                    * 放大窗口中标记缺陷
                    disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
                    stop ()
                    dev_close_window ()
                    dev_set_part (0, 0, Height - 1, Width - 1)
                endif
            endfor
        endif
        * 逻辑同上
        if (NumberTeeth2 < 37)
            for J := 0 to NumberTeeth2 - 2 by 1
                if (Distance2[J] > 4.0)
                    RowFault := round(0.5 * (RowEdge12[J + 1] + RowEdge22[J]))
                    ColFault := round(0.5 * (ColEdge12[J + 1] + ColEdge22[J]))
                    disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
                    dev_open_window (0, Width + 20, 80, 80, 'black', WindowHandleZoom)
                    dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
                    dev_display (SearchImage)
                    disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
                    stop ()
                    dev_close_window ()
                    dev_set_part (0, 0, Height - 1, Width - 1)
                endif
            endfor
        endif
        dev_set_color ('yellow')
        stop ()
    endfor
endif
* -------------------  End of the application  -----------------
dev_disp_text ('End of program', 'window', 'bottom', 'right', 'black', [], [])
dev_update_on ()

三、关键算子解释

(1)get_generic_shape_model_object( : Object : ModelID, GenParamName : )

Object:输出参数,接收从形状模型中提取出的对象。

ModelID:输入参数,训练好的形状模型的标识符。

GenParamName:输入参数,指定想要从模型中提取哪种类型的对象或者信息,具体可提取的参数参考官方手册。

算子说明:提取和操作形状模型内部的数据。

(2)get_system( : : Query : Information)

Query:输入参数,表示你想要查询的系统参数或状态的名称,可以是关于显示设置(如窗口大小、背景色)、内存管理、调试选项、设备状态等,具体可查询的参数参考官方手册。

Information:输出参数,接收从系统中查询到的相应参数的当前值或状态信息。

算子说明:用于获取当前系统配置或状态信息。

(3)set_system( : : SystemParameter, Value : )

SystemParameter:输入参数,表示想要设置的系统参数的名称。

Value:输入参数,为指定系统参数设置的新值。

算子说明:设置系统指定参数的值。

(4)gen_measure_rectangle2( : : Row, Column, Phi, Length1, Length2, Width, Height, Interpolation : MeasureHandle)

Row、Column、Phi:测量矩形中心点的行列坐标及矩形的旋转弧度。

Length1、Length2:测量矩形宽度和高度的一半。

Width:Height:后续要处理图象的宽高。

Interpolation:插值方法,具体方法参考官方例程。

MeasureHandle:输出创建矩形的句柄。

算子说明:初始化一个具有特定位置、大小、旋转角度和线条宽度的测量矩形。

(5)translate_measure( : : MeasureHandle, Row, Column : )

MeasureHandle:输入参数,之前通过如gen_measure_rectangle2等算子创建的测量对象的句柄,这个句柄是进行测量操作的关键,包含了所有关于测量配置的信息。

Row、Column:输入参数,表示沿图像的行方向、列方向的偏移量。

算子说明:根据给定的行偏移(Row)和列偏移(Column)来移动一个已经创建好的测量对象(如测量矩形、圆等)。这个操作允许你在图像的不同位置重复使用相同的测量设置,而无需重新创建测量对象。

(6)measure_pairs(Image : : MeasureHandle, Sigma, Threshold, Transition, Select : RowEdgeFirst, ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond, AmplitudeSecond, IntraDistance, InterDistance)

Image:输入图像,是需要进行测量的图像。

MeasureHandle:输入参数,是由gen_measure_rectangle2等函数创建的测量对象句柄。通常是一对或多对测量矩形,用于定义测量的区域。

Sigma:输入参数,表示高斯滤波器的标准差,用于边缘增强前的图像平滑处理。较大的值会使边缘变得更宽,更易于检测,但可能降低定位精度。

Threshold:输入参数,边缘检测的阈值,高于此阈值的边缘响应会被认为是有效边缘。

Transition:输入字符串,可选值为'positive', 'negative', 或 'both',指定了要检测的边缘类型。正值边缘对应于从暗到亮的过渡,负值边缘反之,'both'则同时检测两种过渡。

Select:输入参数,决定如何选择边缘对进行测量。可以是 'all', 'first', 'last', 'nearest', 'best',具体影响边缘对的选取规则。

RowEdgeFirst、ColumnEdgeFirst、AmplitudeFirst:输出参数,分别为第一组边缘的行坐标、列坐标和幅度值的向量,表示检测到的第一组边缘的具体位置和边缘幅度。

RowEdgeSecond、ColumnEdgeSecond、AmplitudeSecond:输出参数,分别为第二组边缘的行坐标、列坐标和幅度值的向量,表示检测到的第二组边缘的具体位置和边缘幅度。

IntraDistance:输出参数,表示每一组内边缘之间的距离,即测量矩形内部边缘对的距离。

InterDistance:输出参数,表示两组测量对象(如两个矩形)之间对应边缘的相互距离,如槽宽或厚度测量结果。

算子说明:在一对或多对测量对象(如由gen_measure_rectangle2创建的测量矩形)之间进行边缘检测和距离测量。

四、其中一些算子在上篇基于形状的模板匹配中已经记录

基于形状的模板匹配,Halcon例程adapt_shape_model_high_noise学习-CSDN博客

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值