Halcon圆形查找从原理到实战的完整指南
2026/9/17 16:23:32 网站建设 项目流程

做机器视觉项目的人,十个里有八个都绕不过“halcon 查找圆形”这道坎。定位螺丝孔、检测药瓶瓶口、测量轴承外圈、找芯片上的焊盘点,说白了都是在跟圆打交道。Halcon在这块的优势不用我多吹,工业界用了这么多年,稳定性和精度都是被验证过的。这篇东西我就拿实际项目里的经验,把圆形查找从原理到算子选型、从代码到调试排错,完完整整捋一遍。不管你是刚接触Halcon的新手,还是已经在用但总被边缘、阈值折腾得头疼的工程师,这篇文章应该都能给你些实在的东西。

1. 从需求到方案:圆形查找的两种典型路径

1.1 先想清楚你要找什么样的圆

很多人拿到图就急着调算子,这是最容易翻车的做法。圆形查找这件事,第一步不是写代码,而是把需求问清楚:你要找的是完整的圆还是圆弧?圆的亮度跟背景相比是亮的还是暗的?现场光照稳不稳定?精度要求是像素级还是亚像素级?这几个问题直接决定你后面选哪条技术路线。

举个例子,如果是一个完整的、边界清晰的圆形零件,用边缘提取加圆拟合的经典流程就够了;但如果圆的边缘有一部分被遮挡,或者你只需要测量某个圆弧的半径,那就得考虑基于轮廓的拟合方式;再如果现场有很多个圆,还要区分大小、筛选位置,那通常要配合区域处理或者模板匹配来做。

1.2 两条主流技术路线怎么选

Halcon里查找圆形的手段,归纳下来无非三类:

  • 传统图像处理路线:预处理 + 亚像素边缘提取(edges_sub_pix)+ 圆拟合(fit_circle_contour_xld)。灵活度高,适合各种复杂情况,但对参数调试经验有要求。
  • 测量模型路线:用metrology测量模型(create_metrology_model + add_metrology_object_circle_measure)。Halcon把边缘提取、拟合、输出结果封装成了一套流程,内部细节可控性强,适合测量精度要求高的场景。
  • 模板匹配路线:先创建形状模板(create_shape_model),再在图像里找模板。适合圆的形状特征明显、目标在图像里相对完整的情况,能找到圆心和角度,但输出半径的精度不算它的强项。

直接说结论:做测量类项目,优先考虑metrology模型;做定位抓取类项目,模板匹配更稳;做复杂的异形圆检测或者圆弧拟合,用边缘提取 + 拟合这条老路线最灵活。后面我会结合案例把前两条路线的代码写清楚,因为这两条是实际项目里最常用的。

2. 核心算子拆解:从边缘提取到圆拟合的完整链路

2.1 为什么图像预处理这一步不能跳过

很多新手喜欢拿到图直接edges_sub_pix,结果边缘出来一堆毛刺,拟合出的圆半径忽大忽小,这时候才想起预处理的重要性。Halcon里的预处理核心目标就两个:降噪和增强对比度。

降噪最常用的是中值滤波(median_image)和高斯滤波(smooth_image)。中值滤波对椒盐噪声特别有效,而且能比较好地保留边缘的锐度;高斯滤波平滑噪声的同时,也会让边缘变钝,所以用在圆形查找上,我通常优先选中值滤波,或者用很小的高斯核(3x3、5x5)。

增强对比度这块,常用的是灰度值拉伸算子。比如图像偏暗、对比度低的时候,可以用scale_image_max直接把灰度范围拉伸到0到255,会让边缘明显清晰很多。Halcon里关于灰度值拉伸的算子有好几个,像scale_image、scale_image_max,实际项目里先跑一下scale_image_max看效果,如果还不行,再用灰度直方图均衡化(equ_histo_image)来处理。

注意:预处理不是越狠越好。我见过有人把图反复滤波,结果边缘被磨平了,亚像素精度反而下降。原则是“够用就行”,只要能稳定提取边缘,处理步骤越少越好。

2.2 亚像素边缘提取:edges_sub_pix 到底做了什么

edges_sub_pix是Halcon里最经典的亚像素边缘提取算子,它基于Canny边缘检测算法,但输出的是亚像素精度的轮廓(XLD contour)。它的核心逻辑分三步:高斯滤波平滑、计算梯度幅值和方向、非极大值抑制加双阈值滞后连接。

这里有个关键概念:亚像素精度。普通像素级边缘,精度只能到1个像素;亚像素边缘通过灰度插值,能把边缘定位精度做到0.1到0.5个像素。在工业测量场景,一个像素对应的物理尺寸可能只有0.01毫米,0.5像素的误差就是5微米,这对精密检测来说就是天壤之别。

edges_sub_pix的参数里,最影响结果的是Sigma(高斯平滑系数)和阈值(Low、High)。Sigma越大,边缘越平滑但定位精度越低;阈值高低直接影响边缘的连续性。实际调试时,我习惯先把Sigma设到1左右,Low和High分别设成10和30,然后看效果慢慢调。如果边缘出现大量断裂,就把High往下降;如果边缘粗糙、有毛刺,就适当加大Sigma。

2.3 圆拟合:fit_circle_contour_xld 的数学原理与参数选择

拿到亚像素边缘轮廓之后,第二步就是拟合成圆。fit_circle_contour_xld支持多种拟合算法,最常用的是“algebraic”和“geometric”。Geometric拟合基于最小二乘原理,使轮廓上所有点到拟合圆的几何距离平方和最小,精度最高,但计算量稍大;Algebraic拟合算得快,但精度略逊。

这里必须提一个非常关键的参数:ClippingFactor。这个参数的本质是离群点剔除。实际图像里,边缘轮廓上难免有一些噪声点或者不属于圆边界的干扰点,如果不剔除,拟合出来的圆会被这些点带偏。ClippingFactor默认值是2.0,表示剔除距离超过中值误差2倍标准差的点。如果你发现拟合的圆明显偏离了实际边缘,重点检查这个参数的设置。

另外一个容易被忽略的点是MaxNumPoints参数。当轮廓点数量特别多时,比如一万个点,参与拟合的计算量会很大。我一般会限制参与拟合的点的最大数目,比如设成1000,既保证精度又加快速度。

2.4 metrology测量模型:为什么推荐用于高精度测量

metrology模型的本质,是把“在圆周围放置测量卡尺、提取边缘点、拟合圆、输出结果”这个流程封装起来。它的核心优势有两个:一是测量区域可控,二是参数调节直观。

具体来说,add_metrology_object_circle_measure会让你指定初始圆心和半径,然后系统会在圆周方向等间距生成多个测量卡尺(measure),每个卡尺沿着法线方向搜索边缘点,最后把这些边缘点拟合成精确的圆。测量卡尺的长度和宽度由MeasureLength1和MeasureLength2控制,卡尺数量由NumMeasures控制,边缘极性由MeasureSelect控制。

用metrology模型做圆形查找,最大的好处是抗干扰能力强。因为每个卡尺只在局部小范围内搜索边缘,周围的干扰物不会影响整体拟合。而且它输出的是测量结果对象,你可以用get_metrology_object_measures拿到每个卡尺提取到的边缘点,可视化检查哪些点被算法接受、哪些被丢弃,调试起来非常直观。这个特性在工业项目里特别实用,因为客户永远会拿各种奇形怪状的样品来考验你的算法。

3. 实战案例:用Halcon查找圆形并输出圆心半径

3.1 方案一:边缘提取加圆拟合法(适合灵活场景)

我直接给一段实际跑通的HDevelop代码,场景是检测一张图里的轴承外圈圆形,并输出圆心坐标和半径。

* 读取图像并转为灰度 read_image (Image, 'bearing.png') rgb1_to_gray (Image, GrayImage) * 预处理:中值滤波去噪 + 灰度拉伸增强对比度 median_image (GrayImage, ImageMedian, 'circle', 3, 'mirrored') scale_image_max (ImageMedian, ImageScaled) * 提取亚像素边缘 edges_sub_pix (ImageScaled, Edges, 'canny', 1.5, 20, 40) * 分割边缘轮廓,挑出圆弧段 segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 5, 4, 2) * 筛选轮廓:只保留接近圆形的轮廓 select_shape_xld (ContoursSplit, SelectedContours, 'circularity', 'and', 0.8, 1.0) * 拟合成圆,输出圆心和半径 fit_circle_contour_xld (SelectedContours, 'geometric', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)

这里重点解释几个细节:

  • segment_contours_xld的第三个参数我用的是lines_circles,意思是把轮廓分段成直线和圆弧。这样即使图像里还有其他干扰轮廓,也能先把圆弧段分离出来。
  • select_shape_xld的circularity是轮廓的圆度,取值范围0到1,1表示完美圆形。我设的0.8,意思是只保留圆度超过0.8的轮廓。按照实际图像调整这个值,能够滤掉大部分非圆的干扰物。
  • fit_circle_contour_xld里,MaxNumPoints填-1表示使用全部点;ClippingEndPoints填0表示不使用端点裁剪;Iterations填3,表示迭代3次剔除离群点;ClippingFactor填2,是离群点剔除的强度。

跑完这个流程之后,Row、Column和Radius就分别是拟合圆的圆心行坐标、列坐标和半径,单位是像素。后面如果要转换成物理单位,就得做标定。

3.2 方案二:metrology测量模型(适合批量高精度检测)

方案一虽然灵活,但如果现场的圆比较多,或者每个圆的边缘附近有干扰,用metrology模型会更省心。下面是一段用metrology模型测量螺栓头部圆形的代码。

* 读取图像 read_image (Image, 'bolt_head.png') rgb1_to_gray (Image, GrayImage) * 创建测量模型 create_metrology_model (MetrologyHandle) * 设置图像尺寸 get_image_size (GrayImage, Width, Height) set_metrology_model_image_size (MetrologyHandle, Width, Height) * 假设粗定位得到的圆心在(Column0, Row0),半径大约Radius0 * 实际项目里这两个值可以通过模板匹配或者用户交互得到 Column0 := 320 Row0 := 240 Radius0 := 80 * 添加圆形测量目标 add_metrology_object_circle_measure (MetrologyHandle, Row0, Column0, Radius0, 20, 15, 1, 30, ['measure_transition'], ['negative'], MetrologyCircleIndices) * 设置参数:卡尺数量、测量方向、边缘极性 set_metrology_object_param (MetrologyHandle, MetrologyCircleIndices, 'num_measures', 60) set_metrology_object_param (MetrologyHandle, MetrologyCircleIndices, 'measure_select', 'first') set_metrology_object_param (MetrologyHandle, MetrologyCircleIndices, 'min_score', 0.6) * 执行测量 apply_metrology_model (MetrologyHandle, GrayImage) * 获取测量结果 get_metrology_object_result (MetrologyHandle, MetrologyCircleIndices, 'result_type', 'all_param', Parameter) * 输出圆心和半径 MeasuredRow := Parameter[0] MeasuredCol := Parameter[1] MeasuredRadius := Parameter[2] * 获取每个卡尺实际提取到的边缘点,用于调试 get_metrology_object_measures (MetrologyHandle, MetrologyCircleIndices, 'all', RowMeasures, ColumnMeasures, MeasureCrossRegions) * 清理测量模型 clear_metrology_model (MetrologyHandle)

这段代码里最需要注意的是add_metrology_object_circle_measure那一行的参数。它的Signature基本是这样的:圆心的初始位置、初始半径、卡尺长度(沿径向的总长度)、卡尺宽度、边缘极性、测量阈值。这里我传的卡尺长度是20个像素、宽度15个像素、阈值30。卡尺长度需要根据你预估的半径误差来定,误差越大,卡尺就要越长,否则边缘点会搜不到。

实际项目里,初始圆心和半径往往不是硬编码的,而是通过模板匹配或者上一帧的结果来动态传入。

3.3 参数选择与计算过程:一个真实调参案例

拿一个检测药瓶瓶口圆的案例来讲。图像分辨率是1280x960,瓶口实际直径是24毫米,在图像里约占180个像素,那么一个像素对应的物理尺寸就是24/180,约0.133毫米。

我先用模板匹配粗定位瓶口圆心,粗定位误差在5像素以内。预估半径是90像素,那么add_metrology_object_circle_measure里的卡尺长度至少要大于粗定位误差,我设为15像素,半径容差就留足了余量。卡尺数量设为60,也就是每隔6度一个卡尺,能覆盖整个圆周。边缘极性设置成negative,因为瓶口在图像里是暗色背景上的亮圆环,过渡方向是从亮到暗。

跑完apply_metrology_model之后,测量出的半径是89.8像素,折合物理尺寸是11.97毫米,和实际直径24毫米的一半很接近。再通过标定板做完整标定,把像素坐标换成物理坐标,最终的直径测量结果稳定在24.013毫米,重复性精度好于0.01毫米。这个精度水平对药瓶检漏检伤的应用来说,完全够用了。

3.4 在C#或Qt工程里怎么调用Halcon

热词里经常看到“qt怎么调用halcon”、“c#直接调用halcon”,这确实是工程落地的关键环节。Halcon提供了HDevEngine,可以让你把HDevelop脚本封装成独立的.hdev文件,然后在C#或C++里通过引擎调用。

在C#里调用的方式大概是:先用HDevEngine加载.hdev脚本,然后设置输入图像变量,执行脚本,最后取出输出结果。在Qt(C++)里也是类似的流程,核心类就是HDevEngine、HDevProgram、HDevProcedure。这套方式的好处是算法逻辑都留在HDevelop里调试,写好之后C#和C++只负责调接口,算法和界面彻底解耦。

另外一点,如果项目里已经用了OpenCV,想同时用Halcon,两者之间传图像就涉及图像格式转换。Halcon的HImage和OpenCV的Mat可以通过内存拷贝的方式互转,核心是灰度图像的通道数、位数、步长要对应上。我自己在C#项目里就是这么干的:OpenCV负责读流和预处理,Halcon负责高精度测量,各干各擅长的。

4. 常见问题与排查技巧实录

4.1 圆的边缘不闭合、有遮挡怎么办

现实图像里,圆的边缘经常不完整。比如工件上有字符、有反光、有夹爪遮挡,导致边缘轮廓断裂成好几段。碰到这种情况,第一反应不应该是提高阈值强行连边,而是改变思路:不需要完整的圆轮廓也能拟合出圆。

解决手段有两个。一个是用segment_contours_xld把轮廓分解成圆弧段,然后只拿长度足够的一段或几段圆弧来拟合。另一个是用metrology模型,因为它天然只依赖局部测量卡尺,某个卡尺区域被遮挡,影响的只是被遮挡的那几个测量点,其余卡尺仍然能正常工作,拟合结果依然可靠。这是metrology模型在抗遮挡上的核心优势,实际项目中尤其好用。

4.2 光照变化导致边缘提取不稳定

现场光照波动是视觉项目里最常见的噩梦。早上下午光线不一样,产品的批次不同颜色深浅不一样,都会让边缘提取失效。

解决办法有两个层面。算法层面:预处理阶段尽量用灰度拉伸增强对比度,把边缘强度统一到相近水平;参数层面:edges_sub_pix的双阈值不要卡太死,留出波动余量。更稳妥的办法是在现场打一个相对均匀的光源,比如同轴光或者环形光,让相机视野内的亮度稳定下来。我做过一个项目,加了光源之后,同样的算法从白天到黑夜、从晴天到雨天都没再出过问题。视觉项目里,七分靠打光,三分靠算法,这句话真不是白说的。

4.3 多个圆同时出现怎么筛选目标

一张图里十几个圆的情况也很常见,比如电池盖板上的多个定位孔。这时候需要做的是先分割出候选圆形区域,再根据大小、位置、灰度信息做筛选。

我常用的流程是:先用threshold或者Blob分析把亮圆或暗圆区域提取出来,然后通过select_shape筛选出面积、圆度符合要求的区域,再对每个区域单独做边缘提取和圆拟合。筛选条件不局限在圆度、面积,还可以加灰度均值、区域位置范围,多条件组合起来,基本能把干扰排除干净。

4.4 像素坐标怎么转换成物理坐标

这是项目交付时绕不开的一步。Halcon里做像素到物理单位的转换,正规做法是使用标定板(如Halcon自带的calibration plate)标定相机,得到相机内参和外参,然后通过image_points_to_world_plane将像素坐标映射到世界坐标平面。

如果项目精度要求不高,也可以用简单的比例法:已知某个标准工件的实际尺寸,在图像里量出对应的像素距离,算出每个像素代表的物理长度。但这个方法忽略了镜头畸变和透视误差,只适合粗糙测量,精密测量还是要老老实实做标定。Halcon里标定的详细流程,建议直接看官方文档里的Calibration示例程序,照着跑一遍就能上手。

为了节省大家排查问题的时间,我把常见的几个问题和调试思路整理成了表格:

现象常见原因排查方向
拟合圆明显偏离实际边缘有离群点干扰,ClippingFactor太大或太小把拟合轮廓和边缘点可视化,检查离群点分布;调整Iterations和ClippingFactor
边缘断裂严重,圆弧不连续阈值设得太高,或者Sigma过大导致边缘被磨平降低阈值High或Low,适当减小Sigma
测到的半径忽大忽小边缘定位精度不够,可能有噪声检查光照是否稳定,预处理降噪是否到位,卡尺数量是否足够
圆周边有干扰,拟合结果被带偏metrology卡尺覆盖范围太大,把干扰边缘也收进来了缩短横向卡尺长度(卡尺长度),或者增加纵向卡尺数量(卡尺宽度),收紧测量范围
图像偏暗导致边缘提取困难阈值和灰度拉伸未适配低亮度图先用scale_image_max增强对比度,再调节阈值
多目标检测时有漏检筛选条件太严格或者边缘提取参数不合适把中间结果显示出来,逐步骤检查分割结果和筛选结果

5. 工具选型与扩展方向:什么时候用Halcon,什么时候用别的

5.1 Halcon深度学习工具能做圆形查找吗

近两年Halcon的深度学习模块越来越受关注,很多人会问:圆形查找是不是也可以用深度学习来做?答案是可以,但要有取舍。Halcon的深度学习工具可以训练目标检测模型,比如用矩形框标注出圆形目标的位置,模型学会之后能直接输出圆心的外接框中心和尺寸。这种方式对遮挡、形变、背景复杂的场景鲁棒性更好,但它的输出精度是像素级的,达不到测量场景的亚像素要求。

所以我的建议是二者结合:要求高精度测量时,用深度学习先粗定位出圆形目标的大致位置和半径,然后把结果传给metrology模型做精确测量。两个阶段一前一后,既解决了复杂背景下的定位问题,又保证了最终测量精度。这种“深度粗定位 + 传统精测量”的组合,现在正逐渐成为工业视觉项目的主流方案,特别是针对之前用传统算法怎么调都调不过来的场景。

5.2 和OpenCV的HoughCircles相比怎么选

OpenCV里找圆最常用的是HoughCircles,简单粗暴,代码量少,很多初学者都是从它入门的。但它的问题在于参数多、调参玄学,尤其是累加器阈值和最小距离这两个参数,换一张光照不同的图可能就得重新调一遍。而且HoughCircles输出的圆心和半径是像素级的,精度做不到亚像素。

Halcon的优势在于三点:一是亚像素精度,这是工业测量最核心的差异;二是参数体系完整,预处理、边缘提取、拟合每一步都暴露给你,调试空间大;三是测量模型封装得好,抗干扰能力强。价格当然也差很多,OpenCV免费开源,Halcon商业授权费用不低。所以小成本项目或者原型验证阶段,OpenCV够用的话就先上OpenCV;真到了要做高精度工业检测、要稳定交付给客户的时候,用Halcon省心太多了。

5.3 什么样的项目适合用圆形查找

圆形查找的应用比想象中广得多。3C行业里,手机摄像头模组的镜片定位、耳机孔的圆心测量;汽车行业里,轮毂螺栓孔的位置度检测、刹车盘的圆度测量;医药行业里,药瓶瓶口的圆度缺陷检测、胶囊的圆度分拣;新能源行业里,锂电池极片的圆形极耳定位、电池盖板焊接圆度检测。这还只是我接触过的领域,实际项目只会更多。

判断一个项目适不适合用圆形查找,核心是看目标在图像里是否呈现圆形边缘特征。只要满足这个前提,都能用上面讲的方法建模。与其担心这个方法有没有局限性,不如先跑一个demo,用几张现场图验证一下边缘提取的稳定性,再决定怎么深入。Halcon的优势就在于demo阶段出效果快,往往一天时间就能评估出方案的可行性。

说在最后

回头看看,其实圆形查找的整套流程并不复杂:预处理让边缘清晰,边缘提取拿到亚像素轮廓,拟合输出圆心半径,metrology模型把控高精度场景。真正拉开差距的,是对参数背后原理的理解,以及现场的调试经验。

我个人在实际调试中还有一个特别想说的小技巧:不要盯着控制台看数字,一定要把中间过程可视化出来。把提取到的轮廓、拟合的圆、metrology的卡尺和边缘点都叠加显示在原图上,一看便知道问题出在哪个环节。很多时候算法的bug不是逻辑烧脑,而是你压根没看到它到底在图像上看到了什么。调试Halcon,视觉反馈比任何文档都管用。这是我在无数个项目里踩出来的体会,分享给看到这里的你。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询