BLOB分析在机器视觉里听起来好像是高深算法,其实它干的活特别朴素:在一张图里找出连成一团的像素区域,再按面积、圆度、位置筛一筛,把所需的圆心坐标稳定地算出来。这次分享的是一套基于BLOB分析的多圆定位例程,配合机器视觉运动控制一体机来实现,属于我手头这套应用例程的第三篇。前两篇分别讲了整体框架搭建和单目标识别,这一篇重点聊多圆场景里的实际问题:怎么把多个圆同时找出来,怎么算准圆心,怎么把像素坐标换算成运动机构能用的物理坐标。工业现场里圆形目标太常见了——瓶盖、药片、轴承、晶圆、手机摄像头模组,多到数不过来,所以这套例程的价值就在于把圆形目标的定位做实、做稳。适合两类人看:一是刚入门视觉、想知道BLOB分析到底怎么落地的人,二是已经在做视觉项目但被多目标干扰、光照波动和坐标标定反复折磨过的开发者。
1. 项目概览与需求拆解
1.1 一体机方案到底解决了什么问题
先说说为什么要把这套东西放在一体机上做,而不是传统的“工业相机加工控机加运动控制卡”组合。传统方案里,相机采集完图像要传给上位机,上位机跑完算法再把结果发给运动控制卡,中间多了一道甚至两道网络或总线通讯。对于定位精度要求高、节拍要求快的产线,哪怕多出来几毫秒延迟,都可能造成停机的连锁反应。
一体机的思路是把图像采集、算法处理、运动控制全部塞进同一个控制器里,视觉程序可以直接给伺服或步进发指令。这样定位结果从算出来到执行,中间几乎不需要跨设备传输,延迟压到了最低。尤其在多圆定位这种场景里,视觉算法算完一堆圆心之后往往要立刻换算成X/Y偏移量和旋转角度,紧接着就要驱动机构去补偿,闭环越短越稳。
这套例程里用的就是一体机自带的视觉软件和运动控制接口,视觉部分负责算目标,运动部分负责跟动作。坦白讲,如果你手头只有普通相机加PC,这套思路一样能迁移,只是要把结果通过串口或以太网发给控制器。明白了这个背景,再往下看算法和调试细节就心里有数了。
1.2 多圆定位到底在定位什么
多圆定位并不只是“找到好几个圆”这么简单,实际项目里大致分成三种形态。
第一种是单圆定位的阵列化。比如药板上的药片,或者手机盖板上一排定位圆孔,目标就是把所有圆的圆心都输出,位置用来做阵列组装或缺陷筛查。第二种是几何关系定位,最常见的就是找两个圆,然后用这两个圆心的连线算出目标当前的旋转角,配合一个圆心坐标做一个完整的2D姿态输出。第三种是内圆外圆嵌套的目标,比如轴承内外圈、晶圆上的同心圆标记,这时候需要同时识别内外圆的圆心和半径。
我这次例程覆盖的是前两种的合并场景:视野里同时有多个圆,其中既有关键的中心圆,也有辅助定位圆。通过BLOB分析把所有圆形目标提取出来,再按面积、圆度、相互位置关系区分谁是谁,最后输出一组圆心的像素坐标和角度信息。这个场景在手机模组装配、PCB对准、精密零件摆盘里都属于标准需求,做透一个例子,其他项目照葫芦画瓢就行。
1.3 为什么首选BLOB分析而不是模板匹配
我在前一篇例程里讲过模板匹配的玩法,它确实能找圆,但多圆场景下我基本不会用。原因有几个。模板匹配对光照变化比较敏感,同一个圆在亮一点暗一点的环境下得分会波动,阈值不好定。更麻烦的是,如果视野里出现多个形状相似的圆,模板匹配经常会给出多个相近的匹配结果,加上模板匹配本身有分辨率限制,想亚像素求圆心还得再补边缘拟合的步骤,算力开销也不小。
Hough圆检测也是个常见选项,但它在多圆场景下调试更头疼,累加器参数、圆心间距约束、半径范围都要一顿调,而且速度比BLOB分析慢一个量级。最关键的是,Hough求粗圆心可以,求精细圆心往往还需要二次精定位。
BLOB分析的思路完全不一样。它是先把图像二值化,把所有连成一片的像素区域全提取出来,然后用几何属性去筛选。圆形目标在二值化之后就是一个天然的连通域,面积、圆度、重心这些几何特征本身就是“像不像圆”的直接度量。这和人工肉眼找圆的逻辑高度一致,每个参数都有物理含义,出了问题也知道从哪下手。多圆场景下,BLOB分析可以一次性把所有候选区域全部拿到,再按条件逐层筛,整个过程流水线化,速度、稳定性、可解释性都占优。
2. 核心原理拆解:BLOB分析的关键细节
2.1 BLOB分析的基本链路
BLOB分析的标准链路是:图像预处理、阈值分割、连通域标记、几何特征计算、特征筛选、结果输出。六个环节里每一步都会直接影响后续质量,我一个个说。
预处理主要做两件事:降噪和增强边界。工业相机拍出来的图多少有点传感器噪声,直接做阈值分割容易在目标边缘产生毛刺,所以一般先做一个高斯平滑或中值滤波。高斯平滑适合整体降噪,中值滤波对椒盐噪声更有效,我自己习惯先用3x3中值滤波把离散噪点擦掉,再用5x5高斯平滑磨一下边缘。
阈值分割是整个BLOB分析的灵魂。阈值选得好,后面全是省心;阈值选得烂,后面怎么调特征筛选都费劲。固定的二值化阈值只适合光照极其稳定的场景,稍微有点环境光波动,目标边缘就会缺一块多一块。所以我一般建议用动态阈值或者大津法,让阈值跟随灰度直方图自适应调整。大津法原理不复杂,就是自动找一个灰度值,让目标和背景两类的类间方差最大,实际效果在大多数工业场景里都很能打。
连通域标记是BLOB分析的核心算法,常见的做法是两遍扫描。第一遍扫描给每个像素打临时标签,同时记录标签之间的连通关系;第二遍扫描把等价标签合并,最终每个连通区域获得唯一编号。这一步做完以后,图像里每一团独立的像素区域就都变成了一个独立对象,后续所有几何计算都是针对这些对象逐个进行的。
2.2 几个关键的几何特征和它们的物理含义
BLOB分析背后是一堆几何公式,不需要全背下来,但有几个特征必须理解透彻。
面积最简单,就是区域内像素点的总数。一个圆如果直径是100像素,面积大约7850像素,如果你设的面积范围是500到8000,那这个目标刚好卡在边缘,很容易误伤。所以设面积范围的时候要留足余量,而且我习惯用等效直径来思考,等效直径等于两倍根号下面积除以圆周率,算出来目标大概多少个像素大,再反推面积范围。
圆度是判别圆形目标最重要的指标,计算公式是圆度等于4π乘面积除以周长的平方。正圆的圆度是1,形状越复杂、边缘越不圆润,圆度值越小。一个正方形圆度大约是0.785,一条细长条可能只有0.1。实际项目里筛圆形目标,圆度下限设在0.7到0.9之间比较合理,具体看你的圆形目标边缘质量。记住一点:圆度对边缘毛刺非常敏感,边缘一旦锯齿化,周长变大,圆度就降。所以预处理阶段把边缘处理干净,比后面调圆度阈值更有效。
重心也叫质心,是用图像矩算出来的,一阶矩除以零阶矩就是重心坐标。二值化后的连通域重心对圆的中心位置是一个不错的估计,但如果圆内部有孔洞或者边缘残缺,重心就会偏移。所以高精度定位不能只靠重心,我用重心只做粗定位和排序。
除了这些,有时还会用到外接矩形、最小外接圆、长轴短轴比等特征作为辅助筛选。比如你要找的目标是标准圆,但视野里有一个矩形螺丝和一个小圆,矩形螺丝的宽高比很大,用长宽比就能直接把螺丝排掉,省得后面圆度筛选折腾。
2.3 求圆心坐标:质心法还是圆拟合法
拿到BLOB区域之后,圆心怎么求?这里有三条路可以走,精度和速度各不相同。
第一条是直接取重心。速度快到可以忽略不计,而且对标准圆形目标精度完全够用。很多项目要求定位精度在0.1毫米以上,配合合适的相机分辨率,质心的亚像素级别的稳定性完全扛得住。但如果目标边缘缺损明显,重心就会偏。
第二条是最小二乘圆拟合。做法是先提取BLOB边缘的轮廓点,然后把这些点带入圆的方程,用最小二乘法求解出最优的圆心和半径。这条路对边缘缺损不敏感,只要边缘点数量足够多且分布均匀,拟合出来的圆心位置会比质心稳得多。精度可以做到亚像素级别,是当前工业界主流的精定位方案。
第三条是计算最小外接圆或最大内接圆的圆心。前者偏向轮廓的外侧,后者偏向内部,在同心圆检测里有用,但通用性不如前两者。
我的实践建议是:如果是粗定位或者目标本身质量很好,直接用质心就够;如果对重复精度要求高,或者目标边缘可能有缺陷,那必须上最小二乘圆拟合。在一体机里,两步走的方案也常见:先用质心粗筛出目标,再在目标ROI内提取边缘点做圆拟合,既保证速度又拿精度。
3. 实操过程:从图像采到坐标输出
3.1 成像环境与光源选择
多圆定位的第一个坑往往不在算法,而在成像。BLOB分析对二值化的结果很敏感,二值化质量取决于目标与背景的灰度差,而灰度差靠光源和曝光来保证。
圆形目标分两类成像情况。第一类目标是表面本身有灰度差异的,比如深色橡胶圈放在浅色传送带上,这时候用环形光源或者条形光源正面打光就行,目标与背景天然有对比。第二类是要测轮廓的,比如金属垫圈、透光玻璃片上的圆形标记,这类最好用背光源。背光一打,目标变成黑色剪影,背景变成白色亮场,二值化之后的边缘极其锐利,BLOB提取的周长和圆度都更准确。我在例程里用的是背光方案,实测圆度在0.94左右,比正面光整整高出一截。
曝光时间也有讲究。原则是目标边缘的灰度过渡越陡越好,最好控制在1到2个像素以内。如果曝光太长,亮背景会溢出并往暗区域渗,边缘一圈都会被吃掉;曝光太短,灰度差不足,内部会出现孔洞。我调试时会盯住直方图,让目标灰度峰值和背景灰度峰值分得足够开。
3.2 参数设置一步步推导
我把这套例程里的一版典型参数拿出来做一个完整推演,方便你理解每个数字是怎么来的。
用的是500万像素黑白相机,视野大约40毫米乘30毫米,目标是一个直径5毫米左右的圆形工件,视野里同一时刻会出现三到五个这样的圆,还混着两个矩形螺丝。
第一步,图像预处理。中值滤波核选3x3,目的是去掉离散噪点;接着高斯平滑核选5x5,进一步稳定边缘。
第二步,阈值分割。直接用大津法做全局自适应阈值,没有手工填固定值。为什么敢用全局大津?因为背光环境光强稳定,目标灰度和背景灰度分布都很集中,全局阈值完全够用。如果用正面光且有渐变阴影,就得考虑局部阈值,但运算量更大,所以优先从光源上解决问题。
第三步,BLOB分析参数。等效直径目标大约5毫米,按视野和分辨率换算,大约200像素直径,折算面积大约31400像素平方。我给面积范围设置为12000到50000,把直径大约80到250像素的区域都圈进来。为什么要放宽?因为生产来料尺寸有公差,视野一致性也有波动,收得太紧会把边缘有遮挡的目标误杀。圆度下限设为0.85,因为背光下标准工件的实测圆度在0.91到0.95之间,矩形螺丝圆度只有0.7出头,0.85一刀切下去,螺丝全部滤除,圆工件稳定保留。
这里有个容易忽略的细节:如果工件边缘有小缺口,圆度会明显下降。这时候可以先做一次闭运算,把边缘小缺口补上,圆度就回上来了。不过闭运算也会略微改变区域周长,参数上要观察不能把两个圆磨成一个圆。
第四步,输出重心和拟合圆心。每个BLOB区域同时计算质心和最小二乘拟合圆心,我最终默认输出拟合圆心,质心只用于目标排序和关联。
3.3 坐标标定:从像素跳到物理坐标
BLOB分析算出来的坐标是像素坐标,运动机构不认像素,它认毫米或者脉冲数。中间的桥梁就是标定。
最常用的方法是放射变换标定。简单理解就是找像素坐标系和运动坐标系之间的数学映射关系,至少需要三个点解出六个参数,实际工程为了稳定会用到九个点。操作方式不复杂:让运动机构带着一个标准圆靶或者工件分别走到九个已知位置,每到一个位置就采一次图,记录下当时图像里目标圆心的像素坐标,以及运动机构实际的物理坐标,然后用这些对应点解出变换矩阵。只要机构重复精度没问题,这套标定做下来,视觉输出的坐标精度可以跟机构自身精度对齐。
标定时还要注意旋转和镜像的问题。如果相机安装方向和运动轴方向存在一个夹角,变换矩阵会自动吸收掉这个夹角,但很容易忽略的是图像坐标系的Y轴方向和运动坐标系的Y轴方向是否一致。工业相机的像素坐标系原点一般在左上角,Y轴向下,而运动坐标系Y轴通常向上,如果不处理,补偿方向是反的,机构越走越偏。所以标定完之后一定要做一个方向验证:视觉输出正X偏移,机构朝正X方向走,看到实际位移和预期一致才叫标定完成。
3.4 坐标输出与运动补偿联动
标定完成后,视觉坐标就可以直接送给运动逻辑了。多圆定位联动运动的典型逻辑是:视觉算出当前工件的圆心坐标和基准位置的偏差,把偏差值发给伺服做位置补偿,然后机构执行对位动作。
以两圆定位为例。基准位置有两个圆,标准情况下它们的圆心分别在某物理坐标值上。当前来料位置有偏移,BLOB分析算出当前两个圆心坐标后,先计算第一个圆心的X/Y偏差,再计算两个圆心连线的角度相对基准角度的偏差。X/Y偏差直接补偿到运动轴,角度偏差补偿到旋转轴。三个量同步发出,机构就能把任意摆放的工件纠正到固定姿态上,这个过程通常叫“取放对位”。
一体机在这里的优势体现得很明显,视觉结果算完不用走网络,直接内部变量赋值到运动缓冲,下一拍就能执行补偿。整套流程从采图到运动启动,我在例程里测出大约25毫秒以内,完全满足产线节拍。
4. 常见问题与排查技巧实录
4.1 BLOB断裂和孔洞
现象很典型:一个完整的圆在二值化之后变成了月牙形,甚至碎成好几块,BLOB分析把它们当成几个独立目标,面积筛选直接失败。
原因大多是目标表面反光。金属圆片在打光时产生镜面反射,局部灰度特别高或特别低,阈值分割时把那一块整个切掉了。处理顺序我建议先动成像,再动算法。把光源角度调低,或者换成偏振片消除镜面反射,问题通常直接消失。如果现场不允许动光源,就用形态学闭运算把断裂的区域缝合,核大小从3x3开始试,够用就行,用太大核会把相邻目标合并,得不偿失。BLOB分析里的“填充孔洞”选项也要打开,它会把区域内部的小空洞补上,对提高圆度数值帮助很大。
4.2 多个圆靠太近导致粘连
两个圆间距很近,或者工件表面有脏污把两个圆连在了一起,二值化后变一个BLOB,面积筛选也救不回来。
我的排查步骤是先看二值化图像确认粘连原因。如果是脏污搭桥,调阈值往往能断开;如果两个圆物理上就挨得近,阈值会把中间缝隙也变成白色,这时候可以试试面积筛选先把超大BLOB排除,再做一次基于距离的分割。更实用的办法是做分水岭分割,或者直接改用“基于区域重心聚类”的思路:先不追求把粘连区域分开,而是把它当成一个粗区域,在粗区域内部用边缘检测找圆弧,分段拟合出多个圆心。我的实际经验是,如果产品设计允许,最好在成像时把两个圆的间距尽量拉开,视觉层面怎么补都不如物理层面解决来得稳。
4.3 圆心位置抖动
现象是目标不动,算法输出的圆心总有正负一两个像素的波动。这种情况最常见的原因是曝光或光源不稳导致二值化边缘来回变化,圆拟合的边界点也随之抖动。
对策从两头入手。硬件上把光源电源换成恒流驱动,亮度波动会明显减少;软件上可以做多次采集平均,比如连续采三帧对圆心结果取平均,但这样会牺牲节拍,好在大部分场景帧率足够,三帧平均的耗时可以接受。另一个容易被忽视的点是边缘提取方式,如果用亚像素边缘检测代替整像素边缘点,圆拟合的稳定性会提高不少。整套例程实测下来,把光源稳定性和亚像素边缘做好之后,圆心重复性从正负1.2像素改善到正负0.15像素,效果非常明显。
4.4 标定之后仍然有位置偏差
标定矩阵算对了,但实际补偿时总是有一定角度的残余偏差。这种情况十有八九是标定用的特征点和实际抓取的目标不在同一个Z高度。视觉是二维投影,目标高度变化会导致视差,圆心的图像位置会随着高度偏移。你在标定时如果用的是一片薄靶,实际干活时工件高了5毫米,这个高度差就会转化为测量误差。
解决方式是让标定时的Z轴高度跟实际作业高度尽量一致。如果平时来料高度波动大,就需要做高度方向的补偿模型,或者增加第三个维度做三维视觉。对于多数平面定位场景,把标定高度固定住,基本就够用了。
4.5 现场问题速查表
| 现象 | 直接原因 | 处理方向 |
|---|---|---|
| 圆变成月牙或碎片 | 镜面反光导致局部灰度异常 | 调整光源角度、加偏振片、开闭运算 |
| 多个圆粘连成一个BLOB | 间距过近或脏污搭桥 | 调阈值、分水岭分割、ROI内做边缘拟合 |
| 圆心抖动超过1像素 | 光源波动、边缘非亚像素 | 换恒流光源、亚像素边缘、多帧平均 |
| 标定后仍有角度偏差 | 标定平面与作业平面高度不一致 | 统一Z高度重新标定 |
| 圆度值始终偏低 | 边缘毛刺、内部孔洞 | 中值滤波、闭运算、填充孔洞 |
| 目标照不全 | ROI边界切掉目标 | 扩大ROI,保留安全边界 |
这个表是我日常调试用的排查索引,照着这个方向走,大多数BLOB多圆定位问题都能在半小时内定位到根因。不用死记,调得多了自然形成直觉。
做这套例程最大的体会是:BLOB分析这些算法本身并不玄妙,真正拉开差距的,是对成像原理的理解和对参数的敬畏。每个数字背后都对应着一个物理过程,哪怕只是把阈值从固定值改成自适应,现场稳定性就能上一个台阶。如果你手头正好有类似的圆形定位需求,建议按这个例程完整的流程走一遍,在调试到二值化那一步时多花点时间看看图像效果,你已经成功了一半。