Halcon 3D 表面匹配基于形状

发布于:2025-05-01 ⋅ 阅读:(65) ⋅ 点赞:(0)

prepare_object_model_3d 准备 3D 物体模型

prepare_object_model_3d( : : ObjectModel3D, Purpose, OverwriteData, GenParamName, GenParamValue : )


    ObjectModel3D
        类型: object_model_3d(-array)(integer)
        描述: 3D对象模型的句柄。这是对正在处理的3D对象的引用。

    Purpose(用途)
        类型: string → (string)
        描述: 3D对象模型的用途。
        默认值: 'shape_based_matching_3d'
        建议值: 'shape_based_matching_3d', 'segmentation', 'distance_computation'

    OverwriteData(覆盖数据)
        类型: string → (string)
        描述: 指定是否覆盖已存在的数据。
        默认值: 'true'
        可选值: 'false', 'true'

    GenParamName(通用参数名称)
        类型: attribute.name-array → (string / real / integer)
        描述: 通用参数的名称列表。
        默认值: []
        可选值: 'distance_to', 'max_area_holes', 'max_distance', 'method', 'sampling_dist_abs', 'sampling_dist_rel'

    GenParamValue(通用参数值)
        类型: attribute.value-array → (string / real / integer)
        描述: 通用参数的值列表。
        默认值: []
        建议值: 0, 1, 100, 'auto', 'triangles', 'points', 'primitive', 'kd-tree', 'voxel', 'linear', 0.01, 0.03

ObjectModel3D: 表示3D对象模型的句柄。通常用于标识和操作特定的3D模型。
Purpose: 定义该3D模型的用途,例如基于形状的匹配 (shape_based_matching_3d)、分割 (segmentation) 或距离计算 (distance_computation)。
OverwriteData: 决定是否覆盖已有数据。如果设置为 'true',则会替换现有数据;如果为 'false',则保留原有数据。
 GenParamName 和 GenParamValue: 这两个参数成对出现,用于指定通用参数的名称和对应的值。例如:
        'distance_to': 计算距离的目标。
        'max_area_holes': 最大孔洞面积。
        'method': 使用的方法,如 'kd-tree''voxel'

read_shape_model_3d — 读取3D匹配模型

read_shape_model_3d( : : FileName : ShapeModel3DID)

    FileName
        类型: filename.read → (string)
        描述: 包含 3D 形状模型的文件名(包括路径)。
        文件扩展名: .sm3
        示例: "model.sm3""C:/models/example.sm3"

输出参数 (Output Parameters)

    ShapeModel3DID
        类型: shape_model_3d → (integer)
        描述: 读取的 3D 形状模型的句柄。此句柄用于后续处理和操作。

create_shape_model_3d 准备要匹配的3D模型

create_shape_model_3d( : : ObjectModel3D, CamParam, RefRotX, RefRotY, RefRotZ, OrderOfRotation, LongitudeMin, LongitudeMax, LatitudeMin, LatitudeMax, CamRollMin, CamRollMax, DistMin, DistMax, MinContrast, GenParamName, GenParamValue : ShapeModel3DID)

    ObjectModel3D
        类型: object_model_3d → (integer)
        描述: 输入的 3D 对象模型句柄。用于标识和引用特定的 3D 模型。

    CamParam
        类型: campar → (real / integer / string)
        描述: 内部相机参数,用于定义相机的内参(如焦距、主点位置等)。

    RefRotX
        类型: angle.rad → (real)
        描述: 参考方向:绕 X 轴的旋转角度或 Rodriguez 向量的 X 分量(单位为弧度或无单位)。
        默认值: 0
        建议值: -1.57, -0.78, -0.17, 0., 0.17, 0.78, 1.57

    RefRotY
        类型: angle.rad → (real)
        描述: 参考方向:绕 Y 轴的旋转角度或 Rodriguez 向量的 Y 分量(单位为弧度或无单位)。
        默认值: 0
        建议值: -1.57, -0.78, -0.17, 0., 0.17, 0.78, 1.57

    RefRotZ
        类型: angle.rad → (real)
        描述: 参考方向:绕 Z 轴的旋转角度或 Rodriguez 向量的 Z 分量(单位为弧度或无单位)。
        默认值: 0
        建议值: -1.57, -0.78, -0.17, 0., 0.17, 0.78, 1.57

    OrderOfRotation
        类型: string → (string)
        描述: 参考方向中旋转值的意义。
        默认值: 'gba'
        可选值: 'abg', 'gba', 'rodriguez'

    LongitudeMin 和 LongitudeMax
        类型: angle.rad → (real)
        描述: 模型视图的最小和最大经度范围(单位为弧度)。
        默认值: LongitudeMin = -0.35, LongitudeMax = 0.35
        限制条件: LongitudeMax >= LongitudeMin

    LatitudeMin 和 LatitudeMax
        类型: angle.rad → (real)
        描述: 模型视图的最小和最大纬度范围(单位为弧度)。
        默认值: LatitudeMin = -0.35, LatitudeMax = 0.35
        限制条件: -π/2 <= LatitudeMin <= π/2, -π/2 <= LatitudeMax <= π/2, LatitudeMax >= LatitudeMin

    CamRollMin 和 CamRollMax
        类型: angle.rad → (real)
        描述: 模型视图的最小和最大相机滚转角(单位为弧度)。
        默认值: CamRollMin = -3.1416, CamRollMax = 3.1416
        限制条件: CamRollMax >= CamRollMin

    DistMin 和 DistMax
        类型: number → (real)
        描述: 模型视图的最小和最大相机到物体的距离。
        默认值: DistMin = 0.3, DistMax = 0.4
        限制条件: DistMin > 0, DistMax >= DistMin

    MinContrast
        类型: number → (integer)
        描述: 搜索图像中物体的最低对比度。
        默认值: 10
        建议值: 1, 2, 3, 5, 7, 10, 20, 30, 1000, 2000, 5000

    GenParamName 和 GenParamValue
        类型: attribute.name(-array)(string) 和 attribute.value(-array)(integer / real / string)
        描述: 控制操作行为的通用参数名称及其对应值。
        默认值: []
        示例名称: 'metric', 'min_face_angle', 'num_levels'
        示例值: 0, 1, 2, 'auto', 'ignore_local_polarity'
    'ignore_local_polarity':忽略局部极性变化,适合一般场景
    'ignore_part_polarity':忽略更大区域的极性变化,能显著加快纹理背景下的搜索速度

find_shape_model_3d ——发现匹配模型

find_shape_model_3d(Image : : ShapeModel3DID, MinScore, Greediness, NumLevels, GenParamName, GenParamValue : Pose, CovPose, Score)
输入参数 (Input Parameters)

    Image
        类型: (multichannel-)image → object (byte / uint2)
        描述: 输入图像,用于在其中查找 3D 形状模型。可以是单通道或多通道图像。

    ShapeModel3DID
        类型: shape_model_3d → (integer)
        描述: 3D 形状模型的句柄。通常是通过 create_shape_model_3d 或 read_shape_model_3d 创建或加载的模型。

    MinScore
        类型: real → (real)
        描述: 找到的模型实例的最低得分阈值。只有得分高于此值的实例才会被返回。
        默认值: 0.7
        建议值: 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0
        典型范围: 0 ≤ MinScore ≤ 1
        最小增量: 0.01
        推荐增量: 0.05

    Greediness
        类型: real → (real)
        描述: 搜索启发式的“贪婪度”。值越小,搜索越安全但速度较慢;值越大,搜索越快但可能错过匹配。
        默认值: 0.9
        建议值: 0.0, 0.1, 0.2, ..., 1.0
        典型范围: 0 ≤ Greediness ≤ 1
        最小增量: 0.01
        推荐增量: 0.05

    NumLevels
        类型: integer-array → (integer)
        描述: 匹配过程中使用的金字塔层数。如果数组长度为 2,则表示最低和最高金字塔层。
        默认值: 0
        可选值: 0, 1, 2, ..., 10

    GenParamName 和 GenParamValue
        类型: attribute.name-array → (string) 和 attribute.value-array → (integer / real / string)
        描述: 控制操作行为的通用参数名称及其对应值。
        默认值: []
        示例名称: 'border_model', 'cam_roll_max', 'cam_roll_min', 'cov_pose_mode', ...
        示例值: -0.78, -0.35, 0.0, 'none', 'true', 'false', ...

输出参数 (Output Parameters)

    Pose
        类型: pose(-array)(real / integer)
        描述: 找到的 3D 形状模型的姿态(位置和方向)。每个姿态由 6 个参数表示:3 个平移参数和 3 个旋转参数。

    CovPose
        类型: real-array → (real)
        描述: 姿态参数的 6 个标准差或 36 个协方差值,用于评估姿态估计的不确定性。

    Score
        类型: real-array → (real)
        描述: 找到的 3D 形状模型实例的匹配得分。分数越高,匹配质量越好。

project_shape_model_3d 将三维形状模型的边缘投影到图像坐标中。

project_shape_model_3d( : ModelContours : ShapeModel3DID, CamParam, Pose, HiddenSurfaceRemoval, MinFaceAngle : )
输出参数 (Output Parameters)

    ModelContours
        类型: xld_cont-array → object
        描述: 模型视图的轮廓表示。以 XLD(扩展线描述符)格式存储,可用于绘制或分析。

输入参数 (Input Parameters)

    ShapeModel3DID
        类型: shape_model_3d → (integer)
        描述: 3D 形状模型的句柄。通常是通过 create_shape_model_3d 或 read_shape_model_3d 创建或加载的模型。

    CamParam
        类型: campar → (real / integer / string)
        描述: 内部相机参数,用于定义相机的内参(如焦距、主点位置等)。

    Pose
        类型: pose → (real / integer)
        描述: 3D 形状模型在世界坐标系中的姿态(位置和方向)。姿态由 6 个参数表示:3 个平移参数和 3 个旋转参数。

    HiddenSurfaceRemoval
        类型: string → (string)
        描述: 是否移除隐藏表面(即是否启用隐藏面剔除)。
        默认值: 'true'
        可选值: 'false', 'true'

    MinFaceAngle
        类型: angle.rad → (real / integer)
        描述: 显示边缘所需的最小面角度(单位为弧度)。小于该角度的边缘将被忽略。
        默认值: 0.523599(约 30 度)
        建议值: 0.17, 0.26, 0.35, 0.52

示例

‘ignore_part_polarity’:忽略更大区域的极性变化,能显著加快纹理背景下的搜索速度

在这里插入图片描述

* 这个示例程序展示了如何使用HALCON的3D基于形状的匹配
* 来找到瓷砖间隔片的3D姿态

* 由于背景纹理较强,在create_shape_model_3d()中使用'ignore_part_polarity'度量
* 以加快搜索速度。为了展示速度提升,创建了两个3D形状模型:
* 一个使用'ignore_local_polarity'度量,另一个使用'ignore_part_polarity'度量

* 然后,为每个找到的对象显示轮廓并比较搜索时间

* 本示例还使用了'lowest_model_level'选项,这在示例程序
* 3d_matching_lowest_model_level.hdev中有更详细的解释

* 关闭显示更新
dev_update_off ()

* 获取并设置异常处理偏好(抑制已处理异常的对话框)
dev_get_preferences ('suppress_handled_exceptions_dlg', SuppressHandledExceptionsDlg)
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')

* 设置相机参数(可以通过相机标定获得)
gen_cam_par_area_scan_division (0.0269462, -354.842, 1.27964e-005, 1.28e-005, 254.24, 201.977, 512, 384, CamParam)

* 从相机参数中获取图像宽度和高度
get_cam_par_data (CamParam, 'image_width', IWidth)
get_cam_par_data (CamParam, 'image_height', IHeight)

* 关闭并重新打开显示窗口
dev_close_window ()
dev_open_window (0, 0, 512 * 1.5, 384 * 1.5, 'black', WindowHandle)

* 设置显示字体
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')

* 设置线宽为2
dev_set_line_width (2)

* 定义颜色数组
Colors := ['blue','forest green','black']

* 获取用于搜索的两个形状模型
acquire_shape_models (WindowHandle, CamParam, ShapeModel3DID1, ShapeModel3DID2)

* 显示继续消息并暂停
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

* 设置匹配参数
MatchingParameters := ['num_matches','pose_refinement']
MatchingParameterValues := [2,'least_squares_high']
MinScore := 0.65
Greediness := 0.9
NumLevels := 0

* 匹配循环
NumImages := 9
for I := 1 to NumImages by 1
    * 读取图像
    read_image (Image, 'tile_spacers/tile_spacers_' + I$'02')
    
    * 显示图像(使用蓝色)
    dev_set_color (Colors[0])
    dev_display (Image)
    
    * 使用'ignore_local_polarity'度量的模型1查找最多两个实例
    Message := 'Search model with \'ignore_local_polarity\' ...'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 记录开始时间
    count_seconds (Seconds1)
    * 执行3D形状匹配
    find_shape_model_3d (Image, ShapeModel3DID1, MinScore, Greediness, NumLevels, MatchingParameters, MatchingParameterValues, Pose, CovPose, Score1)
    * 记录结束时间
    count_seconds (Seconds2)
    Time1 := Seconds2 - Seconds1
    
    * 通过投影3D形状模型来可视化找到的匹配
    for J := 0 to |Score1| - 1 by 1
        PoseTmp := Pose[J * 7:J * 7 + 6]
        project_shape_model_3d (ModelContours, ShapeModel3DID1, CamParam, PoseTmp, 'true', rad(30))
        dev_display (ModelContours)
    endfor
    
    * 显示匹配结果信息
    Message := 'Search model with \'ignore_local_polarity\': ' + |Score1| + ' Match(es) found in ' + Time1$'.1f' + ' s'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 使用'ignore_part_polarity'度量的模型2查找最多两个实例
    dev_set_color (Colors[1])
    Message[1] := 'Search model with \'ignore_part_polarity\' ...'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 记录开始时间
    count_seconds (Seconds1)
    * 执行3D形状匹配
    find_shape_model_3d (Image, ShapeModel3DID2, MinScore, Greediness, NumLevels, MatchingParameters, MatchingParameterValues, Pose, CovPose, Score2)
    * 记录结束时间
    count_seconds (Seconds2)
    Time2 := Seconds2 - Seconds1
    
    * 通过投影3D形状模型来可视化找到的匹配(使用虚线样式)
    set_line_style (WindowHandle, [10,10])
    for J := 0 to |Score2| - 1 by 1
        PoseTmp := Pose[J * 7:J * 7 + 6]
        project_shape_model_3d (ModelContours, ShapeModel3DID1, CamParam, PoseTmp, 'true', rad(30))
        dev_display (ModelContours)
    endfor
    set_line_style (WindowHandle, [])
    
    * 显示匹配结果信息和速度提升因子
    Message[1] := 'Search model with \'ignore_part_polarity\':  ' + |Score2| + ' Match(es) found in ' + Time2$'.1f' + ' s'
    Message[2] := 'Speed-up factor with \'ignore_part_polarity\': ' + (Time1 / Time2)$'.1f'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 如果不是最后一张图像,显示继续消息并暂停
    if (I < NumImages)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor

* 暂停程序
stop ()

* 清除3D形状模型
clear_shape_model_3d (ShapeModel3DID1)
clear_shape_model_3d (ShapeModel3DID2)

* 恢复异常处理偏好设置
dev_set_preferences ('suppress_handled_exceptions_dlg', SuppressHandledExceptionsDlg)* 这个示例程序展示了如何使用HALCON的3D基于形状的匹配
* 来找到瓷砖间隔片的3D姿态

* 由于背景纹理较强,在create_shape_model_3d()中使用'ignore_part_polarity'度量
* 以加快搜索速度。为了展示速度提升,创建了两个3D形状模型:
* 一个使用'ignore_local_polarity'度量,另一个使用'ignore_part_polarity'度量

* 然后,为每个找到的对象显示轮廓并比较搜索时间

* 本示例还使用了'lowest_model_level'选项,这在示例程序
* 3d_matching_lowest_model_level.hdev中有更详细的解释

* 关闭显示更新
dev_update_off ()

* 获取并设置异常处理偏好(抑制已处理异常的对话框)
dev_get_preferences ('suppress_handled_exceptions_dlg', SuppressHandledExceptionsDlg)
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')

* 设置相机参数(可以通过相机标定获得)
gen_cam_par_area_scan_division (0.0269462, -354.842, 1.27964e-005, 1.28e-005, 254.24, 201.977, 512, 384, CamParam)

* 从相机参数中获取图像宽度和高度
get_cam_par_data (CamParam, 'image_width', IWidth)
get_cam_par_data (CamParam, 'image_height', IHeight)

* 关闭并重新打开显示窗口
dev_close_window ()
dev_open_window (0, 0, 512 * 1.5, 384 * 1.5, 'black', WindowHandle)

* 设置显示字体
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')

* 设置线宽为2
dev_set_line_width (2)

* 定义颜色数组
Colors := ['blue','forest green','black']

* 获取用于搜索的两个形状模型
acquire_shape_models (WindowHandle, CamParam, ShapeModel3DID1, ShapeModel3DID2)

* 显示继续消息并暂停
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

* 设置匹配参数
MatchingParameters := ['num_matches','pose_refinement']
MatchingParameterValues := [2,'least_squares_high']
MinScore := 0.65
Greediness := 0.9
NumLevels := 0

* 匹配循环
NumImages := 9
for I := 1 to NumImages by 1
    * 读取图像
    read_image (Image, 'tile_spacers/tile_spacers_' + I$'02')
    
    * 显示图像(使用蓝色)
    dev_set_color (Colors[0])
    dev_display (Image)
    
    * 使用'ignore_local_polarity'度量的模型1查找最多两个实例
    Message := 'Search model with \'ignore_local_polarity\' ...'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 记录开始时间
    count_seconds (Seconds1)
    * 执行3D形状匹配
    find_shape_model_3d (Image, ShapeModel3DID1, MinScore, Greediness, NumLevels, MatchingParameters, MatchingParameterValues, Pose, CovPose, Score1)
    * 记录结束时间
    count_seconds (Seconds2)
    Time1 := Seconds2 - Seconds1
    
    * 通过投影3D形状模型来可视化找到的匹配
    for J := 0 to |Score1| - 1 by 1
        PoseTmp := Pose[J * 7:J * 7 + 6]
        project_shape_model_3d (ModelContours, ShapeModel3DID1, CamParam, PoseTmp, 'true', rad(30))
        dev_display (ModelContours)
    endfor
    
    * 显示匹配结果信息
    Message := 'Search model with \'ignore_local_polarity\': ' + |Score1| + ' Match(es) found in ' + Time1$'.1f' + ' s'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 使用'ignore_part_polarity'度量的模型2查找最多两个实例
    dev_set_color (Colors[1])
    Message[1] := 'Search model with \'ignore_part_polarity\' ...'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 记录开始时间
    count_seconds (Seconds1)
    * 执行3D形状匹配
    find_shape_model_3d (Image, ShapeModel3DID2, MinScore, Greediness, NumLevels, MatchingParameters, MatchingParameterValues, Pose, CovPose, Score2)
    * 记录结束时间
    count_seconds (Seconds2)
    Time2 := Seconds2 - Seconds1
    
    * 通过投影3D形状模型来可视化找到的匹配(使用虚线样式)
    set_line_style (WindowHandle, [10,10])
    for J := 0 to |Score2| - 1 by 1
        PoseTmp := Pose[J * 7:J * 7 + 6]
        project_shape_model_3d (ModelContours, ShapeModel3DID1, CamParam, PoseTmp, 'true', rad(30))
        dev_display (ModelContours)
    endfor
    set_line_style (WindowHandle, [])
    
    * 显示匹配结果信息和速度提升因子
    Message[1] := 'Search model with \'ignore_part_polarity\':  ' + |Score2| + ' Match(es) found in ' + Time2$'.1f' + ' s'
    Message[2] := 'Speed-up factor with \'ignore_part_polarity\': ' + (Time1 / Time2)$'.1f'
    disp_message (WindowHandle, Message, 'window', 12, 12, Colors, 'true')
    
    * 如果不是最后一张图像,显示继续消息并暂停
    if (I < NumImages)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor

* 暂停程序
stop ()

* 清除3D形状模型
clear_shape_model_3d (ShapeModel3DID1)
clear_shape_model_3d (ShapeModel3DID2)

* 恢复异常处理偏好设置
dev_set_preferences ('suppress_handled_exceptions_dlg', SuppressHandledExceptionsDlg)

在这里插入图片描述

'lowest_model_level’参数可减少内存需求

在这里插入图片描述

* 本示例展示如何使用HALCON基于形状的3D匹配技术
* 来定位瓷砖间隔片的3D姿态。由于物体在图像中较大,
* 3D模型需要许多不同视角的内部表示,导致模型内存消耗很高。
* 使用'lowest_model_level'参数可减少内存需求:
* - 默认级别为1,提高级别可减少内存(每级约减少3)
* - 同时模型创建时间减少2/* - 代价是匹配鲁棒性可能降低,搜索时间略增(5-10%)
*
* 本例设置'lowest_model_level'3,结果是:
* - 模型内存需求减少6* - 模型创建时间减少4* 关闭显示更新
dev_update_off ()

* 获取并设置异常处理偏好(抑制已处理异常的对话框)
dev_get_preferences ('suppress_handled_exceptions_dlg', SuppressHandledExceptionsDlg)
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')

* 设置相机参数(可通过相机标定获得)
gen_cam_par_area_scan_division (0.0269462, -354.842, 1.27964e-005, 1.28e-005, 254.24, 201.977, 512, 384, CamParam)

* 获取图像尺寸
get_cam_par_data (CamParam, 'image_width', IWidth)
get_cam_par_data (CamParam, 'image_height', IHeight)

* 读取示例图像并初始化窗口
read_image (Image, 'tile_spacers/tile_spacers_color_01')
dev_close_window ()
dev_open_window (0, 0, 512 * 1.5, 384 * 1.5, 'white', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (3)

* 尝试从磁盘读取3D形状模型
dev_clear_window ()
disp_message (WindowHandle, 'Reading the 3D shape model file from disk ...', 'window', 12, 12, 'black', 'false')
try
    read_shape_model_3d ('tile_spacer.sm3', ShapeModel3DID)
catch (Exception)
    * 如果读取失败,则创建新模型
    * 从DXF文件读取3D对象模型
    read_object_model_3d ('tile_spacer.dxf', 0.0001, [], [], ObjectModel3DID, DXFStatus)
    prepare_object_model_3d (ObjectModel3DID, 'shape_based_matching_3d', 'true', [], [])
    
    disp_message (WindowHandle, 'Reading the 3D shape model file from disk ... not found!', 'window', 12, 12, 'red', 'false')
    disp_message (WindowHandle, 'Creating the 3D shape model (may take a few seconds) ...', 'window', 42, 12, 'black', 'false')
    
    * 记录模型创建时间
    count_seconds (S1)
    
    * 关键参数设置:使用'lowest_model_level'=3来优化内存和创建时间
    create_shape_model_3d (ObjectModel3DID, CamParam, 0, 0, 0, 'gba', 
                         -rad(60), rad(60), -rad(60), rad(60), 0, rad(360), 
                         0.26, 0.27, 10, 
                         'lowest_model_level', 3, ShapeModel3DID)
    
    count_seconds (S2)
    T := S2 - S1
    
    * 清理原始3D对象模型
    clear_object_model_3d (ObjectModel3DID)
    
    * 显示创建时间
    disp_message (WindowHandle, 'Creation time: ' + T$'.3' + ' s', 'window', 72, 12, 'black', 'false')
    
    * 尝试保存模型
    try
        disp_message (WindowHandle, 'Writing model to disk ...', 'window', 102, 12, 'black', 'false')
        write_shape_model_3d (ShapeModel3DID, 'tile_spacer.sm3')
    catch (Exception)
        disp_message (WindowHandle, 'Writing model to disk ... failed!', 'window', 102, 12, 'red', 'false')
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endtry
endtry

* 显示模型级别信息
disp_lowest_model_level_info (WindowHandle)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

* 匹配阶段
Times := []
NumImages := 12
for I := 1 to NumImages by 1
    read_image (Image, 'tile_spacers/tile_spacers_color_' + I$'02')
    dev_display (Image)
    
    * 查找最多3个实例(设置'border_model''true'因为物体可能接触图像边界)
    count_seconds (Seconds1)
    find_shape_model_3d (Image, ShapeModel3DID, 0.7, 0.85, 0, 
                        ['num_matches','max_overlap','border_model'], 
                        [3,0.75,'true'], Pose, CovPose, Score)
    count_seconds (Seconds2)
    Time := Seconds2 - Seconds1
    Times := [Times,Time]
    
    * 可视化匹配结果
    for J := 0 to |Score| - 1 by 1
        * 显示轮廓
        PoseTmp := Pose[J * 7:J * 7 + 6]
        project_shape_model_3d (ModelContours, ShapeModel3DID, CamParam, PoseTmp, 'true', rad(30))
        dev_set_color ('yellow')
        dev_display (ModelContours)
        
        * 显示3D坐标系
        dev_set_colored (3)
        disp_3d_coord_system (WindowHandle, CamParam, PoseTmp, 0.015)
    endfor
    
    * 显示姿态参数
    for K := 0 to |Score| - 1 by 1
        PoseTmp := Pose[K * 7:K * 7 + 6]
        display_match_pose (ShapeModel3DID, PoseTmp, WindowHandle)
    endfor
    
    * 显示匹配结果信息
    disp_message (WindowHandle, |Score| + ' Match(es) found in ' + Time$'4.2f' + ' s', 'window', 12, 12, 'dark green', ['white','false'])
    
    if (I < NumImages)
        disp_continue_message (WindowHandle, 'black', ['white','false'])
        stop ()
    endif
endfor

* 清理资源
clear_shape_model_3d (ShapeModel3DID)
dev_set_preferences ('suppress_handled_exceptions_dlg', SuppressHandledExceptionsDlg)
disp_end_of_program_message (WindowHandle, 'black', ['white','false'])

在这里插入图片描述

find_shape_model_3d 的 recompute_score 匹配精度

在这里插入图片描述

* 本程序演示find_shape_model_3d算子中通用参数'recompute_score'的效果
* 
* 当设置'recompute_score''true'时,姿态优化后会重新计算分数,
* 这可能导致分数值略有不同(但更一致),代价是执行时间稍长

* 初始化相机参数
gen_cam_par_area_scan_division (0.01, 0, 7e-6, 7e-6, 320, 240, 640, 480, CamParam)
get_cam_par_data (CamParam, 'image_width', Width)
get_cam_par_data (CamParam, 'image_height', Height)

* 创建显示窗口
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_set_part (0, 0, Height - 1, Width - 1)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_update_off ()

* 创建立方体3D模型
X := [-1,-1,1,1,-1,-1,1,1]  * X坐标
Y := [1,-1,-1,1,1,-1,-1,1]  * Y坐标
Z := [-1,-1,-1,-1,1,1,1,1]  * Z坐标
Polygons := [4,0,1,2,3,4,4,5,6,7,4,0,1,5,4,4,3,2,6,7,4,0,3,7,4,4,1,2,6,5]  * 多边形定义
gen_object_model_3d_from_points (X, Y, Z, ObjectModel3DID)
set_object_model_3d_attrib_mod (ObjectModel3DID, 'polygons', [], Polygons)

* 准备3D对象模型用于匹配
prepare_object_model_3d (ObjectModel3DID, 'shape_based_matching_3d', 'true', [], [])

* 显示3D对象模型
disp_object_model_3d_safe (WindowHandle, ObjectModel3DID, CamParam, [0,0,11,30,40,0,0], [], [])
disp_message (WindowHandle, '3D Object Model of a Cube', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

* 生成3D形状模型
create_cube_shape_model_3d (WindowHandle, ObjectModel3DID, CamParam, ShapeModel3DID)
clear_object_model_3d (ObjectModel3DID)

* 初始化存储变量
Scores1 := []  * 存储recompute_score=false的分数
Scores2 := []  * 存储recompute_score=true的分数
Times1 := []   * 存储recompute_score=false的时间
Times2 := []   * 存储recompute_score=true的时间
Longitudes := []  * 存储经度值

* 设置固定参数
Latitude := rad(45)  * 固定纬度
Distance := 11.5     * 固定距离

* 设置显示属性
dev_set_color ('green')
dev_set_line_width (2)

* 主循环:在30-60度经度范围内测试
for Longitude := rad(30) to rad(60) by rad(0.25)
    * 将球坐标转换为笛卡尔坐标
    convert_point_3d_spher_to_cart (Longitude, Latitude, Distance, '-y', '-z', CamX, CamY, CamZ)
    
    * 创建相机姿态
    create_cam_pose_look_at_point (CamX, CamY, CamZ, 0, 0, 0, '-y', 0, CamPose)
    
    * 防止闪烁
    set_system ('flush_graphic', 'false')
    
    * 生成立方体的合成图像
    project_cube_image (Image, CamPose, CamParam, X, Y, Z, Polygons)
    
    * 第一次匹配:recompute_score=false
    count_seconds (Seconds1)
    find_shape_model_3d (Image, ShapeModel3DID, 0.7, 0.9, 0, [], [], Pose1, CovPose1, Score1)
    count_seconds (Seconds2)
    Time1 := (Seconds2 - Seconds1) * 1000.0  * 转换为毫秒
    
    * 第二次匹配:recompute_score=true
    count_seconds (Seconds1)
    find_shape_model_3d (Image, ShapeModel3DID, 0.7, 0.9, 0, 'recompute_score', 'true', Pose2, CovPose2, Score2)
    count_seconds (Seconds2)
    Time2 := (Seconds2 - Seconds1) * 1000.0  * 转换为毫秒
    
    * 显示匹配结果
    dev_display (Image)
    if (|Score1| == 1 and |Score2| == 1)
        * 显示匹配轮廓
        project_shape_model_3d (ModelContours, ShapeModel3DID, CamParam, Pose1, 'true', rad(30))
        dev_display (ModelContours)
        
        * 显示当前经度信息
        disp_message (WindowHandle, 'Matching at Longitude: ' + deg(Longitude)$'3.1f' + ' deg (from 30 to 60 deg)', 'window', 12, 12, 'white', 'false')
        
        * 生成并显示匹配结果消息
        gen_matching_result_message (Time1, Time2, Score1, Score2, Message)
        disp_message (WindowHandle, Message, 'window', 420, 12, ['white','yellow','green'], 'false')
        
        * 存储结果数据
        Longitudes := [Longitudes,deg(Longitude)]
        Scores1 := [Scores1,Score1]
        Scores2 := [Scores2,Score2]
        Times1 := [Times1,Time1]
        Times2 := [Times2,Time2]
    endif
    
    * 恢复图形刷新
    set_system ('flush_graphic', 'true')
    * 通过绘制不可见线条强制刷新显示
    disp_line (WindowHandle, -1, -1, -1, -1)
endfor

* 显示分数值对比图
dev_clear_window ()
Title := ['\'recompute_score\'=\'false\'','\'recompute_score\'=\'true\'']
Colors := ['yellow','green']
plot_tuple (WindowHandle, Longitudes, [Scores1,Scores2], 'Longitude [deg]', 'Matching score', Colors, ['ticks_x','ticks_y','end_y'], [6,.01,1])
disp_message (WindowHandle, Title, 'window', 12, 350, Colors, 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

* 显示时间消耗对比图
dev_clear_window ()
plot_tuple (WindowHandle, Longitudes, [Times1,Times2], 'Longitude [deg]', 'Matching time [ms]', Colors, 'ticks_x', 6)
disp_message (WindowHandle, Title, 'window', 12, 350, Colors, 'false')

* 清理3D形状模型
clear_shape_model_3d (ShapeModel3DID)

在这里插入图片描述

Halcon 3D 表面匹配


网站公告

今日签到

点亮在社区的每一天
去签到