文章目录
HALCON 剃须刀片检测程序详解(逐行注释+思路归纳)
1. 程序概述
该程序使用 基于形状的匹配(Shape-Based Matching) 检测剃须刀片,并通过 测量工具(Measure Tool) 检查刀片的齿状结构是否完整。程序支持 两种测量模式:
- 全仿射变换(Full Affine Transformation)
- 平移测量(
translate_measure
)
通过 USING_TRANSLATE_MEASURE
变量切换模式。
2. 逐行代码解析
(1) 初始化设置
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 () // 暂停(调试用)
作用:初始化HALCON环境,加载图像,并准备显示窗口。
(2) 选择模型区域(ROI)
Row1 := 46 // 第一个矩形的起始行坐标
Column1 := 57 // 第一个矩形的起始列坐标
Row2 := 79 // 第一个矩形的结束行坐标
Column2 := 94 // 第一个矩形的结束列坐标
gen_rectangle1 (ROIPart1, Row1, Column1, Row2, Column2) // 创建第一个矩形ROI
gen_rectangle1 (ROIPart2, Row1 + 364, Column1 + 13, Row2 + 364, Column2 + 13) // 创建第二个矩形ROI(偏移364行+13列)
union2 (ROIPart1, ROIPart2, ModelROI) // 合并两个ROI
area_center (ModelROI, Area, CenterROIRow, CenterROIColumn) // 计算ROI的中心点
dev_display (ModelImage) // 重新显示图像
dev_display (ModelROI) // 显示ROI区域
stop () // 暂停
作用:
- 选择刀片的关键区域(两个矩形)作为训练模型的输入。
- 计算ROI的中心点,用于后续仿射变换的基准点。
(3) 创建形状模型
reduce_domain (ModelImage, ModelROI, ImageROI) // 裁剪图像,仅保留ROI区域
create_generic_shape_model (ModelID) // 创建通用形状模型
set_generic_shape_model_param (ModelID, 'num_levels', 4) // 设置金字塔层数(4层)
set_generic_shape_model_param (ModelID, 'optimization', 'none') // 不优化模型(更快训练)
set_generic_shape_model_param (ModelID, 'contrast_high', 30) // 设置高对比度阈值(30)
train_generic_shape_model (ImageROI, ModelID) // 训练模型
get_shape_model_contours (ModelContours, ModelID, 1) // 获取模型的轮廓
hom_mat2d_identity (HomMat2DModelContours) // 创建单位矩阵(用于仿射变换)
hom_mat2d_translate (HomMat2DModelContours, CenterROIRow, CenterROIColumn, HomMat2DModelContours) // 平移矩阵(使轮廓居中)
affine_trans_contour_xld (ModelContours, ModelContoursTranslated, HomMat2DModelContours) // 变换轮廓到图像中心
dev_clear_window () // 清空窗口
dev_set_color ('blue') // 设置颜色(蓝色)
dev_display (ModelContoursTranslated) // 显示变换后的轮廓
stop () // 暂停
作用:
- 训练一个 基于形状的匹配模型,用于后续搜索刀片。
- 获取模型的轮廓,并 平移至图像中心,方便后续测量。
(4) 创建测量ROI
Rect1Row := 244 // 测量ROI1的行坐标
Rect1Col := 73 // 测量ROI1的列坐标
DistColRect1Rect2 := 17 // ROI1和ROI2的列间距
Rect2Row := Rect1Row // ROI2的行坐标(与ROI1相同)
Rect2Col := Rect1Col + DistColRect1Rect2 // ROI2的列坐标(偏移17像素)
RectPhi := rad(90) // ROI旋转角度(90度,垂直方向)
RectLength1 := 122 // ROI长度(长边)
RectLength2 := 2 // ROI宽度(短边)
gen_rectangle2 (MeasureROI1, Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2) // 创建第一个测量ROI
gen_rectangle2 (MeasureROI2, Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2) // 创建第二个测量ROI
dev_display (ModelImage) // 显示图像
dev_set_color ('yellow') // 设置颜色(黄色)
dev_display (MeasureROI1) // 显示ROI1
dev_display (MeasureROI2) // 显示ROI2
作用:
- 定义两个 垂直矩形ROI,用于测量刀片的齿状结构。
- 由于刀片是垂直排列的,所以
RectPhi = 90°
(垂直方向)。
(5) 平移测量ROI(仿射变换准备)
get_system ('clip_region', OriginalClipRegion) // 保存当前裁剪设置
set_system ('clip_region', 'false') // 禁用裁剪(防止ROI被截断)
move_region (MeasureROI1, MeasureROI1Ref, -CenterROIRow, -CenterROIColumn) // 平移ROI1到原点
move_region (MeasureROI2, MeasureROI2Ref, -CenterROIRow, -CenterROIColumn) // 平移ROI2到原点
set_system ('clip_region', OriginalClipRegion) // 恢复裁剪设置
DistRect1CenterRow := Rect1Row - CenterROIRow // 计算ROI1相对于中心的偏移
DistRect1CenterCol := Rect1Col - CenterROIColumn // 计算ROI1列偏移
DistRect2CenterRow := Rect2Row - CenterROIRow // 计算ROI2行偏移
DistRect2CenterCol := Rect2Col - CenterROIColumn // 计算ROI2列偏移
if (USING_TRANSLATE_MEASURE != 0) // 如果使用平移测量模式
gen_measure_rectangle2 (Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1) // 创建测量对象1
gen_measure_rectangle2 (Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2) // 创建测量对象2
endif
stop () // 暂停
作用:
- 平移测量ROI到原点,方便后续仿射变换。
- 如果
USING_TRANSLATE_MEASURE=1
,则 预先创建测量对象,后续只需平移,提高效率。
(6) 搜索刀片(在新图像中)
read_image (SearchImage, 'razors2') // 读取待检测图像
dev_display (SearchImage) // 显示图像
set_generic_shape_model_param (ModelID, 'min_contrast', 10) // 设置最小对比度(10)
set_generic_shape_model_param (ModelID, 'angle_start', 0.0) // 起始角度(0°)
set_generic_shape_model_param (ModelID, 'angle_end', 0.0) // 终止角度(0°,不旋转)
set_generic_shape_model_param (ModelID, 'max_overlap', 0.0) // 最大重叠(0,不允许重叠)
set_generic_shape_model_param (ModelID, 'min_score', 0.8) // 最小匹配分数(0.8)
set_generic_shape_model_param (ModelID, 'greediness', 0.7) // 搜索贪婪度(0.7,平衡速度/精度)
find_generic_shape_model (SearchImage, ModelID, MatchResultID, NumMatchResult) // 搜索匹配的刀片
作用:
- 在新图像
razors2
中搜索刀片,使用训练好的模型。 - 设置搜索参数(角度范围、匹配分数等)。
(7) 遍历匹配结果并检测缺陷
if (NumMatchResult > 0) // 如果找到匹配
get_generic_shape_model_result (MatchResultID, 'all', 'column', Column) // 获取所有匹配的列坐标
Indices := sort_index(Column) // 按列坐标排序(从左到右显示)
for I := 0 to NumMatchResult - 1 by 1 // 遍历每个匹配结果
* --- 方法1:使用 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) // 显示变换后的轮廓
* --- 方法2:直接获取仿射矩阵 ---
get_generic_shape_model_result (MatchResultID, Indices[I], 'hom_mat_2d', MovementOfObject) // 直接获取变换矩阵
get_generic_shape_model_result_object (ModelAtNewPosition, MatchResultID, Indices[I], 'contours') // 直接获取变换后的轮廓
* --- 测量齿状结构 ---
affine_trans_region (MeasureROI1Ref, MeasureROI1AtNewPosition, MovementOfObject, 'constant') // 变换ROI1到匹配位置
affine_trans_region (MeasureROI2Ref, MeasureROI2AtNewPosition, MovementOfObject, 'constant') // 变换ROI2到匹配位置
dev_display (MeasureROI1AtNewPosition) // 显示ROI1
dev_display (MeasureROI2AtNewPosition) // 显示ROI2
affine_trans_pixel (MovementOfObject, DistRect1CenterRow, DistRect1CenterCol, Rect1RowCheck, Rect1ColCheck) // 计算ROI1的新坐标
affine_trans_pixel (MovementOfObject, DistRect2CenterRow, DistRect2CenterCol, Rect2RowCheck, Rect2ColCheck) // 计算ROI2的新坐标
if (USING_TRANSLATE_MEASURE != 0) // 如果使用平移测量
translate_measure (MeasureHandle1, Rect1RowCheck, Rect1ColCheck) // 平移测量对象1
translate_measure (MeasureHandle2, Rect2RowCheck, Rect2ColCheck) // 平移测量对象2
measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1) // 测量齿状结构1
measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2) // 测量齿状结构2
else // 否则,重新创建测量对象
RectPhiCheck := RectPhi + AngleCheck // 调整角度
gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle1) // 创建测量对象1
gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, 'bilinear', MeasureHandle2) // 创建测量对象2
measure_pairs (SearchImage, MeasureHandle1, 2, 25, 'negative', 'all', RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1) // 测量1
measure_pairs (SearchImage, MeasureHandle2, 2, 25, 'negative', 'all', RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2) // 测量2
endif
* --- 检查齿状结构是否完整 ---
NumberTeeth1 := |Width1| // 获取齿的数量(ROI1)
NumberTeeth2 := |Width2| // 获取齿的数量(ROI2)
dev_set_color ('red') // 设置颜色(红色,标记缺陷)
if (NumberTeeth1 < 37) // 如果齿数不足37
for J := 0 to NumberTeeth1 - 2 by 1 // 遍历所有齿
if (Distance1[J] > 4.0) // 如果齿间距 > 4.0(可能缺失)
RowFault := round(0.5 * (RowEdge11[J + 1] + RowEdge21[J])) // 计算缺陷位置
ColFault := round(0.5 * (ColEdge11[J + 1] + ColEdge21[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
* --- 同理检查ROI2 ---
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
作用:
- 遍历所有匹配的刀片,计算其位置和角度。
- 变换测量ROI 到匹配位置。
- 测量齿状结构(使用
measure_pairs
检测边缘对)。 - 检查缺陷:
- 齿数是否足够(
NumberTeeth1 < 37
) - 齿间距是否过大(
Distance1[J] > 4.0
) - 标记缺陷位置,并放大显示。
- 齿数是否足够(
3. 核心思路归纳
步骤 | 关键技术 | 作用 |
---|---|---|
1. 初始化 | dev_update_off , read_image |
加载图像,准备显示 |
2. 选择ROI | gen_rectangle1 , union2 |
定义训练区域 |
3. 训练模型 | create_generic_shape_model , train_generic_shape_model |
创建形状匹配模型 |
4. 定义测量ROI | gen_rectangle2 |
设置检测齿状结构的测量区域 |
5. 搜索匹配 | find_generic_shape_model |
在新图像中定位刀片 |
6. 变换测量ROI | affine_trans_region |
调整测量区域到匹配位置 |
7. 测量齿状结构 | measure_pairs |
检测齿的数量和间距 |
8. 缺陷检测 | if (Distance1[J] > 4.0) |
标记缺失或异常的齿 |
关键点
- 两种测量模式:
USING_TRANSLATE_MEASURE
控制是否复用测量对象(优化性能)。 - 仿射变换:通过
affine_trans_region
和affine_trans_pixel
调整测量ROI。 - 缺陷检测逻辑:齿数不足或间距过大时,标记缺陷并放大显示。
4. 适用场景
- 工业检测:适用于 刀片、齿轮、锯齿状物体 的缺陷检测。
- 高精度定位:基于形状匹配,可适应 轻微旋转和偏移。
- 自动化质检:可集成到生产线,实现 实时检测。
该程序展示了 HALCON在工业视觉检测中的典型应用,结合了 形状匹配、测量工具、仿射变换 等核心技术。