原文作者:aircraft
原文链接:https://www.cnblogs.com/DOMLX/p/18783476
有兴趣可以多看其他的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区域,当我们匹配到这个零件的时候,检测缺陷的区域也会到当前零件的小孔位置去,这样我们就可以对其进行区域缺陷检测了(工业中非常常用!!!)
大概过程如下:
- 读取并显示图像;
- 绘制模板ROI及待检测ROI;
- 创建模型;
- 匹配模板;
- ROI仿射变换,得到待检测ROI位置。
第一步:画模板区域,框选了一颗零件矩形区域。

第二步:画待检测区域

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

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


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

OK 实例的过程讲完了,我们在认识一下接下来要用到的算子,然后就直接看代码理解。
1.创建形状匹配模板算子create_shape_model ([Template](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:) : : [NumLevels](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:), [AngleStart](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:), [AngleExtent](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:), [AngleStep](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:), [Optimization](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:), [Metric](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:), [Contrast](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:), [MinContrast](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : ModelID)详解:) : [ModelID](#1.创建形状匹配模板算子create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metric, Contrast, MinContrast : 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. AngleStart
与 AngleExtent
(角度范围)
- 作用:定义模型在匹配时的旋转角度搜索范围。
- 工业设置:
- 固定角度 :
AngleStart=0
,AngleExtent=0
(无旋转) - 全角度检测 :
AngleStart=0
,AngleExtent=rad(360)
- 固定角度 :
- 案例:
- 传送带零件允许±30°倾斜 →
AngleStart=rad(-30)
,AngleExtent=rad(60) 一般前面的绝对值是后面一半这样设置
- 传送带零件允许±30°倾斜 →
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. Contrast
与 MinContrast
(对比度参数)
- 作用:控制模型边缘特征的提取灵敏度。
- 参数结构:
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
)
性能优化技巧
- 边缘滤波:
在创建模型前使用emphasize
或laplace
增强边缘对比度。 - ROI裁剪:
使用reduce_domain
缩小模板区域,去除无关背景。 - 亚像素优化:
在find_shape_model
中启用'least_squares'
亚像素模式。
通过精准配置create_shape_model
参数,可兼顾速度与精度,满足工业检测的严苛要求。建议使用inspect_shape_model
工具验证模型质量,并根据实际场景微调参数。
2.模板匹配算子find_shape_model ([Image](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:) : : [ModelID](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [AngleStart](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [AngleExtent](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [MinScore](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [NumMatches](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [MaxOverlap](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [SubPixel](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [NumLevels](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [Greediness](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:) : [Row](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [Column](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [Angle](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:), [Score](#2.模板匹配算子find_shape_model(Image : : ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness : Row, Column, Angle, Score)详解:))详解:
函数原型:
find_shape_model(
Image : : // 输入图像(单通道灰度)
ModelID : : // 形状模型句柄
AngleStart : : // 起始角度(弧度)
AngleExtent : : // 角度范围(弧度)
MinScore : : // 最小匹配分数(0-1)
NumMatches : : // 最大匹配数量
MaxOverlap : : // 最大重叠度(0-1)
SubPixel : : // 亚像素模式
NumLevels : : // 搜索金字塔层级范围([起始层, 结束层])
Greediness : : // 贪婪系数(0-1)
: Row, Column, Angle, Score // 输出坐标、角度及分数
)
参数详解与工业配置策略
1. AngleStart
与 AngleExtent
- 作用 :限定匹配时的角度搜索范围,减少计算量。
- 推荐设置 :技巧:
- 固定角度 →
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'
- 坐标精度要求≤0.5像素 →
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 |
最佳实践总结
- 参数联动调整 :创建模型时的
Contrast
与搜索时的NumLevels
需协同优化。 - 结果验证 :使用
dev_display_shape_matching_results
可视化匹配结果。 - 资源释放 :循环结束后调用
clear_shape_model
避免内存泄漏。
通过合理配置find_shape_model
参数,可在工业检测中实现高精度 、高速度的物体定位。
3.旋转矩阵生成算子hom_mat2d_rotate ( : : [HomMat2D](#3.旋转矩阵生成算子hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py : HomMat2DRotate)详解:), [Phi](#3.旋转矩阵生成算子hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py : HomMat2DRotate)详解:), [Px](#3.旋转矩阵生成算子hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py : HomMat2DRotate)详解:), [Py](#3.旋转矩阵生成算子hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py : HomMat2DRotate)详解:) : [HomMat2DRotate](#3.旋转矩阵生成算子hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py : 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')
关键注意事项
- 旋转中心 :
(Px, Py)
必须是原始坐标系中的坐标。若之前的变换已移动物体,需计算其在原始坐标系中的目标位置。 - 变换顺序 :新矩阵按
旋转 × 原始
组合,意味着先执行原始变换,再旋转。 - 角度方向 :正值表示逆时针旋转,使用
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 ( : : [HomMat2D](#4.平移矩阵生成算子hom_mat2d_translate( : : HomMat2D, Tx, Ty : HomMat2DTranslate)详解:), [Tx](#4.平移矩阵生成算子hom_mat2d_translate( : : HomMat2D, Tx, Ty : HomMat2DTranslate)详解:), [Ty](#4.平移矩阵生成算子hom_mat2d_translate( : : HomMat2D, Tx, Ty : HomMat2DTranslate)详解:) : [HomMat2DTranslate](#4.平移矩阵生成算子hom_mat2d_translate( : : HomMat2D, Tx, Ty : 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')
注意事项
- 变换顺序 :
矩阵乘法顺序决定变换执行顺序。例如:- 先旋转后平移 → 物体绕原点旋转,再移动到新位置。
- 先平移后旋转 → 物体移动到新位置后绕该点旋转。
* 顺序不同,结果不同!
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_rotate 和hom_mat2d_translate 调用顺序。 |
平移后图像边缘被裁剪 | 未扩展画布 | 使用affine_trans_image 时设置'adapt_size' 参数为'true' 。 |
5.仿射变换算子(轮廓)affine_trans_contour_xld ([Contours](#5.仿射变换算子(轮廓)affine_trans_contour_xld(Contours : ContoursAffineTrans : HomMat2D : )详解:) : [ContoursAffineTrans](#5.仿射变换算子(轮廓)affine_trans_contour_xld(Contours : ContoursAffineTrans : HomMat2D : )详解:) : [HomMat2D](#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_rotate 、hom_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)
关键注意事项
- 变换顺序:
矩阵乘法顺序决定变换执行顺序。例如:
* 先平移后旋转 vs 先旋转后平移
hom_mat2d_translate → hom_mat2d_rotate → 平移后旋转
hom_mat2d_rotate → hom_mat2d_translate → 旋转后平移
-
坐标系方向:
HALCON图像坐标系原点在左上角,x轴向右,y轴向下。变换矩阵中的坐标需与此一致。 -
性能优化:
- 避免频繁变换:若需多次应用相同变换,可预计算矩阵。
- 使用
hom_mat2d_invert
快速逆变换。
应用场景
- 目标定位:
将模板轮廓变换到检测位置,用于匹配验证。 - 运动补偿:
动态调整轮廓以跟踪运动物体。 - 图像配准:
对齐不同视角或时间点的轮廓数据。
错误排查
现象 | 可能原因 | 解决方案 |
---|---|---|
变换后轮廓消失 | 矩阵错误导致轮廓移出图像范围 | 检查变换参数或扩展图像区域。 |
轮廓形状畸变 | 缩放/剪切参数不合理 | 验证矩阵是否包含非法操作(如负缩放)。 |
性能低下 | 高密度轮廓+复杂变换 | 简化轮廓或优化矩阵生成逻辑。 |
6.仿射变换算子(区域)affine_trans_region ([Region](#6.仿射变换算子(区域)affine_trans_region(Region : RegionAffineTrans : HomMat2D, Interpolate : )详解:) : [RegionAffineTrans](#6.仿射变换算子(区域)affine_trans_region(Region : RegionAffineTrans : HomMat2D, Interpolate : )详解:) : [HomMat2D](#6.仿射变换算子(区域)affine_trans_region(Region : RegionAffineTrans : HomMat2D, Interpolate : )详解:), [Interpolate](#6.仿射变换算子(区域)affine_trans_region(Region : RegionAffineTrans : HomMat2D, Interpolate : )详解:) : )详解:
函数原型:
affine_trans_region(
Region : : // 输入:待变换的区域(Region)
HomMat2D : : // 输入:二维齐次变换矩阵
Interpolate : : // 输入:插值方法(区域像素处理方式)
: RegionAffineTrans // 输出:变换后的区域
)
参数详解
参数 | 类型 | 说明 |
---|---|---|
Region |
Region | 输入区域(需为非空区域)。 |
HomMat2D |
Matrix | 二维齐次变换矩阵,由 hom_mat2d_rotate 、hom_mat2d_scale 等生成。 |
Interpolate |
String | 插值方法,控制变换后区域的像素填充方式,可选值:'nearest_neighbor' (最近邻,速度快)、'bilinear' (双线性插值,边缘更平滑)、'constant' (固定值填充)。 |
RegionAffineTrans |
Region | 输出区域,执行仿射变换后的结果。 |
核心功能
-
几何变换
对输入区域执行 平移、旋转、缩放、剪切 等复合变换,生成新区域。 -
插值控制
根据
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)
应用场景
- 目标姿态调整
将检测到的区域变换到标准位置,用于后续测量或比对。 - ROI动态跟踪
根据运动估计更新感兴趣区域的位置和角度。 - 图像增强
生成旋转/缩放的训练数据(数据增强)。
注意事项
-
插值选择:
- 二值区域 → 优先使用
'nearest_neighbor'
(避免灰度插值引入噪声)。 - 灰度区域 → 选择
'bilinear'
或'constant'
(保持边缘平滑)。
- 二值区域 → 优先使用
-
性能优化:
- 对二值区域,
'nearest_neighbor'
比'bilinear'
快3-5倍。 - 提前裁剪区域(
reduce_domain
)以减少计算量。
- 对二值区域,
-
边界处理:
- 若变换后区域超出图像范围,超界部分会被自动裁剪。
- 使用
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 ( : : [Row1](#7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)详解:), [Column1](#7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)详解:), [Angle1](#7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)详解:), [Row2](#7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)详解:), [Column2](#7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)详解:), [Angle2](#7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : HomMat2D)详解:) : [HomMat2D](#7.生成刚体变换矩阵算子vector_angle_to_rigid( : : Row1, Column1, Angle1, Row2, Column2, Angle2 : 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)
关键注意事项
-
角度单位:
HALCON中角度必须使用弧度 ,可用rad(角度)
转换,如rad(30)
表示30度。 -
坐标系方向:
HALCON图像坐标系原点在左上角,Y轴向下。若与机械臂坐标系(通常Y轴向上)不一致,需额外转换。 -
复合变换:
若需叠加缩放或剪切,需手动组合矩阵:
* 先缩放后刚体变换
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入门教程(五):
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. 坐标单位转换(像素到物理尺寸)