文章目录
🎯 卡尺工具联合使用实战指南(Halcon视觉入门进阶)
在实际的工业视觉项目中,我们常常遇到这样的需求:
先精准找到一个物体的位置,然后对其关键特征(如边缘、孔、圆等)进行精密测量。
如果你只用卡尺工具,有时候无法知道测量区域的精确位置;
如果你只用模板匹配,也无法完成尺寸测量或对边缘精度的检测。
这时候就可以将 模板匹配 + 卡尺工具(直线/圆形) 组合使用,达到“先定位,再测量”的效果。
💡 一、使用场景举例
应用 | 描述 |
---|---|
插座PIN脚检测 | 模板匹配定位插座,再用直线卡尺测量PIN脚高度 |
螺丝孔位测量 | 模板匹配定位螺丝轮廓,再用圆形卡尺检测孔径 |
电池极耳宽度测量 | 定位电池边缘,再用直线卡尺测量极耳的宽度 |
齿轮内孔测量 | 先定位齿轮,再用圆形卡尺量内圆或中心位置 |
🧭 二、典型流程图
1. 模板创建 → 2. 模板匹配 → 3. 坐标系建立 →
4. 卡尺工具构建(直线/圆) → 5. 亚像素边缘测量 → 6. 结果显示与判断
🔧 三、实战示例:模板匹配+直线卡尺测量边缘位置
📋 场景:测量某一区域直线数量
👇 步骤如下:
dev_update_off ()
dev_close_window ()
read_image (Image, 'C:/Users/25972/MVS/Data/Image_20250707163712868.jpg')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_set_line_width (3)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_display (Image)
*
* Search parameters
AngleExtent := 90
AngleExtentTracking := 20
MinScore := 0.4
MinScoreTracking := 0.3
TrackingRadius := 80
ScaleROffset := 0.01
ScaleCOffset := 0.0
Metric := 'use_polarity'
gen_rectangle1 (ModelRegion, 1887.08, 1021.38, 2348.88, 1348.56)
gen_rectangle1 (Circle, 1859.66, 1105.21, 1924.35, 1240.74)
area_center (ModelRegion, Area, Row, Column)
reduce_domain (Image, ModelRegion, ImageReduced)
create_planar_uncalib_deformable_model (ImageReduced, 'auto', [], [], 'auto', 1, [], 'auto', 1, [], 'auto', 'none', Metric, 'auto', 'auto', [], [], ModelID)
set_deformable_model_origin (ModelID, -Row, -Column)
get_deformable_model_contours (Contours, ModelID, 1)
dev_display (Image)
dev_set_color ('green')
dev_set_draw ('margin')
dev_display (Contours)
disp_message (WindowHandle, 'Model created', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
Score := []
select_obj (Contours, ObjectSelected, 1)
get_contour_xld (ObjectSelected, RowOrig, ColOrig)
NotFound := []
TrackingFailed := []
list_files('E:/anglePicture/lew/term', 'files', Files)
tuple_regexp_select (Files, ['.*(bmp|jpg)','ignore_case'], Files)
NumImages := 100
tuple_regexp_select (Files, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
wait_seconds (0.05)
TrackingTime := 0
* Either it is the first image, and one needs to perform full search,
* or else the algorithm lost track of the object, and needs to start
* all over again
* if (|Score| > 0)
* Keep track of the object: project the image with the pose that the object had
* in the previous image. The assumption is that the pose does not change much
* from image to image (see parameter AngleExtentTracking). Update the pose after
* successful search
try
count_seconds (S1)
find_planar_uncalib_deformable_model (Image, ModelID, rad(-AngleExtentTracking / 2), rad(AngleExtentTracking), 1, 1 + ScaleROffset, 1, 1 + ScaleCOffset, MinScoreTracking, 1, 1, 0, 0.9, [], [], HomMat2DTrack, Score)
hom_mat2d_invert (HomMat2DTrack, HomMat2DInvert)
projective_trans_image (Image, TransImage, HomMat2DInvert, 'bilinear', 'false', 'false')
reduce_domain (TransImage, Circle, ImageReduced)
crop_domain(ImageReduced, ImagePart)
count_seconds (S2)
dev_set_color ('green')
catch (Exception)
TrackingTime := S2 - S1
TrackingFailed := [TrackingFailed,Index]
endtry
* endif
endfor
get_image_size (ImagePart, Width, Height)
* Measure 03: Code generated by Measure 03
* Measure 03: Prepare measurement
AmplitudeThreshold := 40
RoiWidthLen2 := 5
set_system ('int_zooming', 'true')
* Measure 03: Coordinates for line Measure 03 [0]
LineRowStart_Measure_03_0 :=Height/2
LineColumnStart_Measure_03_0 := 0
LineRowEnd_Measure_03_0 := Height/2
LineColumnEnd_Measure_03_0 := Width
* Measure 03: Convert coordinates to rectangle2 type
TmpCtrl_Row := 0.5*(LineRowStart_Measure_03_0+LineRowEnd_Measure_03_0)
TmpCtrl_Column := 0.5*(LineColumnStart_Measure_03_0+LineColumnEnd_Measure_03_0)
TmpCtrl_Dr := LineRowStart_Measure_03_0-LineRowEnd_Measure_03_0
TmpCtrl_Dc := LineColumnEnd_Measure_03_0-LineColumnStart_Measure_03_0
TmpCtrl_Phi := atan2(TmpCtrl_Dr, TmpCtrl_Dc)
TmpCtrl_Len1 := 0.5*sqrt(TmpCtrl_Dr*TmpCtrl_Dr + TmpCtrl_Dc*TmpCtrl_Dc)
TmpCtrl_Len2 := RoiWidthLen2
* Measure 03: Create measure for line Measure 03 [0]
* Measure 03: Attention: This assumes all images have the same size!
gen_measure_rectangle2 (TmpCtrl_Row, TmpCtrl_Column, TmpCtrl_Phi, TmpCtrl_Len1, TmpCtrl_Len2, Width, Height, 'nearest_neighbor', MsrHandle_Measure_03_0)
* Measure 03: ***************************************************************
* Measure 03: * The code which follows is to be executed once / measurement *
* Measure 03: ***************************************************************
* Measure 03: The image is assumed to be made available in the
* Measure 03: variable last displayed in the graphics window
copy_obj (ImagePart, Image, 1, 1)
* Measure 03: Execute measurements
measure_pos (Image, MsrHandle_Measure_03_0, 1, AmplitudeThreshold, 'all', 'all', Row_Measure_03_0, Column_Measure_03_0, Amplitude_Measure_03_0, Distance_Measure_03_0)
🔵 四、圆形卡尺的配合使用示例
对于圆孔或螺丝孔等特征,可以使用 gen_measure_circle
配合 measure_pos
或 measure_arc
实现:
* 创建圆形卡尺
gen_measure_circle(Row, Column, Radius,
Width, Height, 'bilinear', MeasureHandle)
* 查找圆边缘
measure_pos(Image, MeasureHandle, Sigma, Threshold,
'all', 'all', RowEdge, ColumnEdge, Amplitude, Distance)
然后拟合圆或计算半径、圆心位置等。
🧠 五、小技巧与建议
目的 | 技巧 |
---|---|
提高鲁棒性 | 在模板匹配中使用多个角度范围 |
测量稳定性 | 卡尺区域设置要略大于边缘区域,避免误检 |
多产品适应 | 支持多个模板,根据匹配结果选择不同测量路径 |
数据输出 | 可导出为 CSV 或画到 UI 中进行展示、判断 |
📌 六、总结
将 模板匹配 和 卡尺工具(直线 / 圆形) 联合使用,是视觉开发中非常经典、实用的组合方式。它能帮我们:
- 精准定位产品特征(模板匹配)
- 稳定提取亚像素边缘(卡尺工具)
- 实现高精度测量、判断、反馈控制
📌 无论你是做尺寸测量、孔位校验、偏差检测,都建议你掌握这种组合方式。它将极大提升你在 Halcon 项目中的开发能力与鲁棒性。