做视觉项目年头多了,会发现一个挺反直觉的事实:很多看起来“高科技”的检测需求,最后落到算法层面,反而是最基础的 Blob 分析在扛大梁。几年前我做一个金属件的外观缺陷检测方案,甲方要求找出表面直径0.3mm以上的异物和刮伤,一开始我迷信各种高端算子,又是频域又是深度学习,结果在打光不稳定、样本量又少的情况下,方案怎么调都不稳定。后来导师提醒了一句:你先用 Blob 把连通域理清楚再说。我这才重新把 VisionPro 里的 Blob 模块从头到尾啃了一遍,项目反而顺利落地了。
这篇东西就是冲着 VisionPro 的 Blob 模块来的。我会按自己实际做项目的顺序来聊:先讲模块背后的底层逻辑和适用边界,再讲图像采集和预处理里容易忽略的三个坑,然后重点拆阈值、极性这些决定生死的参数,接着是属性过滤和结果字段的解读,再给出一套 Blob 与定位、掩膜工具配合的标准打法和三次真实翻车现场的复盘。适合那些刚入门机器视觉、正在调试 CogBlobTool 的新手,也适合做过一两个项目但总觉得 Blob 调参全凭运气的朋友。
1. 从“连通域”说起:Blob模块的底层逻辑与适用边界
1.1 像素世界里的“同一块区域”
Blob 这个词最早来自二进制大对象,但在机器视觉里它指的就是二值图像中彼此连通、属于同一片区域的像素集合。通俗点说,你在图像里看到一块白斑,计算机看到的是一个个灰度值大于阈值的像素,而 Blob 模块的任务就是把这些像素按“邻接关系”聚成一类,然后告诉你这堆像素一共有多少个、面积多大、重心在哪儿、形状有多圆。
这里的关键是“连通”的定义。VisionPro 的 Blob 模块允许你选 4 邻域或 8 邻域:4 邻域认上下左右四个方向,8 邻域把对角线也算进去。现场选哪个,要看目标形态。比如检测细长划痕,如果划痕方向和对角线方向相近,你用 4 邻域可能会把一个连续的划痕断成好几段;反过来,如果噪声点多,8 邻域又容易把相邻的噪声点连成一片假缺陷。所以这个参数没有绝对答案,要拿实际样本去试。
1.2 Blob能干什么,不能干什么
我自己的体会是,Blob 最适合干三类事:计数、测量、定位。计数比如药板上的胶囊数量;测量比如面积和周长;定位比如用大面积滤芯区域的重心作为参考点。除此之外,它还能做形状分类,比如通过圆度区分圆形缺陷和划伤缺陷。
但它真不是万能的。Blob 完全基于灰度分割,所以它对“纹理差异”和“颜色差异”基本无能为力。如果你要区分一个区域是光滑面还是砂纸面,或者要判断基材是淡黄色还是淡蓝色,Blob 帮不上忙,那不是它该干的活。另外,Blob 对图像分辨率很敏感,目标或者缺陷如果连十几个像素都不到,很容易被噪声淹没,或者说和噪声根本分不开。
1.3 为什么要在VisionPro里专门聊Blob
很多人觉得 VisionPro 里算法模块五花八门,Blob 显得有点“土”。但实际工程里它恰恰是使用频率最高的工具之一。原因不复杂:VisionPro 的 CogBlobTool 运算稳定、逻辑清晰、参数可视化程度高,你甚至可以在运行界面直接拖动阈值滑块,实时看到图像里哪些区域被判定为前景。这种交互体验对现场调试太重要了。
而且它的输出字段非常全,面积、重心、角度、外接矩形、孔洞数量都有,下游接脚本或者接其他工具判断都很方便。我可以负责任地说:把 CogBlobTool 吃透,至少能解决一半以上的表面缺陷检测需求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 拍不出好图,参数调得再好也白搭:图像采集与预处理的三个坑
2.1 光照的角度比亮度更重要
在 Blob 项目里翻车的第一原因,十个有八个是打光方案没想清楚就开始调参。我遇到过最典型的场景:某注塑件表面的溢胶是凸起的,来料方向不固定,甲方现场用环形光垂直照明,结果溢胶边缘高光反射,把胶痕照得亮白一片,阈值一拉,溢胶和正常高光区全都变成了前景,Blob 直接糊成一大团。
后来我把环形光换成低角度环形光,让凸起部分产生明显的阴影,溢胶就变成了暗斑,与正常区域一下子拉出了对比度。这里要说句实话:Blob 的成败,在按下快门那一刻就基本定了。你是要抓暗斑还是亮斑,用什么角度把目标特征“凸显”出来,这属于光学方案的活,比调参数重要得多。
2.2 噪声过滤要在Blob之前做
很多人直接在原图上跑 CogBlobTool,结果发现 Blob 数量特别多,以为是自己参数没调好,其实是因为图像里的椒盐噪声、表面颗粒都被当成独立连通域了。我现在的习惯是,在 Blob 前面加一个 CogIPOneImageTool,先用中值滤波或者高斯滤波把高频噪声压掉;如果目标是小划痕,还常用形态学开运算把孤立亮点去掉,再用闭运算把断裂的划痕接起来。
具体参数端看目标尺寸而定。比如最小缺陷面积是 20 个像素,那么滤波核开到 3x3 到 5x5 就差不多了,切勿把核开得比缺陷本身还大,否则小缺陷会被直接滤掉。我在一个金属面板项目中就犯过这个错误,为了去噪声把中值滤波开到 7x7,结果细小划痕的灰度差异也被抹平了,漏检率直接飙升。
2.3 分辨率与目标尺寸的教训
Blob 检测有个底层约束:一个目标在图像里至少要占足够多的像素,分割结果才有统计意义。我一般按一个最简单标准来卡:最小可接受缺陷的成像面积不少于 9 到 16 个像素,也就是边长 3 到 4 个像素以上。如果缺陷只有 2x2 像素,那你分割出来的是目标还是噪声,本质上是个概率问题。
我曾经接过一个手机背板划痕项目,甲方要求检测宽度 0.05mm 的划痕,我算了一下,在给定视野和相机分辨率下,划痕宽度只占 1.5 个像素。这种情况做 Blob 就是硬来。后来换了更高分辨率的相机,或者干脆针对局部区域再放大成像,才把项目救回来。所以,任何 Blob 调参技巧都有一个前提:你的图像分辨率配得上你的检测精度。
3. 阈值与极性:Blob分割成败的生死线
3.1 阈值分割的三种主流模式
阈值分割是把灰度图变成二值图的那一步,CogBlobTool 里给了好几种阈值模式,我实际用下来主要就三种:固定阈值、自动阈值、动态局部阈值。
固定阈值适合对比度稳定、光照均匀的场景,比如背光下测螺丝轮廓。自动阈值适合整体光照稍有波动但目标和背景灰度分布呈双峰的图像,VisionPro 里提供了大津法、熵法等几种自动算法,用大津法居多。动态局部阈值针对的是光照不均的大幅面图像,它会在每个小邻域里单独估计阈值,效果比全局阈值好很多,但计算量更大,参数也更敏感。三者没有哪个绝对先进,全看场景。
| 模式 | 适用场景 | 优点 | 短板 |
|---|---|---|---|
| 固定阈值 | 光照稳定、对比度高 | 简单可控、实时性好 | 怕光照波动 |
| 自动阈值(大津/熵) | 双峰明显、轻微波动 | 自适应、稳定 | 双峰不明显时效果差 |
| 动态局部阈值 | 光照不均、背景渐变 | 对不均光强鲁棒 | 参数多、耗资源、易误分 |
3.2 极性:到底是抓亮斑还是抓暗斑
极性选反,是 Blob 调试新手最容易踩的坑。所谓极性,就是告诉软件你关心的目标是比背景亮还是比背景暗。比如背光源下测孔洞,背景是亮场,孔洞是暗斑,那你就得在模式里选择“暗目标”极性;如果前面用低角度光打凸起缺陷,缺陷呈现暗色,同样选暗目标。
听起来不难,但实际现场经常出现目标区域内部灰度不一致,亮的部分和暗的部分混杂。这时盲选单一极性会丢一半信息。我的做法是:先看整幅图的灰度直方图,确认目标峰和背景峰的位置,再决定抓哪个峰。规则很简单,目标灰度在背景的哪一侧,极性就往哪一侧选。还有一种情况,目标本身是亮斑,但目标中心有暗孔,或者表面有亮点,这个要配合下面的属性过滤来处理,别只靠极性硬撑。
3.3 阈值调参的现场方法论
阈值参数的调试,我的经验是四步走。第一步,关掉所有过滤条件,让 Blob 把能分割出来的区域全部展示出来。第二步,选择 20 张以上代表性样本图,覆盖来料正常、轻微波动、极端光照这些情况,逐张看灰度直方图。第三步,把阈值放在双峰谷底附近,留出合理余量。第四步,再逐步加上面积、形状过滤条件,去看剩余误检和漏检的平衡点。
这里有个容易忽略的动作:一定别只盯着当前屏幕上一张图调。现场光照时时刻刻在变,你按照亮场景把阈值定死了,暗场景一来就整片漏检。我习惯在阈值留 10% 到 20% 的裕量,然后在连续生产中观察一段时间,用统计结果回推是否需要修正。
4. 属性过滤与结果解读:让Blob从“能看到”变成“能判定”
4.1 面积过滤与形状过滤的取舍
分割出来之后,下一件事就是过滤。面积过滤是最基本的,设置最小面积和最大面积,把灰尘点、噪声点、超大范围的背景区域全部排除。很多人问这个范围怎么定,我一般先跑一遍不加过滤的模式,看所有 Blob 的面积分布,然后以目标缺陷的面积为中心,设定上下限。比如正常目标面积在 300 像素左右,那么下限可以设到 80,上限可以设到 600,具体看噪声和目标的重叠程度。
形状过滤进阶一点,VisionPro 的 CogBlobTool 里支持按圆度、细长度、填充率、孔洞等特征来筛。圆形脏污和规则圆形零件可以用圆度区分;划痕和圆形凹坑可以用细长度区分。要注意的是,过滤条件加得越多,系统越“挑食”,一旦来料出现你没见过的新形态,很容易误杀。所以形状过滤要谨慎,能用面积解决的,不要轻易上多条件叠加。
4.2 结果字段怎么读:重心、面积、角度、外接矩形
调完参数,需要把结果读出来用。CogBlobTool 的输出字段里,最常用的几个我要单独拎出来讲一讲,因为不少人看着这些字段一脸懵,不知道谁跟谁是联动关系。
面积指的是该连通域的实际像素数,它是判断大小缺陷最直接的依据。重心坐标给出的是区域几何中心在图像坐标系的像素位置,这常用于把 Blob 当成定位点或者计算偏移。外接矩形给出的是包裹这个区域的最小正置矩形(有些版本也能输出旋转矩形),常用来估算目标长宽。角度给出的是区域主方向,比如检测条形磁铁的方向偏移,就可以通过主方向角来判断旋转。
还有一个字段容易被忽视:孔洞数量,也就是区域内部暗孔的数。这在检测密封圈或者垫片裂纹时很有用,一个完整的圆环区域如果出现了额外的孔洞,往往意味着裂纹或破损。读这些字段时,你得想清楚自己要什么:是做尺寸判定,做位置偏差,还是做形状分类,三种需求对应的字段完全不同。
4.3 输出与判定:从图像结果到OK/NG信号
拿到了结果,接下来最难的反而是“怎么判定”。实际项目中,需求方通常不关心你有几个 Blob,只关心这个工件能不能用。我一般的做法是在 Blob 工具之后接一个用户脚本,从 Blob 结果里取面积最大或数量最关键的指标,和允许上限做比较,输出一个布尔值,再把这个布尔值映射到最终的 OK/NG 信号。
举个例子,一个药片表面的黑点检测,允许条件是“单个黑点面积不超过 250 像素,且总黑点数量不超过 3 个”。我就在脚本里遍历所有输出的 Blob,逐一判断面积和数量,只要有一项超了就 NG。这里要特别注意:这些判定阈值要在跑过大批量真品和缺陷样本之后才能定下来,拍脑袋定阈值的后果,就是上线之后误检率忽高忽低,你根本分不清是参数问题还是来料问题。
5. 组合拳打法:Blob与定位、卡尺、掩膜工具的协作流程
5.1 为什么单独跑Blob不够
很多新手在 VisionPro 里拉一个 CogBlobTool,输入图像就直接开始分析,然后把相机稍微动了一下,或者治具稍微偏了一点,结果就全乱了。原因很简单:Blob 只在它看到的像素区域里工作,它不知道自己应该检测的目标到底在图像哪个位置。如果你的检测区域是固定画死的,目标一旦偏移出那个区域,漏检就不可避免。
所以,单独跑 Blob 只适用于目标位置严格固定的场景,比如小视野高精度治具定位,或者目标被夹具死死卡住的工位。现实中,绝大多数产线做不到这一点。我的建议也很直接:把 Blob 放到一个整体视觉流程里去,前面让定位工具告诉你目标在哪,后面再让 Blob 去目标位置干活。
5.2 标准流程:PMAlign定位 + 坐标空间绑定 + Blob局部区域分析
我在现场最常用的组合是:用 CogPMAlignTool 先做一个基准模板定位,通过输出空间绑定建立一个从图像坐标到工件坐标的变换关系,然后把 CogBlobTool 的检测区域也放进这个坐标空间里。这样即使产品在视野里平移旋转,Blob 的 ROI 也能跟着目标走,始终框在你要检测的位置上。
这里有个容易忽略的操作细节:ROI 的坐标空间一定要和定位工具的坐标空间绑定,而不是随手在图像坐标里画个框。如果忘了绑定,相机一震动,前期工作全废。具体做法是:在 Blob 工具的输入里接收一个空间变换对象,ROI 形式选择“绑定到空间”,再用定位结果来驱动这个空间。绑定并不复杂,但理解了这层关系,你的方案就不再是“看运气”,而是真正的视觉系统架构。
5.3 掩膜工具:把干扰区域挡在门外
现场图像里往往有一些区域你不关心,但它们又实实在在会影响 Blob 的分割结果。比如产品表面印刷的字符、logo、条码,这些和你要检测的缺陷同为暗斑或亮斑,一旦进入检测区域,Blob 就会把它们当成缺陷,误检率瞬间爆炸。
处理办法是在 Blob 之前加一个 Mask 掩膜工具,把这些固定干扰区域干脆屏蔽掉。掩膜的好处是,不用去调整复杂的过滤逻辑,直接从源头把干扰排除。我在一个包装检测项目里,产品表面有一块固定的标签区,标签内容包含深浅不一的文字,不管怎么调阈值都会产生误检。后来用 CogMaskRegionTool 把标签区域挡住,误检率从 10% 直接降到 0.2%。掩膜区域一定要跟着定位走,否则目标一偏,干扰区域漏出来,等于白挡。
6. 现场项目复盘:三次典型的Blob翻车事故与修复路径
6.1 事故一:药板包装上的污渍误检
第一个项目是药板包装外观检测,要求找出板面上的黑点污渍。刚开始我在强光和相对均匀背景下测,效果很好,阈值设到 120,黑点、字符全部被正确分开。结果一上线,药板表面结构本身有凹凸,局部反光导致背景灰度不均,整幅图里出现了大片的高亮区,这些高亮区边缘被分割成了很多零碎的 Blob,误检满天飞。
修复路径分三步:首先在预处理阶段用背景矫正手段把光照不均压平,其次把面积过滤下限提高,过滤掉那些由边缘反光产生的碎小区域,最后把阈值从固定改成大津法自动阈值,让它在不同亮度条件下自己找分割点。改完之后误检率总算压到了千分之一以内。这个项目让我彻底信了两件事:背景矫正在 Blob 流程里不是可选项,而是必选项;自动阈值在光照波动场景里,比手动阈值可靠得多。
6.2 事故二:注塑件毛边粘连成一大片
第二个项目是注塑件边缘毛边检测。毛边形态比较细碎,但多个毛边在阈值分割后,会和主轮廓粘连在一起,形成一个巨型连通域。我设定的最大面积是 5000 像素,结果毛边和本体连起来之后面积是 3 万像素,按面积过滤它确实超限了,本体也因为被连带判定 NG,整批良品全部误杀。
这个问题的本质是“目标粘连”。单纯靠调高面积阈值救不了,因为毛边和本体的灰度太接近,分割阶段就分不开。我当时的做法是:把检测区域缩小到仅覆盖毛边可能出现的边缘带,避开本体大面积区域;同时在预处理里加了形态学腐蚀操作,先把毛边从本体上“掐断”,再跑 Blob。效果立竿见影。后来我又加了一条边界规则的判断:凡是被图像边缘切断的区域,不参与面积判定,避免工件边缘附近的正常区域被误算成缺陷。
6.3 事故三:金属高光表面反光导致Blob成片高亮
第三个项目最折磨人,是金属壳表面的磕碰伤检测。金属表面高光区域随着环境光变化而“游走”,某一时刻这些反光区域会连成片,把整个检测画面变成白花花一片。Blob 拿到这种图,分割出来的前景面积非常大,你根本分不清哪里有伤、哪里只是反光。
一开始我想通过调低阈值和加过滤来规避,试了整整两天,没用。后来痛定思痛回到光学方案:把光源改为条形光配合偏振片,消除高光反射。再搭配一个较暗的检测背景,让磕碰伤呈现出和正常表面不同的灰度。这一步做完了,后续参数调试顺风顺水。这个项目给我的教训特别深:Blob 的难度天花板往往不在算法参数,而在图像获取环节。参数调不出来的时候,回头去看打光,大概率能找到突破口。
6.4 小批量验证与上线追踪
最后聊一个贯穿所有项目的步骤:小批量验证与样本保存。每次调完一版参数,我都会从产线随机抽 50 件产品做离线验证,其中必须包含已知缺陷件。把检测结果和人工判定结果对照,统计误检率和漏检率。同时,我习惯把关键时刻的图像和参数配置全部导出命名保存,按照日期和项目批次归档。这样做最大的好处是:万一上线之后出了问题,能快速回退到之前有效的版本,不至于现场手忙脚乱地乱调。
灰度直方图的趋势记录也很重要。我会把每天同一种产品的灰度直方图存下来,做成趋势曲线。如果某一天发现背景峰偏移了,就说明过来料颜色变了或者光源衰减了,这时候哪怕 Blob 参数没变,也得提前预警。这种细节听起来琐碎,但真正能让你少跑几次现场。
我自己在调 Blob 时还有一个小习惯分享给各位:每一次调参,只改一个变量。哪怕是同时想改阈值和面积过滤,也先改一个,观察结果,再改另一个。同时改多个参数,就算结果变好了,你也不知道是哪个参数救了你。这个习惯帮我省掉了大量重复劳动,也让每次调试都能留下可复用的经验。Blob 模块看起来是个老工具,但只要你把它背后的逻辑吃透,很多新项目里它依然是最可靠的第一选择。
