尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

HALCON 3D点云球体拟合实战:从预处理到参数评估全流程

HALCON 3D点云球体拟合实战:从预处理到参数评估全流程 刚接手一个新项目客户要在线测量轴承滚珠的直径和球度原来一直靠人工抽检加千分尺速度跟不上数据也零散。我第一反应是上2D视觉做边缘拟合但试了几轮发现反光、遮挡、姿态变化都很难搞。后来换成halcon3D点云方案用fit_primitives_object_model_3d把点云拟合成球体问题一下清爽了不用管姿态不用高精度机械定位只要点云质量还行球心坐标和半径直接出来再算个均方误差球度也就有了。这篇就把halcon3D点云拟合球体的完整思路写出来内容包括点云怎么读入、怎么预处理、拟合算子怎么调、结果怎么验证最后再谈几个现场踩过的坑。适合正在做3D视觉测量、想用HALCON直接处理点云的工程师参考也适合刚接触3D点云处理、想知道拟合球体到底怎么落地的新手。1. 球体拟合需求的第一现场不只有滚珠测量1.1 哪些工件适合用点云拟合球体来测很多人一听拟合球体第一反应就是测钢珠。实际上这类需求在产线上远不止这一种。我做过和见过的场景大概有这些滚动体尺寸测量轴承滚珠、陶瓷球、研磨介质需要直径精度到微米级甚至还要测批内一致性。球面零件轮廓验收球阀阀芯、人工关节球头、球面轴承外圈这类工件球面只是其中一个关键面需要拟合球面来反推球心位置再配合其他尺寸公差。球形容器或腔体的容积估算罐体、球坯、密封球壳点云拟合球体后直接算半径和中心再配合容积公式估算容量。复杂零部件姿态求取有些工件的定位基准是一个球面比如汽车转向球销、机器人关节球需要通过球心坐标来确定零件的空间姿态方便后续抓取或装配。科研和逆向场景比如地质岩芯球度评估、材料科学里的颗粒球度分析同样会用到球拟合。这些场景共同点是你手上拿到的不是整齐的CAD模型而是一堆三维坐标点点云的形状大概是个球但又不完全是球你需要用数学方法把它规整成一个标准球并量化偏离程度。1.2 为什么2D视觉在球形工件面前容易翻车我以前在不少项目里习惯优先用2D视觉因为快、部署成熟、算法库丰富。但到了球形工件2D有几个绕不过去的坎边缘投影不等于球面轮廓。球形工件在不同姿态下2D相机拍到的只是球面在某个方向上的投影直径和球心的换算依赖姿态先验姿态稍微偏一点测量误差就放大了。反光干扰严重。金属球面、抛光球面在打光下经常出现高光斑块边缘提取很容易把高光边沿误判成工件轮廓。遮挡导致特征缺失。多颗球靠在一起时2D图像里球与球互相遮挡只能测到露出来的部分边缘拟合必然失真。3D点云就没有这些问题它记录的是空间坐标球心拟合天然不受姿态影响遮挡问题也可以通过视角规划来缓解。当然3D方案也有自己的难点主要是点云质量、预处理、算法参数这几块下面逐步说。2. 先把点云收拾干净读入、裁切、去噪一个都不能少2.1 HALCON里点云是怎么组织的在HALCON里点云不是简单的坐标数组它被封装成3D对象模型ObjectModel3D。这个模型里除了点坐标还可以包含点法向量、颜色、灰度、三角网格等信息。平时我们接触比较多的两个入口read_object_model_3d直接从文件读入支持ply、om3、dxf、stl等格式其中ply最常用激光轮廓仪、结构光相机基本都能导出ply格式的点云。相机标定和立体匹配生成的视差图通过xyz_attrib_to_object_model_3d把X、Y、Z三通道图转成ObjectModel3D这是摄影测量类3D相机常用的路径。拿到ObjectModel3D之后如果不确定点云长什么样先用visualize_object_model_3d打开窗口看一眼这一步能避免后面一堆问题。我见过太多人拿到点云直接上拟合算子结果拟合出来一个莫名其妙的结果回头一查原始点云里全是飞点。* 读取点云文件 read_object_model_3d (ball_cloud.ply, mm, [], [], ObjectModel3D, Status) * 可视化检查 visualize_object_model_3d (WindowHandle, ObjectModel3D, [], [], \ [disp_background], [darkgray], [], [], [], PoseOut)2.2 裁切出有效区域别让背景把拟合带偏点云拟合球体最怕的就是混入大量非球面的点。比如一个钢球放在载物台上点云里除了球面还有台面、夹具、周围环境的点。直接拟合的结果会被这些外点严重拉偏尤其是代数拟合算法外点多的情况下球心可能偏出好几毫米。裁切的有效手段是reduce_object_model_3d_by_box直接在三维空间里画一个盒子留下盒子内部的点。选盒子的时候要稍微贴着球面外沿留一点余量但不要把背景框进来。还有一种做法是reduce_object_model_3d_by_sphere用一个大致的球区域去裁适合知道球大概位置和半径范围的情况。* 先用一个三维盒子圈出球体附近区域 read_object_model_3d (ball_cloud.ply, mm, [], [], ObjectModel3D, Status) reduce_object_model_3d_by_box (ObjectModel3D, box, [-25, -25, 20], [25, 25, 70], \ ReducedObjectModel3D)盒子的两个对角点坐标不是乱填的需要结合点云的实际范围来定。一个简单办法是先读点云后用get_object_model_3d_params拿到点云的最小包围盒再根据包围盒往里收缩如果点云场景复杂还可以先用segment_object_model_3d做初步分割找到球面簇再对簇做裁切。2.3 去离群点和降采样让拟合更稳、更快点云里经常会出现孤立的离群点它们离球面很远可能来自多路径反射、环境光干扰或者传感器本身的噪声。对这些外点HALCON里比较常用的是remove_outliers_object_model_3d基于点与邻近点的距离统计来判断。这个算子有两个关键参数一个是邻域半径min_neighbors一个是距离阈值min_dist。实际调参经验是先看点云的平均点间距把邻域半径设为点间距的3到5倍距离阈值设为点间距的10到20倍然后观察输出点云数量外点多的场景逐步收紧。需要说明的是这个算子对稠密点云效果好如果点云本身就稀疏参数需要放得很宽否则容易把有效球面点也删掉。* 去除离群点参数基于点间距估算 remove_outliers_object_model_3d (ReducedObjectModel3D, mla, 6, 12, \ CleanObjectModel3D)降采样方面HALCON提供sample_object_model_3d可以选择保留全部点或者按距离均匀采样。为什么要降采样一个是让计算更快另一个是让拟合算法不受点密度不均的影响。比如一个球靠近相机的部分点特别密背面的点很疏如果不做采样算法会把密集区域的权重放得很大拟合出来的球心会偏向点密的那一侧。* 均匀采样设置最小点间距为0.15mm sample_object_model_3d (CleanObjectModel3D, fast, 0.15, SampledObjectModel3D)3. fit_primitives_object_model_3d 算子拆解球体拟合到底在拟合什么3.1 算子的核心调用方式HALCON从17版开始提供了fit_primitives_object_model_3d这个通用基元拟合算子把平面、球、圆柱、圆锥的拟合统一了接口。拟合球体时代码长这样fit_primitives_object_model_3d (SampledObjectModel3D, primitive, \ [primitive_type, primitive_algo], \ [sphere, algebraic], \ PrimitiveParameter, Score)算子的输出PrimitiveParameter是一个元组球体对应五元组依次是[0]球心X坐标[1]球心Y坐标[2]球心Z坐标[3]球半径[4]拟合均方误差Score保存的是拟合迭代过程的终止分数可以理解成算法收敛状态的一个指标。均方误差那一项在工程上才是最有价值的它直接反映了点云偏离理想球面的程度。3.2 代数拟合 vs. 几何拟合精度和速度的权衡primitive_algo参数有三个可选值algebraic、geometric、ransac。代数拟合通过线性最小二乘直接求解球参数不需要迭代速度极快适合点云质量好、外点少的情况。缺点是它对离群点敏感而且拟合误差定义在代数距离上不是真正点到球面的几何距离所以外点一多结果会明显偏。几何拟合基于Levenberg-Marquardt迭代优化让所有点到拟合球面的几何距离平方和最小。精度高对噪声也更稳健但需要迭代速度慢一些且对初始值有一定依赖。好在HALCON内部会自动算一个代数拟合作为初始值大多数情况下你不需要自己给初值。RANSAC拟合随机采样一致性算法抗外点能力最强。对于外点比例很高、球面仅占点云一部分的场景比如球体周围有一大堆散乱点用ransac最合适。代价是慢而且结果有一定随机性需要设置随机种子保证可复现。实际项目里点云预处理做得干净的话直接用algebraic就够了如果点云里外点难以根除或者你要在拟合的同时找球面点云那就上ransac几何拟合更适合对精度要求高、且点云本身已经比较干净的测量场景。我把三者的对比整理成了表算法速度抗外点能力精度适用场景algebraic快弱中点云干净、批量产线、在线测量geometric中中高有噪声但外点少、计量级测量ransac慢强中高外点多、球面占比低、复杂背景3.3 迭代次数、随机种子与其他隐藏参数除了primitive_type和primitive_algofit_primitives_object_model_3d还能接收一组通用参数常用的有这么几个max_num_iterations几何拟合的最大迭代次数默认值是50大多数场景够用如果点云很密或者初始值偏离较大可以调到100~200。seed/rand_seedRANSAC算法的随机种子务必固定下来不然同一份点云每跑一次结果都会有微小差异这对产线自动判定是非常致命的。min_connectivityRANSAC在判定一个点属于某个球面时要求该点周围有多少个邻近点也属于同一球面用来避免把离散噪声点也当成球面点。max_distRANSAC判定点属于球面的最大距离阈值单位是当前点云单位的倍数。设得太大会把外点也算进来设得太小会漏掉有效点导致拟合失败。这些参数不是每个项目都需要调但当你发现拟合半径明显偏大或者球心乱跳时先回头调它们往往比堆点云精度更见效。4. 从点云到球参数一个完整流程实例4.1 场景设定和完整代码这里用一个模拟场景展示全流程。假设我们的工件是一个半径约12.5mm的陶瓷球放在一个深色橡胶垫上3D相机从斜上方扫描原始点云包含台面、部分夹具和球体。目标是从点云中拟合出球半径并输出球度评估。完整流程如下dev_update_window (off) dev_close_window () dev_open_window (0, 0, 512, 512, black, WindowHandle) set_display_font (WindowHandle, 16, mono, true, false) * 1. 读入点云 read_object_model_3d (ceramic_ball_scene.ply, mm, [], [], ObjectModel3D, Status) if (Status ! ok) stop () endif * 2. 可视化确认 visualize_object_model_3d (WindowHandle, ObjectModel3D, [], [], \ [disp_background], [lightgray], [], [], PoseOut) * 3. 裁切用包围盒只留下工件所在的区域 * 根据点云整体范围调整坐标单位mm reduce_object_model_3d_by_box (ObjectModel3D, box, [-28, -28, 18], [28, 28, 48], \ ReducedObjectModel3D) * 4. 去离群点 remove_outliers_object_model_3d (ReducedObjectModel3D, mla, 4, 10, \ CleanObjectModel3D) * 5. 均匀采样点间距取0.2mm sampled_object_model_3d (CleanObjectModel3D, fast, 0.2, SampledObjectModel3D) * 6. 拟合球体先用几何拟合精度优先 fit_primitives_object_model_3d (SampledObjectModel3D, primitive, \ [primitive_type, primitive_algo], \ [sphere, geometric], \ PrimitiveParameter, Score) * 7. 提取结果 CenterX : PrimitiveParameter[0] CenterY : PrimitiveParameter[1] CenterZ : PrimitiveParameter[2] Radius : PrimitiveParameter[3] MSE : PrimitiveParameter[4]这里第三步的裁切盒参数是根据点云场景定的。如果每次来料的球位置有偏差你不想手动改盒子坐标可以先用get_object_model_3d_params拿到初始点云的包围盒再通过坐标变换把盒子跟着球走。稳定、高效的方案是在相机视场内先定位球心的大致区域比如用一个2D相机先找到球的图像位置再反过来引导3D裁切区域。4.2 各步骤的实际作用和效果每一步都不是走过场我逐条说明为什么需要以及效果如何裁切这一步对结果的影响最大。实验里如果不裁台面直接对全场景点云做拟合代数拟合的半径误差能到3mm以上几何拟合也好不到哪去因为台面的一大堆点会跟球面点抢拟合参数。裁完之后参与拟合的点基本都是球面点了。去离群点remove_outliers_object_model_3d用mla方法和邻域统计来剔除飞点。本例里点云平均点间距约0.35mm设min_neighbors为4、min_dist为10能去掉塑料垫反光造成的一些零散杂点。需要说明的是这一步不要删太狠否则球面边缘的点会被误删让拟合半径偏小。均匀采样陶瓷球离相机近的上半球点云很密下半球因为是斜面扫描点距大。fast策略按0.2mm间距采样后参与拟合的点从几万降到了一两万密度也更均匀拟合出的球心更接近真实几何中心。4.3 从拟合结果推导工程指标拿到PrimitiveParameter之后不能直接就拿去用还要做几步转换和评估。直径D 2 * Radius注意单位是当前点云单位前面读入时已经指定mm所以结果直接就是毫米。球度评估球度可以用点云各点到拟合球面的最大偏差来评估。HALCON里提供distance_object_model_3d或get_object_model_3d_params配合计算点到球面的距离然后求最大值和均方根。均方误差MSE是整体偏离水平最大偏差是局部极值两个都要看。球心坐标空间姿态球心点本身就提供了一个关键空间坐标。做抓取时知道球心就能结合机器人坐标系换算抓取位姿做装配时球心位置可以和另一个零件的基准孔做相对位置判定。下面这段代码把点云各点到拟合球面的距离算出来用于最大偏差评估* 生成拟合球的三角网格模型 gen_sphere_object_model_3d (CenterX, CenterY, CenterZ, Radius, FitSphere) * 计算点云到拟合球面的最小距离 distance_object_model_3d (SampledObjectModel3D, FitSphere, DistanceImage)严格来说distance_object_model_3d计算的是两个3D对象模型之间的最近点距离用来做整体偏差评估是可以的。如果要逐点球面距离更精细的做法是用get_object_model_3d_params把点坐标取出来然后按点到球面距离公式计算。5. 拟合结果怎么看、怎么判定合格5.1 均方误差和最大偏差两个互补的指标经常有人只盯着拟合出来的半径却忽略误差指标。实际上半径可能有微米级波动真正反映拟合质量的是MSE和最大偏差。MSE是点云全部点到拟合球面距离的平方平均值单位是平方毫米。它反映整体贴合度MSE小说明球面整体规整。最大偏差是所有点到拟合球面的距离的绝对最大值反映局部缺陷。比如球面有一处磕碰MSE变化不大但最大偏差会明显抬高。工程判定标准建议这样设先测十几个合格的工件统计它们的MSE和最大偏差分布然后以均值加3倍标准差作为现场判定的阈值。不要拍脑袋定一个数产线上的公差必须来自被测对象的真实统计。5.2 用可视化确认拟合球和点云的贴合程度数值指标再漂亮也要肉眼确认一遍。HALCON里可以把原始点云和拟合球同时显示出来用不同颜色区分观察球面是否贴着点云走。* 刚生成的FitSphere本身就是一个ObjectModel3D可以直接可视化 visualize_object_model_3d (WindowHandle, [ObjectModel3D, FitSphere], [], [], \ [color_0, color_1], [white, green], \ [], [], PoseOut)绿色球面如果和白色点云完全贴合说明拟合结果可信如果有一侧悬空一侧陷入问题通常出在预处理或者裁切区域不对称。这里有个非常实用的技巧把视角转到侧面观察球的赤道线位置是不是和点云边缘对齐很多拟合偏差在这个视角下一眼就能看出来。5.3 多次测量重复性的验证方法产线测量最重要的指标之一是重复性也就是同一个工件反复测结果不能有大波动。验证方法是把工件在相机视野内移动几个位置、旋转几个角度分别作拟合看拟合半径的极差最大值减最小值。如果极差超过你公差要求的一半说明方案还不稳定需要优先检查两个问题点云的裁切区域是否每次都一样。如果每次裁切框进不同数量的背景点半径一致性会受影响。RANSAC或几何拟合的随机种子是否固定。没固定的情况下即使点云完全一样结果也可能有微小差异。我在现场碰到过一种特殊情况工件的球面有一小块高反光区域3D相机在这块区域总是重建失败形成空洞。这种情况下每次测量的空洞位置不同拟合出的球心就会小幅度漂移。解决办法有两个方向一个是改变打光方式减少反光另一个是在预处理时把空洞周围的点也约束进拟合并在后处理里对多次测量做滤波平均。6. 现场实战中的几个关键坑和应对6.1 点云边缘比中心更虚别忽略3D相机扫描球体时边缘区域入射角大反射信号弱点云在球边缘往往有较大的噪声甚至出现局部变形。这就导致一个典型现象拟合出来的球半径比实际偏小因为边缘点的噪声把拟合球面勒紧了。应对办法是给参与拟合的点做权重控制。fit_primitives_object_model_3d支持通过generic参数传入点属性权重比如根据点云的质量置信度设置权重。具体操作是在ObjectModel3D上添加一个名为point_weight的属性。如果不想做这么细一个更简单的处理是裁切时把球边缘区域稍微切掉一点只保留法向朝向相机较好的中间区域参与拟合。但这会损失一部分测量信息需要平衡。6.2 球面的反光和透明材质镜面球体或透明小球是3D视觉的老大难。我之前做陶瓷球相对好一点表面磨砂和轴承钢球高光镜面的对比测试轴承钢球的点云在正对光源的区域经常出现大片空洞拟合时这些空洞导致的点在预处理阶段容易被判定为离群值从而把球面形态破坏。这类球有三个土办法可以救用偏振光源或十字偏振片消除镜面反射让3D相机能重建出完整球面。给球面喷一层显像剂临时把镜面变粗糙面测量完再清理。适合离线抽检不适合在线全检。用多视角拼接把几个角度扫到的球面点云拼起来。HALCON里可以用transform_object_model_3d做点云配准或者直接使用支持多视角重建的3D相机系统。6.3 拟合参数的后处理和产线接入从拟合结果到产线判定中间还有一段路要走。首先是单位换算和坐标系对齐。HALCON拟合出来的球心坐标是在相机坐标系下的如果要和机器人配合需要通过手眼标定矩阵变换到机器人基座坐标系。手眼标定用HALCON的calibrate_hand_eye或calibrate_hand_eye_scara具体标定流程我就不在这篇里展开了。其次是滤波。单帧点云的拟合结果会受噪声影响有小幅抖动产线上一般对连续N帧结果做中值滤波或滑动均值滤波再判定是否合格。N取5到10比较合适太小平滑效果不明显太大响应变慢。最后是触发逻辑。如果工件是在流水线上移动的需要配合编码器或光电传感器触发3D相机采集。HALCON在这类场景里通常跑在带有硬触发的工业相机上采集后马上做点云生成和拟合整个过程控制在几百毫秒内是可以做到的。7. 几句实在话halcon3D的点云拟合球体说难不难算子调通很快但真正用到产线上坑全在点云质量和细节处理上。我个人的体会是不要一上来就优化拟合算法先把点云预处理做扎实。很多时候半径飘忽不定不是拟合算子的问题是点云本身脏、裁切区域不一致、随机种子没固定这些看上去很不起眼的原因。如果你是从PCL或CloudCompare转过来的HALCON的一大优势是算子封装得很干净不需要自己手写最小二乘和RANSAC内部实现也经过了工业级优化。但相应地你更需要理解每个参数背后的物理意义不然出了偏差很难排查。最后分享一个调试小技巧拟合结果异常时把拟合球和原始点云一起可视化然后绕着一圈看。球面嵌入点云内部还是悬浮在外侧偏差方向会直接告诉你问题出在预处理、裁切还是参数设置。这个习惯帮我省下了大量排查时间也希望能帮你少走弯路。
返回列表