时间:2025-03-20 17:14
人气:
作者:admin
原文作者:aircraft
原文链接:https://www.cnblogs.com/DOMLX/p/18783476
有兴趣可以多看其他的halcon教程
本篇主要讲一下工业中最常用的基于形状的模板匹配,以及根据模板定位锁定待检测区域的位置。注意本篇对于工业的缺陷检测是最基础的也是最重要的!!!不管是检测还是量测,前提都是你能定位到需要检测和量测的具体位置,然后在通过具体的分析方法去检测缺陷和测量长宽之类的参数。如果你学习掌握了本篇的demo示例,基本一些简单的工业缺陷检测是没有什么大问题的。
本来应该是有个halcon的程序集里的示例代码的,但是我没找到比较短的,好入门的,所以我临时手写了一个halcon例子。至于其他的例子可以去看halcon官方的。

一.模板匹配简介
halcon中的模板匹配是一种图像处理技术,主要用于在新的图像中找到特定模板图像的位置。模板匹配通过算法比较图像和模板之间的相似度,从而实现对目标的定位和识别。HALCON提供了多种模板匹配方法:
'keypoint_radius':特征点邻域半径,影响描述符的区分度。'min_score':匹配分数阈值,过滤低置信度匹配。
'mask_size':匹配时的掩模大小,影响抗噪声能力。'subpixel':是否启用亚像素精度('true'/'false')。
'angle_step':角度搜索步长(越小越慢但精度↑)。'scale_min'/'scale_max':允许的缩放范围。'min_contrast':最小边缘对比度(过滤噪声)。
'component_relation':子组件间的空间约束(如距离容差)。'min_component_score':单个子组件的最低匹配分数。'deformation_smoothness':形变平滑度约束(值越高形变越受限)。'max_deformation':最大允许形变量(像素单位)。
'perspective_model':是否启用透视模型('true'/'false')。'max_deformation':最大形变参数值。| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 匹配分数低 | 模板与图像差异大 | 检查光照、对比度,调整min_contrast |
| 匹配时间过长 | 搜索范围过大 | 缩小角度/缩放范围,增大angle_step |
| 误匹配多 | 阈值设置过松 | 提高min_score,启用max_overlap |
| 无法创建模型 | 模板图像质量差 | 使用edges_image强化边缘 |
二.图像匹配以及缺陷区域定位
老规矩,直接上图:

我们接下来对一个零件建立模板,并且我们建立一个小孔区域的缺陷检测ROI区域,当我们匹配到这个零件的时候,检测缺陷的区域也会到当前零件的小孔位置去,这样我们就可以对其进行区域缺陷检测了(工业中非常常用!!!)
大概过程如下:
第一步:画模板区域,框选了一颗零件矩形区域。

第二步:画待检测区域

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

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


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

OK 实例的过程讲完了,我们在认识一下接下来要用到的算子,然后就直接看代码理解。
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 // 输出模型句柄
)
NumLevels (金字塔层级数)AngleStart 与 AngleExtent (角度范围)AngleStart=0, AngleExtent=0(无旋转)AngleStart=0, AngleExtent=rad(360)AngleStart=rad(-30), AngleExtent=rad(60) 一般前面的绝对值是后面一半这样设置AngleStep (角度步长)'auto'**:自动计算(推荐优先使用)rad(1.0)rad(0.1)Optimization (优化模式)'none':不优化(内存占用最小)'pregeneration':预生成模型(匹配最快,内存占用高)'no_pregeneration':不预生成(内存占用低,匹配稍慢)'pregeneration''no_pregeneration'Metric (匹配度量方式)'use_polarity':要求模板与目标对比度极性相同(亮/暗一致)'ignore_global_polarity':允许全局极性反转(如白底黑字→黑底白字)'ignore_local_polarity':允许局部极性变化(抗光照不均)'use_polarity''ignore_global_polarity'Contrast 与 MinContrast (对比度参数)Contrast:各金字塔层的对比度阈值(列表,长度=NumLevels)MinContrast:模型允许的最小边缘对比度* 参数配置
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
)
* 参数配置
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增强边缘对比度。reduce_domain缩小模板区域,去除无关背景。find_shape_model中启用'least_squares'亚像素模式。通过精准配置create_shape_model参数,可兼顾速度与精度,满足工业检测的严苛要求。建议使用inspect_shape_model工具验证模型质量,并根据实际场景微调参数。
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 // 输出坐标、角度及分数
)
AngleStart 与 AngleExtentAngleStart=0, AngleExtent=0AngleStart=rad(-30), AngleExtent=rad(60)MinScore (最小匹配分数)NumMatches (最大匹配数量)MaxOverlap (最大重叠度一般我们设置最小为0.01或者0.1,不要设置成0)SubPixel (亚像素模式)'none':禁用(最快)'interpolation':插值法(平衡)'least_squares':最小二乘优化(最精确)'least_squares''interpolation' 或 'none'NumLevels (金字塔层级范围)[起始层, 结束层](需≤创建模型时的金字塔层数)可以理解成两次匹配,一次粗匹配一次细匹配一般我们这样设置【3-2】或者【2-1】[3,1](从低分辨率到高分辨率)[0,2](从高分辨率开始)Greediness (贪婪系数)
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
)
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, Phi, Px, Py : HomMat2DRotate)详解:
函数原型:
hom_mat2d_rotate(
: :
HomMat2D, // 输入齐次变换矩阵
Phi, // 旋转角度(弧度,正值逆时针)
Px, Py, // 旋转中心坐标(原始坐标系中的点)
: HomMat2DRotate // 输出旋转后的变换矩阵
)
rad(30) 表示逆时针旋转30度。HomMat2D),再绕原始坐标系中的点 (Px, Py) 旋转角度 Phi。
* 读取图像并获取尺寸
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')
* 将物体平移到(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, Tx, Ty : HomMat2DTranslate)详解:
函数原型:
hom_mat2d_translate(
: :
HomMat2D, // 输入齐次变换矩阵
Tx, Ty, // X/Y方向平移量(像素单位)
: HomMat2DTranslate // 输出平移后的变换矩阵
)
| 参数名 | 类型 | 说明 |
|---|---|---|
HomMat2D |
矩阵 | 输入的二维齐次变换矩阵。若初始为单位矩阵(无变换),可通过hom_mat2d_identity创建。 |
Tx, Ty |
数值 | X和Y方向的平移量(像素单位)。正值为向右/下平移,负值为向左/上平移。 |
HomMat2DTranslate |
矩阵 | 输出矩阵,包含原矩阵的变换叠加平移后的结果。 |

这意味着先执行原矩阵的变换,再进行平移。
* 创建单位矩阵(无变换)
hom_mat2d_identity(HomMat2D)
* 向右平移50像素,向下平移30像素
hom_mat2d_translate(HomMat2D, 50, 30, HomMat2DTranslate)
* 应用平移变换到图像
affine_trans_image(Image, ImageTranslated, HomMat2DTranslate, 'constant', 'false')
* 绕图像中心旋转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 : 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对象 | 输出的变换后轮廓,保留原始属性(如闭合性、点顺序)。 |
* 创建矩形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)
* 生成圆形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 : 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 使用)。* 创建初始矩形区域
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)
* 生成复合变换矩阵(先缩放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)
插值选择:
'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, 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。
Angle2 - Angle1)(Row2 - Row1, Column2 - Column1))
* 假设模板中心为(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')
* 视觉系统检测到物体中心为(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入门教程(六) 缺陷检测:
* 打开一个黑色背景的显示窗口,用于后续图像和结果的展示
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)
* 将矩阵叠加旋转和平移变换 想象一下:后两个参数就是绕某点坐标旋转
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. 坐标单位转换(像素到物理尺寸)
转发和使用本文,请注明作者信息和原文地址---本文原作者为aircraft ---大家好我是徐飞机,有没有大佬们的公司招c++开发/图像处理/opengl/opencv/halcon实习的啊,带上我一个呗QAQ。。。hhhhhh 想要免费获取前端,后端,c/c++,matlab,Python,opencv,机器学习,深度学习,安卓,java,等等全套视频教程请关注机器视觉开发公众号,转发集赞28即可百度云获得hhhhhhhh