原文作者:aircraft

原文链接:https://www.cnblogs.com/DOMLX/p/18783476

有兴趣可以多看其他的halcon教程

halcon 学习教程目录

    本篇主要讲一下工业中最常用的基于形状的模板匹配,以及根据模板定位锁定待检测区域的位置。注意本篇对于工业的缺陷检测是最基础的也是最重要的!!!如果你学习掌握了本篇的demo示例,基本一些简单的工业缺陷检测是没有什么大问题的。

    本来应该是有个halcon的程序集里的示例代码的,但是我没找到比较短的,好入门的,所以我临时手写了一个halcon例子。至于其他的例子可以去看halcon官方的。

一.模板匹配简介

  halcon中的模板匹配‌是一种图像处理技术,主要用于在新的图像中找到特定模板图像的位置。模板匹配通过算法比较图像和模板之间的相似度,从而实现对目标的定位和识别。HALCON提供了多种模板匹配方法:

1. 基于点的匹配(Point-Based Matching)​

原理与特点

  • 核心机制:通过提取图像中的关键点​(如SIFT、SURF特征点)进行匹配,依赖局部特征描述符的相似度。
  • 优势
    • 视角变化​(旋转、缩放、倾斜)鲁棒。
    • 部分遮挡​(只要保留足够特征点即可匹配)。
  • 局限
    • 需要图像中存在丰富的纹理或角点。
    • 计算复杂度较高,实时性受限。

参数调优

  • 关键参数

    • 'keypoint_radius':特征点邻域半径,影响描述符的区分度。
    • 'min_score':匹配分数阈值,过滤低置信度匹配。

应用场景

  • 无人机航拍匹配:识别地标或建筑特征点。
  • 动态视角检测:如机器人抓取不同角度的工件。

2. 基于灰度值的匹配(Gray-Value-Based Matching)​

原理与特点

  • 核心机制:直接比较模板与图像区域的像素灰度值相似度​(如SSD、NCC)。
  • 优势
    • 计算极快,适合实时性要求高的场景。
    • 无需特征提取,适用于无纹理或低对比度图像。
  • 局限
    • 光照变化、旋转、缩放敏感。
    • 无法处理形变或遮挡。

参数调优

  • 关键参数

    • 'mask_size':匹配时的掩模大小,影响抗噪声能力。
    • 'subpixel':是否启用亚像素精度('true'/'false')。

应用场景

  • 印刷品定位:固定光源下检测标签位置。
  • 电子元件校准:如LED晶圆的对位。

3. 基于形状的匹配(Shape-Based Matching)​--------------工业场景中最常用的方法!!!

原理与特点

  • 核心机制:提取模板的边缘轮廓,通过形状相似性(边缘梯度方向)进行匹配。
  • 优势
    • 抗光照变化​(仅依赖边缘信息)。
    • 支持旋转、缩放​(通过参数化设置范围)。
    • 工业场景中最常用的方法。
  • 局限
    • 边缘模糊或缺失敏感。
    • 需要清晰的轮廓定义。

参数调优

  • 关键参数

    • 'angle_step':角度搜索步长(越小越慢但精度↑)。
    • 'scale_min'/'scale_max':允许的缩放范围。
    • 'min_contrast':最小边缘对比度(过滤噪声)。

应用场景

  • 机械臂抓取:定位金属零件轮廓。
  • OCR预处理:定位文本区域。

4. 基于组件的匹配(Component-Based Matching)​

原理与特点

  • 核心机制:将物体分解为多个子组件,分别匹配后组合结果。
  • 优势
    • 严重遮挡​(只要保留关键子组件即可匹配)。
    • 适合复杂结构物体​(如多部件装配体)。
  • 局限
    • 需定义子组件的空间关系​(如相对位置、角度)。
    • 参数配置复杂。

参数调优

  • 关键参数

    • 'component_relation':子组件间的空间约束(如距离容差)。
    • 'min_component_score':单个子组件的最低匹配分数。

应用场景

  • 汽车装配检测:检查发动机组件的完整性。
  • 货架商品识别:部分遮挡下的商品匹配。

5. 基于局部可变形匹配(Locally Deformable Matching)​

原理与特点

  • 核心机制:允许模板在匹配过程中发生局部非线性形变​(如拉伸、弯曲)。
  • 优势
    • 处理弹性变形​(如布料、橡胶件)。
    • 对局部缺损鲁棒。
  • 局限
    • 计算复杂度高,实时性差。
    • 需要高质量的模板图像。

参数调优

  • 关键参数

    • 'deformation_smoothness':形变平滑度约束(值越高形变越受限)。
    • 'max_deformation':最大允许形变量(像素单位)。

应用场景

  • 软包装检测:如食品袋的褶皱匹配。
  • 生物医学图像:器官组织的弹性变形分析。

6. 基于可变形的匹配(Deformable Matching)​

原理与特点

  • 核心机制:通过参数化变形模型​(仿射、透视变换)处理全局形变。
  • 优势
    • 支持透视变换和3D投影。
    • 可校正大范围视角倾斜。
  • 局限
    • 需要已知变形参数范围(如倾斜角度限制)。
    • 对非线性形变(如局部弯曲)处理能力有限。

参数调优

  • 关键参数

    • 'perspective_model':是否启用透视模型('true'/'false')。
    • 'max_deformation':最大形变参数值。

应用场景

  • 倾斜视角校正:如车牌识别。
  • AR/VR定位:虚拟物体的3D叠加。

错误排查指南

现象 可能原因 解决方案
匹配分数低 模板与图像差异大 检查光照、对比度,调整min_contrast
匹配时间过长 搜索范围过大 缩小角度/缩放范围,增大angle_step
误匹配多 阈值设置过松 提高min_score,启用max_overlap
无法创建模型 模板图像质量差 使用edges_image强化边缘

二.图像匹配以及缺陷区域定位

老规矩,直接上图:

我们接下来对一个零件建立模板,并且我们建立一个小孔区域的缺陷检测ROI区域,当我们匹配到这个零件的时候,检测缺陷的区域也会到当前零件的小孔位置去,这样我们就可以对其进行区域缺陷检测了(工业中非常常用!!!)

大概过程如下:

  1. 读取并显示图像;
  2. 绘制模板ROI及待检测ROI;
  3. 创建模型;
  4. 匹配模板;
  5. ROI仿射变换,得到待检测ROI位置。

第一步:画模板区域,框选了一颗零件矩形区域。

第二步:画待检测区域

第三步:创建模板,默认模板都在左上角,模板中心点没设置的话默认是模板的重心位置  自己可以用set_shape_model_origin(这个算子工业开发中会用到)算子设置一下,基本我们都是设置为裁剪区域的中心点。

第四步:匹配定位到模板,在将模板以及待检测区域的位置转换过去

第五步:就是检测这个区域了,这里简单的提取个中心显示一下,正常你们是要对其进行某些检测的。比如我在小孔这里画个白色的什么脏东西,你就可以用Blob分析去检测出来,或者这里小孔位置歪了,或者干脆没有小孔,那么你该怎么检测呢?

OK 实例的过程讲完了,我们在认识一下接下来要用到的算子,然后就直接看代码理解。

1.创建形状匹配模板算子create_shape_model(Template : : NumLevelsAngleStartAngleExtentAngleStepOptimizationMetricContrastMinContrast : ModelID)详解:

函数原型:

create_shape_model(
Template : : // 输入模板图像(ROI区域)
NumLevels : : // 金字塔层级数
AngleStart : : // 起始角度(弧度)
AngleExtent : : // 角度范围(弧度)
AngleStep : : // 角度步长(弧度或'auto')
Optimization : : // 模型优化模式
Metric : : // 匹配度量方式
Contrast : : // 对比度参数(列表)
MinContrast : : // 最小对比度阈值
: ModelID // 输出模型句柄
)

参数详解与工业配置策略

1. NumLevels (金字塔层级数)

  • 作用:控制模型的金字塔层级,层级越多,匹配速度越快,但会损失细节。 正常我们都是1-3之间设置自己摸索一下。
  • 推荐值
    • 高速场景:3-5层(如产线速度>30fps)
    • 高精度场景:1-3层(需亚像素精度)

2. AngleStartAngleExtent (角度范围)

  • 作用:定义模型在匹配时的旋转角度搜索范围。
  • 工业设置
    • 固定角度AngleStart=0, AngleExtent=0(无旋转)
    • 全角度检测AngleStart=0, AngleExtent=rad(360)
  • 案例
    • 传送带零件允许±30°倾斜 → AngleStart=rad(-30), AngleExtent=rad(60)  一般前面的绝对值是后面一半这样设置

3. AngleStep (角度步长)

  • 作用:角度搜索的步长,决定角度分辨率。
  • 设置策略
    • ​**'auto'**:自动计算(推荐优先使用)
    • 手动设置:根据精度需求调整(越小越精确但速度越慢)
      • 高速产线:rad(1.0)
      • 高精度检测:rad(0.1)

4. Optimization (优化模式)

  • 可选值

    • 'none':不优化(内存占用最小)
    • 'pregeneration':预生成模型(匹配最快,内存占用高)
    • 'no_pregeneration':不预生成(内存占用低,匹配稍慢)
  • 推荐
    • 实时检测'pregeneration'
    • 嵌入式设备'no_pregeneration'

5. Metric (匹配度量方式)

  • 选项

    • 'use_polarity':要求模板与目标对比度极性相同​(亮/暗一致)
    • 'ignore_global_polarity':允许全局极性反转(如白底黑字→黑底白字)
    • 'ignore_local_polarity':允许局部极性变化(抗光照不均)
  • 工业场景
    • 金属零件检测 → 'use_polarity'
    • 印刷品检测(可变背景) → 'ignore_global_polarity'

6. ContrastMinContrast (对比度参数)

  • 作用:控制模型边缘特征的提取灵敏度。
  • 参数结构
    • Contrast:各金字塔层的对比度阈值(列表,长度=NumLevels)
    • MinContrast:模型允许的最小边缘对比度

案例1:高速产线零件定位

* 参数配置
NumLevels := 4 // 4级金字塔加速匹配
AngleStep := 'auto' // 自动角度步长
Optimization := 'pregeneration' // 预生成模型
Metric := 'use_polarity'// 极性一致(稳定光照)
Contrast := [25,12,6,3] // 各层对比度阈值
MinContrast := 5 // 最小边缘对比度 * 创建模型
create_shape_model (
TemplateImage,
NumLevels,
rad(-30), rad(60), // 允许±30°旋转
AngleStep,
Optimization,
Metric,
Contrast,
MinContrast,
ModelID
)

案例2:低对比度塑料件检测

* 参数配置
NumLevels := 2 // 高精度模式
AngleStep := rad(0.5) // 小角度步长
Optimization := 'none' // 节省内存
Metric := 'ignore_local_polarity' // 抗光照不均
Contrast := [10,5] // 低对比度阈值
MinContrast := 3 // 捕捉微弱边缘 * 创建模型
create_shape_model (
TemplateImage,
NumLevels,
rad(0), rad(360), // 全角度搜索
AngleStep,
Optimization,
Metric,
Contrast,
MinContrast,
ModelID
)

性能优化技巧

  1. 边缘滤波

    在创建模型前使用emphasizelaplace增强边缘对比度。
  2. ROI裁剪

    使用reduce_domain缩小模板区域,去除无关背景。
  3. 亚像素优化

    find_shape_model中启用'least_squares'亚像素模式。

通过精准配置create_shape_model参数,可兼顾速度与精度,满足工业检测的严苛要求。建议使用inspect_shape_model工具验证模型质量,并根据实际场景微调参数。

2.模板匹配算子find_shape_model(Image : : ModelIDAngleStartAngleExtentMinScoreNumMatchesMaxOverlapSubPixelNumLevelsGreediness : RowColumnAngleScore)详解:

函数原型:

find_shape_model(
Image : : // 输入图像(单通道灰度)
ModelID : : // 形状模型句柄
AngleStart : : // 起始角度(弧度)
AngleExtent : : // 角度范围(弧度)
MinScore : : // 最小匹配分数(0-1)
NumMatches : : // 最大匹配数量
MaxOverlap : : // 最大重叠度(0-1)
SubPixel : : // 亚像素模式
NumLevels : : // 搜索金字塔层级范围([起始层, 结束层])
Greediness : : // 贪婪系数(0-1)
: Row, Column, Angle, Score // 输出坐标、角度及分数
)

参数详解与工业配置策略

1. AngleStartAngleExtent

  • 作用:限定匹配时的角度搜索范围,减少计算量。
  • 推荐设置:​技巧
    • 固定角度AngleStart=0, AngleExtent=0
    • 允许±30°旋转AngleStart=rad(-30), AngleExtent=rad(60)
  • 若模型创建时已限定角度范围,此处应保持一致。

2. MinScore (最小匹配分数)

    • 作用:过滤低质量匹配(范围0~1,1为完全匹配)。
    • 工业建议
      • 高精度检测 → 0.7-0.9
      • 高速场景 → 0.5-0.7

3. NumMatches (最大匹配数量)

  • 作用:限制返回的匹配结果数量。
  • 场景
    • 单一目标定位 → 1
    • 多目标检测 → 根据图像中预期目标数设置(如5)

4. MaxOverlap (最大重叠度)

  • 作用:控制重叠区域的匹配结果去重。
  • 设置规则
    • 密集排列物体 → 0.3-0.5
    • 孤立物体 → 0.8(几乎不抑制)

5. SubPixel (亚像素模式)

  • 选项

    • 'none':禁用(最快)
    • 'interpolation':插值法(平衡)
    • 'least_squares':最小二乘优化(最精确)
  • 推荐
    • 坐标精度要求≤0.5像素'least_squares'
    • 实时检测'interpolation''none'

6. NumLevels (金字塔层级范围)

  • 格式[起始层, 结束层](需≤创建模型时的金字塔层数)
  • 策略
    • 高速优先[3,1](从低分辨率到高分辨率)
    • 精度优先[0,2](从高分辨率开始)

7. Greediness (贪婪系数)

  • 作用:平衡速度漏检率​(值越高速度越快,但可能漏检)。
  • 建议
    • 稳定环境 → 0.7-0.9
    • 复杂背景 → 0.4-0.6

案例1:高精度零件定位(亚像素+严格过滤)

find_shape_model (
Image, ModelID,
rad(-10), rad(20), // 允许±10°旋转
0.8, // 最小分数0.8
1, // 只找最佳匹配
0.5, // 最大重叠度0.5
'least_squares', // 亚像素优化
[0, 3], // 使用所有金字塔层
0.7, // 中等贪婪度
Row, Column, Angle, Score
)

案例2:高速产线多目标检测

find_shape_model (
Image, ModelID,
0, rad(360), // 全角度搜索
0.6, // 容忍较低分数
5, // 最多5个匹配
0.3, // 抑制重叠>30%的结果
'interpolation', // 快速亚像素
[2, 1], // 从第2层开始搜索
0.9, // 高贪婪度
Row, Column, Angle, Score
)

错误排查与调试

现象 可能原因 解决方案
无匹配结果 MinScore过高 逐步降低至0.3,观察是否出现匹配
匹配位置偏移 亚像素模式未启用 设置SubPixel='least_squares'
检测时间过长 Greediness过低 逐步提高至0.9
重复匹配同一物体 MaxOverlap过低 调整至0.6-0.8

最佳实践总结

  1. 参数联动调整:创建模型时的Contrast与搜索时的NumLevels需协同优化。
  2. 结果验证:使用dev_display_shape_matching_results可视化匹配结果。
  3. 资源释放:循环结束后调用clear_shape_model避免内存泄漏。

通过合理配置find_shape_model参数,可在工业检测中实现高精度高速度的物体定位。

3.旋转矩阵生成算子hom_mat2d_rotate( : : HomMat2DPhiPxPy : HomMat2DRotate)详解:

函数原型:

hom_mat2d_rotate(
: :
HomMat2D, // 输入齐次变换矩阵
Phi, // 旋转角度(弧度,正值逆时针)
Px, Py, // 旋转中心坐标(原始坐标系中的点)
: HomMat2DRotate // 输出旋转后的变换矩阵
)

参数解释

  • HomMat2D:输入的二维齐次变换矩阵。若初始为单位矩阵,表示无先前变换。
  • Phi:旋转角度(弧度)。例如,rad(30) 表示逆时针旋转30度。
  • Px, Py:旋转中心在原始坐标系中的坐标。无论之前的变换如何,旋转始终绕此点进行。
  • HomMat2DRotate:输出的新变换矩阵,将输入矩阵与旋转变换组合。

功能描述

  • 旋转变换:生成的矩阵会先执行原始变换(HomMat2D),再绕原始坐标系中的点 (Px, Py) 旋转角度 Phi
  • 矩阵组合:新矩阵 = 旋转变换矩阵 × 原始矩阵。即,先应用原始变换,再执行旋转。

示例1:绕图像中心旋转30度

* 读取图像并获取尺寸
read_image(Image, 'part.png')
get_image_size(Image, Width, Height) * 计算图像中心坐标
CenterX := Width / 2
CenterY := Height / 2 * 创建初始单位矩阵
hom_mat2d_identity(HomMat2D) * 绕中心点旋转30度(逆时针)
hom_mat2d_rotate(HomMat2D, rad(30), CenterX, CenterY, HomMat2DRotate) * 应用变换到图像
affine_trans_image(Image, ImageRotated, HomMat2DRotate, 'constant', 'false')

示例2:平移后绕新位置旋转

* 将物体平移到(200,200),再绕该点旋转45度
hom_mat2d_identity(HomMat2D)
hom_mat2d_translate(HomMat2D, 200, 200, HomMat2DTranslate)
hom_mat2d_rotate(HomMat2DTranslate, rad(45), 200, 200, HomMat2DRotate) * 应用变换到区域
affine_trans_region(Region, RegionTrans, HomMat2DRotate, 'nearest_neighbor')

关键注意事项

  1. 旋转中心(Px, Py) 必须是原始坐标系中的坐标。若之前的变换已移动物体,需计算其在原始坐标系中的目标位置。
  2. 变换顺序:新矩阵按 旋转 × 原始 组合,意味着先执行原始变换,再旋转。
  3. 角度方向:正值表示逆时针旋转,使用 rad() 函数转换角度。

错误排查

  • 非预期旋转中心:检查 Px, Py 是否在原始坐标系中计算。
  • 角度错误:确认使用弧度而非角度,例如 rad(30) 而非直接 30

可视化验证

使用 affine_trans_pixel 变换关键点并绘制,确认旋转中心正确:

* 变换旋转中心点(应保持不变)
affine_trans_pixel(HomMat2DRotate, Px, Py, TransPx, TransPy)
gen_cross_contour_xld(Cross, TransPy, TransPx, 20, 0.785398)
dev_display(Image)
dev_display(Cross)

4.平移矩阵生成算子hom_mat2d_translate( : : HomMat2DTxTy : HomMat2DTranslate)详解:

函数原型:

hom_mat2d_translate(
: :
HomMat2D, // 输入齐次变换矩阵
Tx, Ty, // X/Y方向平移量(像素单位)
: HomMat2DTranslate // 输出平移后的变换矩阵
)

参数详解

参数名 类型 说明
HomMat2D 矩阵 输入的二维齐次变换矩阵。若初始为单位矩阵(无变换),可通过hom_mat2d_identity创建。
Tx, Ty 数值 X和Y方向的平移量(像素单位)。正值为向右/下平移,负值为向左/上平移。
HomMat2DTranslate 矩阵 输出矩阵,包含原矩阵的变换叠加平移后的结果。

功能描述

    • 作用:在现有变换矩阵的基础上叠加平移变换,生成新的变换矩阵。
    • 数学原理

      若原矩阵为 ​H,平移矩阵为 ​T,则新矩阵为:

这意味着先执行原矩阵的变换,再进行平移

示例1:纯平移变换(无初始变换)

* 创建单位矩阵(无变换)
hom_mat2d_identity(HomMat2D)
* 向右平移50像素,向下平移30像素
hom_mat2d_translate(HomMat2D, 50, 30, HomMat2DTranslate)
* 应用平移变换到图像
affine_trans_image(Image, ImageTranslated, HomMat2DTranslate, 'constant', 'false')

示例2:组合变换(旋转+平移)

* 绕图像中心旋转30度后,再平移
hom_mat2d_identity(HomMat2D)
* 计算图像中心坐标
get_image_size(Image, Width, Height)
CenterX := Width / 2
CenterY := Height / 2
* 旋转
hom_mat2d_rotate(HomMat2D, rad(30), CenterX, CenterY, HomMat2DRotate)
* 平移(在旋转后的坐标系中平移)
hom_mat2d_translate(HomMat2DRotate, 100, -50, HomMat2DTranslate)
* 应用复合变换
affine_trans_image(Image, ImageTransformed, HomMat2DTranslate, 'constant', 'false')

注意事项

    1. 变换顺序

      矩阵乘法顺序决定变换执行顺序。例如:

      • 先旋转后平移 → 物体绕原点旋转,再移动到新位置。
      • 先平移后旋转 → 物体移动到新位置后绕该点旋转。
* 顺序不同,结果不同!
hom_mat2d_rotate → hom_mat2d_translate : 旋转后平移
hom_mat2d_translate → hom_mat2d_rotate : 平移后旋转
    • 坐标系基准

      平移量 (Tx, Ty)始终基于原始坐标系。若之前有旋转/缩放,需手动计算偏移方向。
    • 复合变换验证

      使用affine_trans_pixel验证关键点变换结果:
* 测试点 (0,0) 的变换结果
affine_trans_pixel(HomMat2DTranslate, 0, 0, Qx, Qy)
disp_message(WindowHandle, '平移后坐标: (' + Qx + ',' + Qy + ')', 'window', 10, 10, 'black', 'true')

错误排查

现象 原因 解决方案
平移方向相反 坐标系方向理解错误 HALCON中Y轴向下为正,检查符号。
变换结果偏离预期 变换顺序错误 调整hom_mat2d_rotatehom_mat2d_translate调用顺序。
平移后图像边缘被裁剪 未扩展画布 使用affine_trans_image时设置'adapt_size'参数为'true'

5.仿射变换算子(轮廓)affine_trans_contour_xld(Contours : ContoursAffineTrans : HomMat2D : )详解:

函数原型:

affine_trans_contour_xld(
Contours : : // 输入:原始XLD轮廓
HomMat2D : : // 输入:2D仿射变换矩阵
: ContoursAffineTrans // 输出:变换后的XLD轮廓
)

功能描述

    • 作用:将输入的 XLD轮廓 通过指定的仿射变换矩阵 HomMat2D 进行几何变换(平移、旋转、缩放、剪切等),生成变换后的新轮廓。
    • 数学原理

      对轮廓中的每个点 (x, y) 应用变换:

其中 (x', y') 是变换后的坐标。

参数说明

参数 类型 说明
Contours XLD对象 输入的XLD轮廓(如边缘、多边形等)。
HomMat2D 矩阵 二维齐次变换矩阵,由 hom_mat2d_rotatehom_mat2d_translate 等生成。
ContoursAffineTrans XLD对象 输出的变换后轮廓,保留原始属性(如闭合性、点顺序)。

案例1:平移矩形轮廓

* 创建矩形XLD轮廓
gen_rectangle2_contour_xld (Rectangle, 100, 100, 0, 50, 30) * 生成平移变换矩阵(向右50像素,向下30像素)
hom_mat2d_identity (HomMat2D)
hom_mat2d_translate (HomMat2D, 50, 30, HomMat2DTranslate) * 应用平移变换
affine_trans_contour_xld (Rectangle, HomMat2DTranslate, RectangleTrans)

案例2:绕中心旋转并缩放

* 生成圆形XLD轮廓
gen_circle_contour_xld (Circle, 200, 200, 50, 0, 6.28318, 'positive', 1) * 绕中心点(200,200)旋转30度并缩放0.8倍
hom_mat2d_identity (HomMat2D)
hom_mat2d_rotate (HomMat2D, rad(30), 200, 200, HomMat2DRotate)
hom_mat2d_scale (HomMat2DRotate, 0.8, 0.8, 200, 200, HomMat2DScale) * 应用复合变换
affine_trans_contour_xld (Circle, HomMat2DScale, CircleTrans)

关键注意事项

    1. 变换顺序

      矩阵乘法顺序决定变换执行顺序。例如:

* 先平移后旋转 vs 先旋转后平移
hom_mat2d_translate → hom_mat2d_rotate → 平移后旋转
hom_mat2d_rotate → hom_mat2d_translate → 旋转后平移
  1. 坐标系方向

    HALCON图像坐标系原点在左上角,x轴向右,y轴向下。变换矩阵中的坐标需与此一致。

  2. 性能优化

    • 避免频繁变换:若需多次应用相同变换,可预计算矩阵。
    • 使用hom_mat2d_invert快速逆变换。

应用场景

  1. 目标定位

    将模板轮廓变换到检测位置,用于匹配验证。
  2. 运动补偿

    动态调整轮廓以跟踪运动物体。
  3. 图像配准

    对齐不同视角或时间点的轮廓数据。

错误排查

现象 可能原因 解决方案
变换后轮廓消失 矩阵错误导致轮廓移出图像范围 检查变换参数或扩展图像区域。
轮廓形状畸变 缩放/剪切参数不合理 验证矩阵是否包含非法操作(如负缩放)。
性能低下 高密度轮廓+复杂变换 简化轮廓或优化矩阵生成逻辑。

6.仿射变换算子(区域)affine_trans_region(Region : RegionAffineTrans : HomMat2DInterpolate : )详解:

函数原型:

affine_trans_region(
Region : : // 输入:待变换的区域(Region)
HomMat2D : : // 输入:二维齐次变换矩阵
Interpolate : : // 输入:插值方法(区域像素处理方式)
: RegionAffineTrans // 输出:变换后的区域
)

参数详解

参数 类型 说明
Region Region 输入区域(需为非空区域)。
HomMat2D Matrix 二维齐次变换矩阵,由 hom_mat2d_rotatehom_mat2d_scale 等生成。
Interpolate String 插值方法,控制变换后区域的像素填充方式,可选值:'nearest_neighbor'(最近邻,速度快)、'bilinear'(双线性插值,边缘更平滑)、'constant'(固定值填充)。
RegionAffineTrans Region 输出区域,执行仿射变换后的结果。

核心功能

    1. 几何变换

      对输入区域执行 ​平移、旋转、缩放、剪切 等复合变换,生成新区域。

    2. 插值控制

      根据 Interpolate 参数选择不同的像素处理策略:

      • ​**'nearest_neighbor'**:速度快,但边缘可能产生锯齿(适合二值区域)。
      • ​**'bilinear'**:边缘平滑,适合需要亚像素精度的场景(如测量)。
      • ​**'constant'**:用固定灰度值填充空白区域(需配合 set_grayval 使用)。

示例1:旋转区域(工业零件定位)

* 创建初始矩形区域
gen_rectangle1 (Region, 100, 100, 200, 300) * 生成旋转变换矩阵(绕左上角原点旋转30度)
hom_mat2d_identity (HomMat2D)
hom_mat2d_rotate (HomMat2D, rad(30), 0, 0, HomMat2DRotate) * 应用变换(使用双线性插值保持边缘平滑)
affine_trans_region (Region, HomMat2DRotate, 'bilinear', RegionRotated)

示例2:平移+缩放区域(图像ROI调整)

* 生成复合变换矩阵(先缩放0.5倍,再平移)
hom_mat2d_identity (HomMat2D)
hom_mat2d_scale (HomMat2D, 0.5, 0.5, 0, 0, HomMat2DScale)
hom_mat2d_translate (HomMat2DScale, 50, 100, HomMat2DTranslate) * 应用变换(最近邻插值,快速处理)
affine_trans_region (Region, HomMat2DTranslate, 'nearest_neighbor', RegionTrans)

应用场景

    1. 目标姿态调整

      将检测到的区域变换到标准位置,用于后续测量或比对。
    2. ROI动态跟踪

      根据运动估计更新感兴趣区域的位置和角度。
    3. 图像增强

      生成旋转/缩放的训练数据(数据增强)。

注意事项

  1. 插值选择

    • 二值区域 → 优先使用 'nearest_neighbor'(避免灰度插值引入噪声)。
    • 灰度区域 → 选择 'bilinear''constant'(保持边缘平滑)。
  2. 性能优化

    • 对二值区域,'nearest_neighbor''bilinear'快3-5倍
    • 提前裁剪区域(reduce_domain)以减少计算量。
  3. 边界处理

    • 若变换后区域超出图像范围,超界部分会被自动裁剪。
    • 使用 full_domain 恢复完整区域(可能包含无效像素)。

可视化验证

* 显示原始区域和变换后的区域
dev_display (Region)
dev_set_color ('green')
dev_display (RegionAffineTrans) * 显示变换矩阵作用点(如旋转中心)
affine_trans_pixel (HomMat2D, 0, 0, TransX, TransY)
gen_cross_contour_xld (Cross, TransY, TransX, 20, 0.785)
dev_display (Cross)

7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1Column1Angle1Row2Column2Angle2 : HomMat2D)详解:

函数原型:

vector_angle_to_rigid(
: :
Row1, Column1, Angle1, // 原始坐标系下的参考点及角度
Row2, Column2, Angle2, // 目标坐标系下的参考点及角度
: HomMat2D // 输出的刚体变换矩阵
)

参数详解

参数 类型 说明
Row1, Column1 浮点数 原始坐标系中的参考点坐标(如模板中心点)。
Angle1 浮点数 原始坐标系中的角度(弧度),通常为0(模板的初始角度)。
Row2, Column2 浮点数 目标坐标系中的参考点坐标(如检测到的目标中心点)。
Angle2 浮点数 目标坐标系中的角度(弧度),表示相对于原始角度的旋转量。
HomMat2D 矩阵 输出的2D刚体变换矩阵(包含平移和旋转,无缩放/剪切)。

功能描述

    • 作用:生成一个刚体变换矩阵,将原始参考点 (Row1, Column1) 旋转并平移到目标参考点 (Row2, Column2),同时将角度 Angle1 调整到 Angle2
    • 数学原理

      变换矩阵 ​H 的构成:

  • R 为旋转矩阵(角度差为 Angle2 - Angle1
  • T 为平移矩阵(平移量为 (Row2 - Row1, Column2 - Column1)

场景1:模板匹配后的姿态对齐

* 假设模板中心为(100,100),角度为0
* 检测到目标中心为(150,200),旋转角度为30°
vector_angle_to_rigid(100, 100, 0, 150, 200, rad(30), HomMat2D)
* 将模板区域变换到目标位置
affine_trans_region(TemplateRegion, RegionTrans, HomMat2D, 'nearest_neighbor')

场景2:机械臂抓取坐标转换

* 视觉系统检测到物体中心为(300,250),旋转角度45°
* 机械臂坐标系需要平移到(500,600),并调整角度到0°
vector_angle_to_rigid(300, 250, rad(45), 500, 600, 0, HomMat2D)
* 转换抓取点坐标
affine_trans_pixel(HomMat2D, GraspX, GraspY, TransX, TransY)

零件旋转角度补偿

* 读取图像并定位目标
read_image(Image, 'part.png')
find_shape_model(Image, ModelID, ..., Row, Column, Angle, Score) * 生成刚体变换矩阵(从模板原点(0,0)到检测位置)
vector_angle_to_rigid(0, 0, 0, Row, Column, Angle, HomMat2D) * 变换模板ROI到目标位置
affine_trans_region(TemplateROI, TransformedROI, HomMat2D, 'nearest_neighbor') * 在变换后的ROI内执行检测
reduce_domain(Image, TransformedROI, ImageCropped)
threshold(ImageCropped, Region, 0, 128)

关键注意事项

    1. 角度单位

      HALCON中角度必须使用弧度,可用rad(角度)转换,如 rad(30) 表示30度。

    2. 坐标系方向

      HALCON图像坐标系原点在左上角,Y轴向下。若与机械臂坐标系(通常Y轴向上)不一致,需额外转换。

    3. 复合变换

      若需叠加缩放或剪切,需手动组合矩阵:

* 先缩放后刚体变换
hom_mat2d_scale(HomMat2D, 0.5, 0.5, 0, 0, HomMat2DScale)
hom_mat2d_compose(HomMat2DScale, HomMat2D, HomMat2DCombined)

可视化验证

* 显示变换前后关键点
gen_cross_contour_xld(Cross1, Row1, Column1, 20, 0.785) // 原始点
gen_cross_contour_xld(Cross2, Row2, Column2, 20, 0.785) // 目标点
affine_trans_contour_xld(Cross1, HomMat2D, Cross1Trans) // 变换后的点
dev_display(Image)
dev_display(Cross1)
dev_display(Cross2)
dev_display(Cross1Trans) // 应重合于Cross2

关于矩阵知识的是大学的线性代数课程,有兴趣可以学一下我这篇博客:关于opengl中的三维矩阵平移代码,矩阵旋转代码,推导过程理解 OpenGL计算机图形学的一些必要矩阵运算知识 glTranslatef(x,y,z)glRotatef(angle,x,y,z)函数详解

接下来进入正题实例代码(注释我都打好了,结合上面的算子和矩阵你们应该还是非常好理解的,这个demo会了以后,正常的工业检测都是这样的套路,先找到个不变得模板定位,然后将区域转换过去检测):

对已经定位到的区域进行检测的一些方法总结也可以看看这篇博客,或者我的halcon入门教程(五):

* 打开一个黑色背景的显示窗口,用于后续图像和结果的展示
dev_open_window (0, 0, 1000, 1000, 'black', WindowHandle)
* 获取当前窗口句柄,用于后续绘图操作
dev_get_window (WindowHandle1) * 读取图像文件并转换为灰度图像
read_image (Image, '0.bmp')
*如果已经是单通道图像直接忽略
rgb1_to_gray (Image, GrayImage) * -------- 模板区域定义 ---------
* 在窗口上手动绘制矩形ROI(用于创建模板) 这边选择的是带方向的矩形,也可以直接画普通矩形
draw_rectangle2 (WindowHandle1, RowMod, ColumnMod, PhiMod, LengthMod1, LengthMod2)
* 根据绘制的参数生成矩形区域对象
gen_rectangle2 (Rectangle1, RowMod, ColumnMod, PhiMod, LengthMod1, LengthMod2)
* 裁剪出矩形区域的图像(模板图像)
reduce_domain (GrayImage, Rectangle1, ImageReduced1) * -------- 检测区域定义 ---------
* 在窗口上手动绘制第二个矩形ROI(用于检测区域)
draw_rectangle2 (WindowHandle1, Row1, Column1, Phi, Length1, Length2)
gen_rectangle2 (Rectangle, Row1, Column1, Phi, Length1, Length2)
* 裁剪检测区域图像
reduce_domain (GrayImage, Rectangle, ImageReduced)
* 对检测区域进行阈值分割(灰度0~80)
threshold (ImageReduced, Region, 0, 80)
* 计算区域面积和中心坐标
area_center (Region, Area, Row222, Column222) * -------- 形状模板建模 ---------
* 创建形状匹配模型(金字塔级别=3,全角度搜索)
* 参数说明:
* [14,31,4] : 最小对比度参数(金字塔各级对比度阈值)
* 6 : 模型生成时的最大边缘噪声容限
create_shape_model (ImageReduced1, 3, rad(0), rad(360), rad(1.5523), ['none','no_pregeneration'], 'use_polarity', [14,31,4], 6, ModelID)
* 获取模型的轮廓用于可视化
get_shape_model_contours (ModelContours, ModelID, 1) * -------- 图像预处理 ---------
* 对原图进行25度旋转(模拟物体倾斜场景)
rotate_image (GrayImage, ImageRotate, 25, 'constant') * -------- 形状匹配过程 ---------
* 在旋转后的图像中搜索模板
* 参数说明:
* [3,2] : 金字塔级别范围(从3到2级) 越大速度越快精度越低,1-3之间是比较合适的
* 0.75 : 最小匹配分数阈值
* 'least_squares' : 亚像素精度优化方法 一般固定选择一个就行
find_shape_model (ImageRotate, ModelID, rad(0), rad(360), 0.5, 0, 0.5, 'least_squares', [3,2], 0.75, Row, Column, Angle, Score) * -------- 匹配结果后处理 ---------
for Index := 0 to |Row|-1 by 1
* 生成仿射变换矩阵 后面两步的前置变量生成,说白了就是随便创建个矩阵变量
hom_mat2d_identity (HomMat2D)
* 将矩阵叠加旋转和平移变换 想象一下:后两个参数为0 就是绕自身旋转调整角度后直接平移 不为0就是绕某点坐标选择
hom_mat2d_rotate (HomMat2D, Angle[Index], 0, 0, HomMat2D)
hom_mat2d_translate (HomMat2D, Row[Index], Column[Index], HomMat2D) * 通过前面设置的移动矩阵参数 将模板轮廓变换到匹配位置
affine_trans_contour_xld (ModelContours, TransContours, HomMat2D)
dev_display (TransContours)
* 显示变换后的轮廓 * 生成刚体变换矩阵(从模板原点变换到匹配位置)这个给后面的检测区域变换使用
*RowMod ColumnMod是绘制检测区域的中心点 想象一下:让这个区域跟随你的模板匹配走一样路程到相对应的位置
vector_angle_to_rigid (RowMod, ColumnMod, 0, Row[Index], Column[Index], Angle[Index], HomMat2D2) * 将检测区域ROI变换到匹配位置
affine_trans_region (Rectangle, RegionAffineTrans2, HomMat2D2, 'nearest_neighbor')
* 在变换后的ROI内进行阈值分割
reduce_domain (ImageRotate, RegionAffineTrans2, ImageReduced2)
threshold (ImageReduced2, Region2, 0, 80) * 计算并显示目标中心点
area_center (Region2, Area2, Row4, Column4)
gen_cross_contour_xld (Cross, Row4, Column4, 15, 0)
* 生成十字标记
endfor
clear_shape_model (ModelID) * 注意:实际工业应用中需添加以下内容:
* 1. 错误处理(try/catch)
* 2. 模型资源释放(clear_shape_model)
* 3. 匹配分数过滤(如只保留Score>0.65的结果)
* 4. 坐标单位转换(像素到物理尺寸)

halcon 入门教程(六) 图像匹配(基于形状的模板匹配)与缺陷检测区域定位的更多相关文章

  1. PySide——Python图形化界面入门教程(六)

    PySide——Python图形化界面入门教程(六) ——QListView和QStandardItemModel 翻译自:http://pythoncentral.io/pyside-pyqt-tu ...

  2. Elasticsearch入门教程(六):Elasticsearch查询(二)

    原文:Elasticsearch入门教程(六):Elasticsearch查询(二) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...

  3. 《zw版·Halcon入门教程与内置demo》

    <zw版·Halcon入门教程与内置demo> halcon系统的中文教程很不好找,而且大部分是v10以前的版本. 例如,QQ群: 247994767(Delphi与halcon), 共享 ...

  4. 无废话ExtJs 入门教程六[按钮:Button]

    无废话ExtJs 入门教程六[按钮:Button] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在表单里加了个两个按钮“提交”与重置.如下所示代码区的第68行位置, butt ...

  5. 【Zigbee技术入门教程-号外】基于Z-Stack协议栈的抢答系统

    [Zigbee技术入门教程-号外]基于Z-Stack协议栈的抢答系统 广东职业技术学院  欧浩源 一.引言    2017年全国职业院校技能大赛"物联网技术应用"赛项中任务三题2的 ...

  6. RabbitMQ入门教程(六):路由选择Routing

    原文:RabbitMQ入门教程(六):路由选择Routing 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...

  7. Halcon编程-基于形状特征的模板匹配

    halcon软件最高效的一个方面在于模板匹配,号称可以快速进行柔性模板匹配,能够非常方便的用于缺陷检测.目标定位.下面以一个简单的例子说明基于形状特征的模板匹配.      为了在右图中,定位图中的三 ...

  8. 无废话WCF入门教程六[一个简单的Demo]

    一.前言 前面的几个章节介绍了很多理论基础,如:什么是WCF.WCF中的A.B.C.WCF的传输模式.本文从零开始和大家一起写一个小的WCF应用程序Demo. 大多框架的学习都是从增.删.改.查开始来 ...

  9. 【转】WCF入门教程六[一个简单的Demo]

    一.前言 前面的几个章节介绍了很多理论基础,如:什么是WCF.WCF中的A.B.C.WCF的传输模式.本文从零开始和大家一起写一个小的WCF应用程序Demo. 大多框架的学习都是从增.删.改.查开始来 ...

  10. [数据与分析可视化] D3入门教程2-在d3中构建形状

    d3.js入门教程2-在 d3.js中构建形状 文章目录 d3.js入门教程2-在 d3.js中构建形状 形状的添加 圆形的添加 矩形的添加 线段的添加 文本的添加 折线的添加 区域的添加 圆弧的添加 ...

随机推荐

  1. WxPython跨平台开发框架之复杂界面内容的分拆和重组处理

    复杂界面内容的分拆和重组处理是现代软件开发中常见的做法,尤其在开发大型应用程序时,可以大幅提升开发效率.可维护性和用户体验.通过将复杂的界面内容分拆成更小的模块,每个模块都专注于单一功能或组件,代码更 ...

  2. [转]Pelco-D协议使用

    1.Pelco-D协议格式如下图所示: 2. 通用示例为:水平向右控制 FF address 00 02 Hspeed 00 checksum水平向左控制 FF address 00 04 Hspee ...

  3. SSM或Spring Boot开发中,mapper包中的mapper.xml没有编译到targger中的解决办法

    SSM或Spring Boot开发中,mapper包中的mapper.xml没有编译到targger中的解决办法 在pom文件中加入如下配置: <resources> <!-- 编译 ...

  4. Unix和Windows操作系统中路径中的正斜杠和反斜杠的区别

  5. MACOS 降级

    最近升级了macos 15.2,结果导致外接显示器显示不正常,经常断掉或者黑屏,因此macos进行降级处理: 1. 首先在App Store下载Ventura 系统; 2. 准备一个16G的U盘,然后 ...

  6. 【Docker】---Docker入门篇(1)

    Docker入门篇 简单一句话: Docker 是一个便携的应用容器. 一.Docker的作用 网上铺天盖地的是这么说的: (1) Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得 ...

  7. kali 2019-04版安装问题

    在这里主要解决的是kali的undercover mode 存在BUG,切换后出现无法还原.或还原失败的情况. 如果要解决的是中文乱码.kali桌面种类与安装和kali桌面切换的问题,直接看最底部的连 ...

  8. 小程序uView中loadMore 加载更多

    <u-loadmore :status="status" :icon-type="iconType" :load-text="loadText& ...

  9. 旁站和C段查询

    旁站和C段查询 旁站和C段的概念 旁站 旁站(也称为邻居站点)是指与目标网站在同一服务器上的其他网站.这些网站与目标网站共享相同的网络环境,包括IP地址(或更具体地说,共享相同的C段IP地址,但D段不 ...

  10. 流程控制之增强for循环

    语法 for (声明语句:表达式){    //代码语句} 实例: package com.yeyue.struct;​public class ForDemo05 {    public stati ...