Halcon几何测量实战:从点到线再到区域,5个distance算子保姆级用法解析
Halcon几何测量实战从点到线再到区域的距离计算全解析在工业视觉检测领域几何测量是最基础也最核心的功能之一。无论是检测零件尺寸、判断装配间隙还是评估产品形状偏差都离不开精确的距离计算。Halcon作为工业视觉领域的标杆软件提供了一系列强大的几何测量算子能够满足从简单点到点距离测量到复杂区域间距离分析的各种需求。1. 点与点之间的距离测量点与点之间的距离测量是最基础的几何测量操作Halcon提供了distance_pp算子来实现这一功能。这个算子的应用场景非常广泛比如测量零件上两个孔的中心距、评估产品边缘关键点之间的偏差等。distance_pp算子的基本语法如下distance_pp(Row1, Column1, Row2, Column2, Distance)其中Row1, Column1第一个点的坐标Row2, Column2第二个点的坐标Distance输出的两点间距离在实际应用中我们通常会先通过图像处理获取特征点的坐标然后再计算它们之间的距离。下面是一个典型的应用示例* 读取图像并获取两个特征点 read_image(Image, part_with_holes) * 通过阈值处理和形态学操作定位孔的中心 threshold(Image, Region, 0, 128) connection(Region, ConnectedRegions) select_shape(ConnectedRegions, Holes, area, and, 100, 1000) area_center(Holes, Area, Row, Column) * 计算第一个孔和第二个孔中心之间的距离 distance_pp(Row[0], Column[0], Row[1], Column[1], HoleDistance)注意当处理高精度测量时建议先进行相机标定将像素坐标转换为实际物理尺寸以获得更准确的测量结果。2. 点到直线的距离计算在实际检测中我们经常需要评估某个特征点相对于基准线的位置偏差这时就需要用到distance_pl算子。典型的应用场景包括检测零件边缘是否平行于基准线评估产品上某点相对于参考线的偏移量判断装配件是否安装到位distance_pl算子的语法结构为distance_pl(Row, Column, Row1, Column1, Row2, Column2, Distance)参数说明Row, Column待测点的坐标Row1, Column1和Row2, Column2定义直线的两个点Distance点到直线的距离下面是一个检测零件边缘平行度的实际案例* 获取零件边缘点 edges_sub_pix(Image, Edges, canny, 1, 20, 40) * 拟合边缘直线 fit_line_contour_xld(Edges, tukey, -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist) * 定义基准线理想位置 BaseLineRow1 : 100 BaseLineCol1 : 50 BaseLineRow2 : 100 BaseLineCol2 : 400 * 计算边缘中点相对于基准线的距离 EdgeMidRow : (RowBegin RowEnd)/2 EdgeMidCol : (ColBegin ColEnd)/2 distance_pl(EdgeMidRow, EdgeMidCol, BaseLineRow1, BaseLineCol1, BaseLineRow2, BaseLineCol2, ParallelDeviation)关键点解析点到直线的距离有正负之分表示点在直线的哪一侧对于平行度检测通常需要计算多个点的距离并统计分析在精度要求高的场合建议使用亚像素边缘检测提高测量精度3. 点到区域的距离分析当我们需要评估一个点与某个区域的关系时distance_pr算子就派上用场了。这个算子不仅返回点到区域的最短距离还能给出最长距离适用于以下场景检测零件上的特征点是否在允许区域内评估产品标识相对于边界的距离判断装配件上的关键点是否在安全范围内distance_pr的调用方式如下distance_pr(Region, Row, Column, DistanceMin, DistanceMax)参数说明Region输入区域Row, Column待测点坐标DistanceMin点到区域的最短距离DistanceMax点到区域的最长距离当点在区域内时为0实际应用示例* 定义安全区域和检测点 read_image(Image, assembly) threshold(Image, SafeRegion, 100, 255) connection(SafeRegion, ConnectedRegions) select_shape(ConnectedRegions, MainArea, area, and, 50000, 1000000) * 获取需要检测的螺丝位置 threshold(Image, Screws, 200, 255) connection(Screws, ConnectedScrews) select_shape(ConnectedScrews, ScrewPoints, area, and, 50, 200) area_center(ScrewPoints, Area, ScrewRow, ScrewCol) * 检查每个螺丝是否在安全区域内 for i : 0 to |ScrewRow|-1 by 1 distance_pr(MainArea, ScrewRow[i], ScrewCol[i], DistMin, DistMax) if (DistMax 0) * 螺丝超出安全区域 dev_set_color(red) gen_circle(Circle, ScrewRow[i], ScrewCol[i], 10) dev_display(Circle) endif endfor常见问题与解决方案问题现象可能原因解决方案DistanceMin异常大点在区域内部检查DistanceMax是否为0距离值不稳定区域边界不清晰先对区域进行平滑处理测量结果偏差大未进行相机标定添加像素到实际尺寸的转换4. 线与区域的距离测量在工业检测中经常需要评估某条线如产品边缘与参考区域的关系这时distance_lr算子就非常有用。典型应用包括检测产品边缘与内部结构的距离评估印刷电路板走线与禁止区域的距离判断密封条与边框的贴合程度distance_lr算子的语法如下distance_lr(Region, Row1, Column1, Row2, Column2, DistanceMin, DistanceMax)参数说明Region输入区域Row1, Column1和Row2, Column2定义直线的两个端点DistanceMin直线到区域的最短距离DistanceMax直线到区域的最长距离当直线穿过区域时为0下面是一个检测产品边缘与内部结构距离的案例* 获取产品区域和内部结构 read_image(Image, electronic_component) threshold(Image, Component, 50, 200) connection(Component, ConnectedRegions) select_shape(ConnectedRegions, Body, area, and, 10000, 100000) * 获取边缘直线 edges_sub_pix(Image, Edges, canny, 1, 20, 40) fit_line_contour_xld(Edges, tukey, -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist) * 计算边缘线与内部结构的安全距离 distance_lr(Body, RowBegin, ColBegin, RowEnd, ColEnd, MinDist, MaxDist) * 可视化结果 if (MinDist 2.0) // 安全阈值为2mm dev_set_color(red) disp_line(WindowHandle, RowBegin, ColBegin, RowEnd, ColEnd) disp_message(WindowHandle, 安全距离不足: MinDist$.2f, window, 10, 10, red, true) endif性能优化技巧对于大尺寸图像可以先对区域进行简化处理如shape_trans如果只需要判断是否相交可以先用intersection算子快速判断对于重复性检测可以预先计算区域的凸包或最小外接矩形来加速5. 线与线之间的距离测量在机械装配检测中经常需要评估两条线如导轨、边缘之间的距离distance_ss算子专门用于这种场景。主要应用包括检测平行线间的距离均匀性评估接缝宽度的一致性判断机械部件间的装配间隙distance_ss算子的调用方式为distance_ss(RowA1, ColumnA1, RowA2, ColumnA2, RowB1, ColumnB1, RowB2, ColumnB2, DistanceMin, DistanceMax)参数说明前四个参数定义第一条线段中间四个参数定义第二条线段DistanceMin两线段间的最短距离DistanceMax两线段间的最长距离装配间隙检测示例* 获取两条装配边缘 read_image(Image, assembly_gap) edges_sub_pix(Image, Edges, canny, 1, 20, 40) * 分割并选择两条主要边缘 segment_contours_xld(Edges, ContoursSplit, lines_circles, 5, 4, 2) select_shape_xld(ContoursSplit, Edge1, contlength, and, 100, 99999) select_shape_xld(ContoursSplit, Edge2, contlength, and, 100, 99999) * 拟合两条边缘直线 fit_line_contour_xld(Edge1, tukey, -1, 0, 5, 2, Row1, Col1, Row2, Col2, Nr1, Nc1, Dist1) fit_line_contour_xld(Edge2, tukey, -1, 0, 5, 2, Row3, Col3, Row4, Col4, Nr2, Nc2, Dist2) * 计算两条边缘线间的距离 distance_ss(Row1, Col1, Row2, Col2, Row3, Col3, Row4, Col4, GapMin, GapMax) * 在多处采样测量间隙 NumSamples : 10 for i : 0 to NumSamples-1 by 1 Ratio : i/(NumSamples-1) SampleRow1 : Row1 (Row2-Row1)*Ratio SampleCol1 : Col1 (Col2-Col1)*Ratio SampleRow2 : Row3 (Row4-Row3)*Ratio SampleCol2 : Col3 (Col4-Col3)*Ratio distance_pp(SampleRow1, SampleCol1, SampleRow2, SampleCol2, Gap) * 记录和分析间隙数据 endfor高级应用技巧对于曲线间的距离测量可以先分割为多段线段再分别计算结合tuple_mean和tuple_deviation可以统计分析距离的一致性在动态检测中可以使用create_shape_model先建立参考模型再实时比较在实际项目中我发现最常遇到的问题是对齐坐标系的问题。特别是在测量距离时如果参考坐标系不一致很容易得到错误的结果。因此在进行任何几何测量前务必确认所有元素都在同一个坐标系下必要时可以使用affine_trans_point等算子进行坐标转换。