机器视觉工业缺陷检测:传统算法、深度学习与工具链实战
2026/9/18 12:10:17 网站建设 项目流程

做工业缺陷检测这行,绕不开两个问题:用什么算法,靠什么库落地。相机、镜头、光源选完之后,真正决定项目能不能验收的,往往就是这两件事。我见过太多方案在实验室跑得漂亮,一上产线就崩——不是硬件不行,而是算法路线选歪了,或者工具链搭得不顺手,调试成本高到项目拖期。这篇就聊聊机器视觉工业缺陷检测里常用算法与库的那些实战细节,把我自己踩过的坑、试过的组合、以及一些参数怎么算出来的过程,尽量写清楚。不管你是刚入门的新人,还是已经做过几个项目想再系统梳理一遍的老手,应该都能从里面挑到能直接用的东西。

1. 动手选算法之前,先把这几件事想明白

1.1 像素精度到底被什么东西牵动

很多人一上来就问"用哪个算法",我更想先问一句:你的成像系统现在能看清多少?因为算法再强,也不能凭空造出信息。

像素精度的基本算式很简单:

单方向像素精度 = 视野(FOV)宽度 ÷ 相机该方向的像素数

举个例子,FOV 是 80 mm × 80 mm,相机是 5000 × 5000 像素,那像素精度就是 80 ÷ 5000 = 0.016 mm/px。如果换成 2000 × 2000 像素的相机,同样视野下就是 0.04 mm/px,差了 2.5 倍。

那"机器视觉动了什么会导致像素精度变化"?顺着这个公式反推就清楚了。第一类是相机本身变了:分辨率变了,或者换了一台像元尺寸不同的机器,虽然分辨率一样,但靶面尺寸变了会连带影响镜头选型,最终 FOV 也跟着变。第二类是光学链路变了:换了镜头焦距、调了工作距离、加了增倍镜或者延长环、更换远心镜头,这些都会直接改变 FOV。第三类是看起来不显眼但特别致命的:镜头畸变没做校正,视野边缘的实际像素精度和中心差一大截;相机安装有倾角,斜视会让视场发生透视变形;产线机械抖动导致工件在曝光瞬间移动,图像拖影,等效于精度下降。

还有一点必须拎出来讲:像素精度不等于测量重复性。亚像素算法在边缘对比度好、光照稳定的前提下,重复性做到 0.1 像素甚至 0.05 像素是有可能的,也就是 0.016 mm/px 的系统重复性可以到 1.6 μm 到 0.8 μm 这个量级。但如果光照在抖、工件表面反光不一致,亚像素的收益会立刻被吃掉。所以真正做项目,我会要求先做一轮 GRR(量具重复性与再现性)测试:同一批样品,反复上下料 30 次,看测量的标准差。这个数据比标称像素精度有用得多。

至于缺陷检出能力,我的经验值是这样的:缺陷在图像上最小维度的投影至少要占到 3 个像素,才谈得上稳定检出;对比度极高的情况下能压到 2 个像素,但误报率会明显上升。按 0.016 mm/px 算,3 像素对应 0.048 mm,也就是说这个系统理论上能可靠检出 0.05 mm 级别的划痕——前提是打光把它照出来了。

1.2 从缺陷特征倒推算法路线

我习惯把工业缺陷先分成四类,分类比选算法重要得多。

第一类是尺寸位置类,比如孔径、间距、偏移、缺失,这类缺陷有明确的几何定义,用传统算法加上亚像素测量就能做到很高精度,而且速度极快、结果可解释。

第二类是外观类,比如划痕、脏污、色差、压伤,形态多变、边界模糊,传统算法往往力不从心,深度学习的分类或者分割会更有效。

第三类是纹理类,比如麻点、橘皮、织纹异常,人眼看着有区别但说不出具体位置,这类问题用异常检测思路(只学好样本,偏离即报警)往往比强行标注缺陷更省事。

第四类是结构类,比如焊点虚焊、缺料、错装、反装,缺陷有固定的几种模式,属于典型的分类或目标检测问题。

说白了,缺陷有清晰几何定义就走传统路线,形态发散就走深度学习。这不是非此即彼,很多项目最后是两条腿走路:传统算法负责尺寸测量和定位,深度学习负责外观判定。

1.3 库的选型逻辑:别只盯着精度

选库的时候,精度只是其中一个维度。我一般会同时看五件事:授权成本、上手门槛、部署环境、和产线设备的对接能力、以及团队后续能不能接得住。

商业库(比如 Halcon、VisionPro、MIL 这类)算子成熟、文档厚、抗造,做传统视觉测量开发效率非常高,但授权费用不低,而且很多是绑定加密狗或者绑定设备的,具体价格得按项目去询。开源方案(OpenCV 是主力)零授权成本、社区活跃、跨平台,但很多高级算子要自己写或者拼,调试周期长。

还有一个经常被忽略的点:交接成本。如果你的项目做完要交给客户的设备部门维护,而对方只会用某一套工具,那你选一个他们完全陌生的库,后面每一次小改动都要找你,长期是个负担。这个账一定要提前算。

2. 传统视觉算法:靠算子打天下的那些路数

2.1 预处理:滤波不是越高级越好

新手容易犯的错是喜欢上"高级"滤波。双边滤波、非局部均值看着很厉害,但在工业实时场景里,它们的时间开销经常直接超预算。

我的一般顺序是这样:先看噪声类型,再做最轻的处理。椒盐噪声(传感器坏点、传输误码)用 3×3 中值滤波;高斯噪声用 3×3 或 5×5 高斯滤波;光照不均用背景相减或者顶帽变换(先做开运算得到背景,再用原图减背景),这招对付大面积明暗渐变特别有效;对比度不足用 CLAHE(限制对比度的自适应直方图均衡),注意它的 clipLimit 参数别调太大,否则会把噪声也放大成"缺陷"。

这里有个坑我必须提醒:检测点状缺陷(比如针孔、小凸点)时,尽量不要用大核中值或大核高斯。5×5 中值滤波足以把一个 2 像素的小黑点抹掉,你会发现自己怎么调都漏检,其实是预处理阶段就把信号毁了。这种场景我宁可改用小核滤波甚至只做背景相减。

2.2 边缘、轮廓与亚像素精度从哪来

边缘检测的经典三件套:Sobel、Scharr、Canny。Sobel 快但定位粗,Scharr 的核系数对旋转更友好,Canny 有双阈值和滞后连接,边缘连续性好,但参数敏感。

真正做测量,我不会直接用 Canny 的轮廓去算尺寸,因为它是像素级的,跳变会有 1 个像素的量化误差。工业上做尺寸测量,主流做法是卡尺工具(Caliper):在一条预设的搜索线上取一条垂直方向的灰度剖面,做一维的亚像素边缘定位,常用的方法有灰度矩法、多项式插值法、以及基于高斯导数拟合的方法。Halcon 里的 measure_pos、VisionPro 里的 Caliper 都是这一类。沿边缘均匀布 N 条卡尺线,把 N 个亚像素点拟合成直线或圆,重复性就能压到 0.02 到 0.05 像素。

标定这件事也不能省。棋盘格或者圆点靶标拍十几张不同姿态的图,用张正友标定法解出内参(焦距、主点、径向畸变 k1/k2/k3、切向畸变 p1/p2),再把图像去畸变。镜头畸变在视野边缘经常能到几个像素,不做校正,边缘区域的测量直接失真。

2.3 阈值分割、Blob 分析与模板匹配

阈值分割看起来最简单,其实花样不少。全局 OTSU 适合双峰直方图且光照均匀的场景;光照不均就上局部自适应阈值(比如局部均值减一个常数,或者局部高斯加权);如果是色差类缺陷,把图像转到 HSL 或者 Lab 空间,在色相、饱和度通道上做阈值,比在 RGB 上折腾有效得多。

分割完之后做连通域分析(也就是常说的 Blob 分析),把每个连通区域的特征提出来:面积、周长、圆度、长宽比、凸度、外接矩形的填充率、区域内灰度均值和方差。然后按这些特征做筛选和分类——面积超过多少算缺陷、圆度低于多少算异物、长宽比大于多少算划痕。这套组合拳在表面缺陷检测里至今仍然好用,尤其是缺陷形态相对固定的场合。

模板匹配分两派。基于灰度的归一化互相关(NCC)对光照变化有一定容忍度,但对旋转和缩放基本无能为力;基于形状的匹配(shape-based matching)用边缘梯度做特征,能支持旋转、缩放、部分遮挡,是目前工业定位的主流。用的时候注意两个参数:一是最小匹配分数,设太高会漏匹配,设太低会误匹配;二是搜索角度范围,角度范围每翻一倍,搜索时间大概也要翻倍,如果工件姿态基本固定,把角度范围收窄到 ±5° 能省下大量时间。

2.4 传统方法的边界在哪里

干了这些年,我总结传统算法崩掉基本就是三种情况。

一是光照变了就崩。阈值是跟当时的灰度分布挂钩的,换一批材料、换个班次环境光变了、灯管老化衰减了,阈值就得重调。这是传统方案在长期运行中最头疼的问题。

二是缺陷形态没定义清楚就崩。客户说"表面要干净",但什么叫不干净?没有量化描述,就没法设计特征。这时候强行上传统算法,最后会变成无限次调参数。

三是背景纹理复杂就崩。比如拉丝金属、编织面料、皮革纹路,背景本身的梯度变化比缺陷还剧烈,阈值和轮廓方法会被淹没。

碰到这三种情况,我的建议是不要硬扛,直接考虑深度学习路线,或者在光学上想办法把背景压掉(比如用偏振片、暗场打光)。

3. 深度学习算法:分类、检测、分割、异常检测四条路

3.1 分类网络做粗筛,性价比很高

图像分类是深度学习里门槛最低、落地最快的一类。ResNet50 是万金油,MobileNetV3、ShuffleNetV2、EfficientNet-B0 这些轻量级 backbone 在工业上用得非常多,因为产线节拍不等人。

我经常把分类模型放在流水线的第一级:先快速判断这张图是 OK 还是 NG,只有被判为 NG 的才往后送去做精细分割或者复核。这样能把整体计算量压下来一大截。

训练上的几个实操点:类别极不平衡时(工业上正常品远多于缺陷品),用加权交叉熵或者 Focal Loss,权重按类别频次的倒数开根号来设,别直接用倒数,否则容易过拟合到少数类;小样本时用 ImageNet 预训练权重做迁移学习,前几个 stage 冻结,只训后面几层和分类头;数据增强要贴合实际,别用大幅度的透视变换,因为工业相机基本是固定视角,加了反而制造了不存在的分布。

3.2 目标检测:单阶段和两阶段怎么选

目标检测是工业缺陷检测里用得最广的,因为它同时给出缺陷的位置和类别。

单阶段代表是 YOLO 系列和 SSD、RetinaNet;两阶段代表是 Faster R-CNN、Cascade R-CNN。工业上大多数项目选单阶段,理由很朴素:节拍。两阶段的第一步会生成大量候选框,再做第二阶段精修,精度常常高一两个点,但推理时间可能是单阶段的两三倍。

评估指标上,别只看 mAP50,那是 IoU 阈值 0.5 下的平均精度,对定位精度要求不高的场景够用;如果缺陷位置本身要量出来给下游用,就得看 mAP50:95。另外工业上更关心的是固定过杀率下的漏检率,这个后面会展开讲。

小目标缺陷是难点。我的常用手法有三个:提高输入分辨率(比如从 640 提到 1024,但耗时成倍增长,要权衡);用更浅层的特征图(P3 甚至 P2)承担小目标检测;重新聚类 anchor 尺寸,让 anchor 分布贴合你们的缺陷尺寸统计。这最后一条经常被忽略,但对小目标召回率影响很大。

3.3 分割:要像素级定位就得上

当缺陷的边界本身是验收指标时(比如要算划痕长度、面积、最大宽度),目标检测的矩形框就不够了,得上语义分割或者实例分割。

U-Net 及其变体是工业分割的常客,编码器-解码器加跳跃连接,小数据集上也能训得动。DeepLabv3+ 用空洞卷积扩大感受野,对大面积缺陷友好。SegFormer 这类基于 Transformer 的结构在纹理复杂的场景表现不错,但推理开销要实测。实例分割可选 Mask R-CNN 或者 YOLOv8-seg,前者精度好、速度慢,后者速度快、部署方便。

损失函数上,纯交叉熵在缺陷像素占比很小的时候会被背景主导,我一般用 Dice Loss 和 BCE Loss 加权组合,或者加 Focal 项。权重比例大概是 0.5 : 0.5 起步,再按验证集表现调。

3.4 异常检测:只有 OK 样本的时候怎么办

这是工业场景里非常现实的问题——产线刚起步,或者缺陷极其罕见,手上只有几百张正常样品图。这时候硬做有监督检测效果很差。

异常检测的思路是:只用正常样本训练,学出"正常长什么样",推理时凡是偏离正常分布的就报警。主流方法有基于特征嵌入的 PaDiM、PatchCore,基于归一化流的 FastFlow,以及最近的 EfficientAD 等。

它们的共同套路是:用预训练 backbone(比如 WideResNet50)提取多尺度特征,建立一个正常样本的特征记忆库,推理时计算测试图像每个位置的特征到记忆库的最近邻距离,距离超过阈值就是异常,再上采样成像素级异常热力图。

这套方法冷启动快、标注成本低,但也有明显的软肋。阈值极其敏感,同一个模型在阈值 0.5 和 0.55 下,漏检和过杀可能差出一倍;对光照变化和换批次材料很敏感,因为"正常"的定义变了,记忆库就失效了,需要重新采集正常样本更新;难以区分缺陷类型,它只告诉你有异常,不告诉你是什么异常。

我的建议是把异常检测当成第一道筛子或者冷启动方案,等积累了足够缺陷样本,再逐步过渡到有监督的分割或检测模型。两者也可以并行,取并集再人工复核。

4. 常用库与工具链,怎么搭才顺手

4.1 传统视觉的几套主流方案

方案语言/接口优势需要留意的地方
OpenCV(含 contrib)C++/Python/Java 等免费开源、跨平台、算子覆盖面广、社区资料多高级测量和形状匹配算子要自己拼,开发周期偏长
HalconHDevelop/C++/C#/Python算子成熟度高、亚像素测量和形状匹配强、文档全商业授权,费用按项目询价,绑定形式要提前确认
VisionPro图形化 + .NET上手快、拖拽配置、Cognex 生态配套商业授权,深度定制受限
MILC++/.NET性能好、硬件采集卡配套完善商业授权,学习曲线偏陡
scikit-image + NumPy + SciPyPython免费、适合做算法原型和离线分析实时性一般,不适合直接上产线

我的实际搭配通常是:原型验证用 Python + OpenCV + scikit-image 快速试,量产出方案用 C++ + 商业库或者 C++ + OpenCV。中间用同一套算法逻辑对齐,避免两套代码行为不一致。

4.2 深度学习框架与推理引擎

训练端基本是 PyTorch 的天下,TensorFlow 在部分老项目里还有存量。工业部署上,我一般走这么一条链路:PyTorch 训练 → 导出 ONNX(注意 opset 版本,12 或 13 兼容性好一些)→ 目标平台推理引擎。

推理引擎的选型看硬件:NVIDIA 平台用 TensorRT,OpenVINO 适合 Intel CPU 和核显,ONNX Runtime 跨平台通用性强,NCNN 在 ARM 上轻量,TFLite 在移动端和部分边缘设备上方便。量化方面,FP16 通常几乎不掉精度但速度提升明显;INT8 速度更快,但必须有足够有代表性的校准集,校准集没覆盖到的场景会掉点严重。我一般会准备三套模型做对比:FP32 基准、FP16、INT8,然后在真实验证集上评估,选满足节拍和精度要求的最轻那套。

4.3 3D 与点云相关的库

3D 检测这两年需求涨得快,尤其是高度、体积、平面度、装配干涉这类指标。

点云库的主力是 PCL 和 Open3D。PCL 算法全(滤波、配准、分割、特征),文档相对老;Open3D 的 Python 接口更友好,可视化方便,做原型很快。做工业 3D 检测,我经常用一个取巧的思路:把深度图转成高度图(height map),本质是一张 2.5D 灰度图,然后用成熟的 2D 算法去做——高度阈值分割、高度梯度找边缘、局部高度统计找凹凸,这条路比直接处理无序点云省太多力气。

真要处理点云,常见操作有:体素降采样、统计离群点滤波、RANSAC 平面拟合(把料盘或者基板平面去掉)、ICP 配准(和 CAD 模型对齐)、法向量估计。这些在 PCL 和 Open3D 里都有现成实现。

4.4 数据与训练辅助工具链

标注工具:LabelImg 适合矩形框,Labelme 适合多边形分割,CVAT 适合团队协作和视频标注,X-AnyLabeling 这类带模型辅助标注的工具能省不少时间——先让模型预标注,人工再修正,效率能翻倍。

数据增强:Albumentations 速度快、算子丰富,是首选;imgaug 老牌但慢一些。要注意增强算子要和实际分布一致,比如工业场景一般不允许水平翻转(如果缺陷有方向性),也不建议用大角度旋转。

实验管理:TensorBoard 看曲线够用,MLflow 或者 Weights & Biases 适合多人多实验对比。数据版本管理用 DVC,能把数据集和模型权重一起管起来,方便复现——这一点在项目交接和问题回溯时价值极高。

5. 一次表面缺陷检测的完整落地过程

5.1 需求拆解与硬件、算法指标换算

假设一个真实需求:检测金属表面的划痕,最小要求检出 0.1 mm 宽、3 mm 长的划痕,产线速度 30 m/min。

先算像素精度。取 FOV 80 mm × 80 mm,相机选 5000 × 5000 像素,像素精度 = 80 ÷ 5000 = 0.016 mm/px。0.1 mm 的划痕宽度在图像上占 0.1 ÷ 0.016 ≈ 6.25 个像素,远高于 3 像素的最低门槛,余量充足。如果选 2000 × 2000 像素,像素精度 0.04 mm/px,0.1 mm 只占 2.5 像素,太勉强,风险大。

再算镜头焦距。用公式:

f = 工作距离 × 靶面尺寸 ÷ 视野尺寸

假设工作距离留 300 mm,相机靶面 1.1 英寸(对角线约 17.6 mm,按短边约 12.3 mm 估),FOV 短边 80 mm,则 f = 300 × 12.3 ÷ 80 ≈ 46 mm。选一个 50 mm 的工业镜头,然后通过微调工作距离把视野压到目标值:WD = f × FOV ÷ 靶面 = 50 × 80 ÷ 12.3 ≈ 325 mm。这个反算过程比拍脑袋选镜头靠谱得多。

接着算节拍。产线 30 m/min = 500 mm/s。取步进量 64 mm(FOV 80 mm,留 20% 重叠避免漏拍接缝处缺陷),则每秒需要拍 500 ÷ 64 ≈ 7.8 帧。如果一台相机负责一个工位,单相机要 8 fps,这个要求很宽松。但如果视野只有 80 mm,整幅工件宽 300 mm,就需要 4 台相机横向拼接同步拍摄,一个工位同时出 4 张图,合计 32 张/秒的处理量,这时候算法耗时就必须压到 31 ms 以内,否则就得加并行。

5.2 打光方案怎么定

打光在缺陷检测里的权重,我个人给到 50% 以上。同一个划痕,换个光角度,可能从清晰可见变成彻底消失。

常见方案和适用场景:暗场低角度打光(光源接近与表面平行),适合划痕、凹坑、凸起这类有高度变化的缺陷,因为它们在斜射下会产生明显的明暗对比;明场同轴打光,适合镜面或者高反光表面,能打出均匀的正面照明;背光,适合轮廓测量和尺寸检测,缺陷以剪影形式呈现;条形光配多角度,适合柱面、曲面的分段照明;穹顶光(无影光),适合表面颜色和印刷字符检测,因为它消除了反光差异。

我的实操流程是这样的:先在实验台上用手持光源绕工件扫一圈,相机实时预览,看哪个角度、哪个方位能把目标缺陷照得最明显、同时把背景纹理压得最平。这一步花一两个小时,能省掉后面几周的算法调参。

还有两个小技巧。一是波长匹配:不同颜色的光在材料上的反射率不同,比如红色光对蓝色油墨的对比度更高,蓝色光对红铜表面反射更强,配一套红蓝白三色可切换光源,很多时候能直接把信噪比提一个档次。二是偏振片:在光源前和镜头前各加一片偏振片并调节相对角度,能有效压掉金属表面的镜面反射,让表面下的真实缺陷浮现出来。

5.3 数据准备与增强策略

数据量上,我的经验是每个缺陷类别至少 300 到 500 张,覆盖不同光照、不同批次、不同工件姿态。正常样本数量要多一些,1000 张以上比较稳。

标注规范必须提前定好,划痕的标注框要不要包含轻微扩散的边缘、两个相邻缺陷要不要合并成一个、模糊到看不清的算不算缺陷,这些都要写成文档让所有标注人员对齐。标注不一致比数据量不足更致命,模型学到一半是噪声,怎么调都上不去。

增强策略上,我常用的组合是:随机亮度、对比度、伽马扰动(模拟光照波动,这个最有效)、高斯噪声、轻微旋转(±5°)、随机裁剪。要避开的是会破坏缺陷特征的算子——细划痕做大幅度缩放或者强模糊后直接消失,等于给模型灌了错误标签。

数据划分上,一定要按批次或者按工单划分,不能随机划分。同一批材料上的图片纹理高度相似,随机划分会导致训练集和验证集数据泄漏,验证指标虚高,上线就崩。这是新手最常掉进去的坑。

5.4 训练、调参与评估

以 YOLO 类检测模型为例,我的一组常用起点配置:输入 640 × 640(或按缺陷尺寸提到 1024),batch size 16,初始学习率 0.01 配 SGD 或者 0.001 配 AdamW,warmup 3 个 epoch,余弦退火到初始值的 1%,训练 300 epoch,权重衰减 5e-4。

评估的时候重点看两条:一是 PR 曲线,二是固定过杀率下的漏检率。工业客户通常能接受一定的过杀(误报),但漏检必须是零容忍或者极低。所以我会找出在过杀率 1% 时漏检率对应的那个置信度阈值,把它作为上线阈值。如果这个点的漏检率还是偏高,说明模型能力不够,回去补数据或者换更大输入尺寸,而不是靠调阈值硬压。

5.5 部署与加速

部署这部分我踩过的坑最多。一条实践过的优化路径:模型导出 ONNX(opset 12),用 TensorRT 构建 FP16 引擎,batch 设为 4,单帧推理耗时从 FP32 的 45 ms 降到约 12 ms,基本满足 30 ms 的节拍要求。

再往上有三个方向。一是流水线并行,把采集、预处理、推理、后处理拆到不同线程或者不同 CUDA stream,让 GPU 不空转。二是零拷贝,图像从采集卡到 GPU 显存尽量不经过主机内存来回搬。三是模型层面,用结构化剪枝、知识蒸馏,或者干脆把大模型裁成只在我们关心的 ROI 上推理——很多场景整张图只有一小块区域需要检测,裁 ROI 能省掉八成算力。

注意:INT8 量化一定要用生产现场采集的校准集,不要图省事用训练集。训练集经过增强,分布和真实推理输入不一致,校准出来的缩放系数会偏,掉点很隐蔽,往往实验室看不出问题,上线才发现。

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

6.1 训练集精度 99%,一上线就崩

这是最高频的问题,原因基本逃不出下面几条,按这个顺序查效率最高。

第一条,数据泄漏。随机划分数据集导致训练集和验证集包含同一批工件、同一次拍摄的图像,验证指标虚高。解决方式是按批次划分,并且在划分前用图像哈希去重。

第二条,成像条件不一致。训练时用的相机曝光、增益、伽马、白平衡,和上线设备的设置不同;或者镜头上有灰尘、保护镜有划痕;或者现场环境光和实验室不同。排查办法是把上线时采集的图存下来,和训练集的图做直方图对比,一眼就能看出差异。这是我最推荐的第一排查动作,比看模型曲线有用得多。

第三条,工件姿态和位置差异。训练时工件都是手工摆正的,上线后是机械手上料,角度有 ±5° 的偏差。解决方式是在训练数据里加入姿态扰动增强,或者加一级定位对齐预处理。

6.2 漏检与过杀的拉扯

这是永恒的矛盾,不可能同时压到零。我的处理思路是分级判定加多级复核。

第一级用高召回阈值,宁可过杀高一点,把可疑的都挑出来;第二级用更精细的模型或者传统算法对可疑区域做复核,把真正的过杀剔掉;第三级留人工复检工位处理剩下模棱两可的少数样本。这样总体过杀率能压下来,同时漏检保持极低。

另外几个技巧:对检测框做形态学后处理,把重叠的框合并、把面积过小的框过滤掉(通常是噪声);用连续多帧确认机制,同一个位置在连续 N 帧或者 N 个工件上都报警才判定为真缺陷,能有效压掉偶发噪声;用多模型投票,两个不同结构的模型同时报警才算,召回稳、过杀低,代价是算力翻倍。

6.3 节拍跟不上怎么办

按优先级排,我一般这么干。

先降输入分辨率,从 1024 降到 640 通常能省一半以上时间,但要验证小缺陷是否还检得出。再裁 ROI,把无关区域切掉,这是收益最大的手段之一。然后换轻量模型,大模型换小模型,配合知识蒸馏弥补精度损失。再上推理加速引擎和 FP16。最后才是加硬件或者加并行进程。

需要提醒的是,不要一上来就砍模型。很多时候瓶颈在预处理和后处理的 CPU 代码上——比如图像解码、色彩空间转换、NMS 后处理,这些如果用 Python 循环写,比推理本身还慢。先做一轮 profiling,看清楚时间花在哪,再决定优化什么。

6.4 常见问题速查表

现象可能原因排查动作解决方向
上线后大量误报光照变化、阈值不匹配、镜头脏污对比上线图与训练图直方图重采数据微调、固定光源、清洁光学件
小缺陷漏检严重输入分辨率不足、anchor 不匹配、预处理抹掉信号打印像素尺寸、检查 anchor 尺寸统计提高分辨率、重聚类 anchor、改小滤波核
推理耗时波动大CPU 预处理拖后腿、显存换页分段计时,看各环节耗时分布预处理并行化、固定 batch、使用零拷贝
换批次材料后性能下降数据分布漂移、表面反射特性变了采集新批次样本做评估增量训练、调整光源角度或波长
分割边界毛糙损失函数偏背景、下采样丢失细节看分割热力图与真值对比加 Dice Loss、加跳跃连接、提高输出分辨率
模型文件导出后精度掉点算子不支持、量化校准集不匹配逐层比对 ONNX 与原始输出换 opset、换等价算子、重做校准集

7. 踩坑之后的一点私人经验

做了这些年,我越来越觉得,工业缺陷检测里最贵的从来不是算法,而是把不确定的东西变成确定的东西这个过程的成本。算法选型错了可以换,但数据标注错了、成像方案定死了、现场光照没法改了,那才是真的麻烦。

我自己的习惯是:项目启动阶段花七成时间在成像和打光上,把信噪比做上去,后面算法环节会顺得不可思议。反过来,靠算法去救烂图,永远是投入产出比最差的一条路。

还有几个小习惯我一直保留着。参数一律配置化,写进 yaml 或者数据库,别硬编码在代码里,现场调阈值的时候能省掉重新编译和发版的时间。每次上线都把原始图、模型输出、最终判定、以及当时的参数全量落盘存一段时间,出问题的时候能回溯,这个日志的价值在半年后才会真正体现出来。模型版本和数据版本用工具管起来,别靠文件名区分,model_final_v2_真的最终版.pth这种命名早晚会出事。

最后一句实在话:能把一个缺陷检测项目做成功的团队,通常不是算法最先进的团队,而是把光学、机械、算法、现场调试这几块咬合得最紧的团队。算法和库只是其中一环,别把它当成全部。

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

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

立即咨询