从产线堆满报废板,到模型跑通的那天晚上,说实话我整个人是有点恍惚的。前前后后折腾了大概两个月,搭完这套基于深度学习的PCB板缺陷检测系统,从数据标注、模型选型、训练调参,到最后接上工业相机部署到测试线上,中间每一步都踩了不少坑。这个项目不算新颖,市面上现成的教程和论文也很多,但真正能让人从零开始、完整跑通一整套流程的资料其实并不多。大部分要么只讲理论,要么只贴代码,部署文档和业务落地的部分往往一笔带过。所以我想把这套系统的完整实践过程整理出来,供做视觉检测的同学参考。
这套系统的核心价值很简单:用深度学习模型代替传统机器视觉规则和人工目检,对PCB板表面的缺孔、短路、断路、鼠咬、划痕、多余物等常见缺陷做自动检测和分类。适合的人群包括电子制造行业的视觉工程师、做毕设或项目实践的学生,以及想了解检测类CV项目如何落地的开发者。
先说结论:光是模型能跑出高mAP还不够,真正让系统在产线上站住脚的,是数据采集的一致性、后处理业务规则的兜底,以及部署链路里每一个容易被忽视的细节。下面我把整个项目掰开揉碎讲。
1. 为什么PCB质检非要上深度学习:缺陷类型与人工巡检的现实困境
1.1 产线质检员看一眼能发现什么
PCB 板的缺陷检测一直是电子制造里最头疼的环节。一块高密度多层板,线路间距可能只有几十微米,过孔密密麻麻,焊盘间距小到肉眼分辨都困难。传统的人工目检,一个熟练质检员一天要看几百块板,平均每块板几十秒,在高强度工作下漏检率根本压不住。这不是人的能力问题,是生理极限问题。
漏检的后果很严重。一块缺陷板流入后端贴片或者成品组装环节,后面排查故障的成本可能放大十倍百倍。所以大部分产线的做法是设置多个质检工位,人海战术叠加AOI设备初筛,人工复判。即便这样,复判人员每天盯着屏幕看缺陷图,看久了也容易麻。
很多公司其实很早就上了传统机器视觉AOI。基于模板匹配、边缘检测、连通域分析这类手段,对于形态固定、背景干净的场景,确实能跑得不错。但PCB缺陷的麻烦之处在于,缺陷类型多、形态变化大,同一类缺陷在不同批次板材、不同光照条件下,呈现出来的样子差异非常大。
传统视觉算法的本质是人工设计特征,你需要告诉算法“什么样的算是短路”“什么样的边缘梯度算断路”。但缺陷的形态学特征不是几个固定规则能概括的,过度依赖规则的代价就是误检率居高不下。比如一个转角处的正常铜箔形状不规则,规则引擎很容易把它当缺陷标出来,导致产线上大量误报,复判工作反而加重了。
1.2 深度学习做识别和人工目检的差异在哪里
深度学习检测器的思路完全不同:它从大量标注样本里自动学习缺陷的视觉特征,而不是靠人工定义规则。你给它几千张“断路”的图,它会自己在特征空间里归纳出一套判断标准。
这种数据驱动的做法有两个实打实的好处。第一,对形态多变的缺陷适应性强,同一类缺陷换个方向、换种粗细、换块基板颜色,模型依然能识别。第二,模型的泛化能力是可迁移的,当产线引入新板型时,只要补充少量标注数据做微调,就能快速适配新场景,这是规则引擎不具备的。
但深度学习也不是万能钥匙。我必须说清楚它的硬边界,否则你会像我一样在项目中期摔一跤。深度学习模型本质上是概率推断,它给出的每个检测框都带置信度,意味着永远存在误判的可能。模型对分布漂移极其敏感——这里的光照、相机参数、板面颜色变了,检测精度立刻会掉给你看。
所以完整落地系统绝不能只靠模型本身,通常会在模型外围套一层业务逻辑:判断缺陷面积是否达到判废阈值、特定缺陷类型是否在连续几块板上重复出现、缺陷位置是否处于关键线路区域。这层规则引擎在大模型时代可能显得有点“土”,但它是保证系统可靠性的基石。
2. 数据是这套系统的命门:样本来源、标注规范与增强策略
2.1 先用公开数据集把流程跑通,别急着上产线数据
做检测项目第一件事不是找模型,是找数据。常见做法是先从公开的PCB缺陷数据集入手。这类数据集通常包含六类典型缺陷:缺孔、鼠咬、短路、断路、腐蚀、多余物,每类缺陷都有几十到几百张不等的图像和对应的标注框。
我的做法是先把公开数据按训练集、验证集、测试集大概 7:2:1 的比例拆开,训练集和验证集来自同一批数据源,测试集单独留出来不参与任何调参。这个“测试集隔离”的习惯特别重要,我见过不少人拿验证集反复调参,最后在真实数据上崩盘。
第一版模型在公开数据上的 mAP@0.5 很快就跑到了 90% 以上,看起来不错,但别高兴太早。公开数据集里的图像来源比较单一,图像分辨率、光照、板面干净程度都和真实产线有差距。它只能作为算法选型和代码链路的验证,不能作为项目交付的性能承诺。
2.2 自建产线数据时,采集规范比数据量更优先
模型能不能在真实场景里用,90% 取决于采集数据的质量一致性。我在这块踩过的坑可以说非常惨烈:前期没有固定相机曝光参数,白天和晚上采回来的图像亮度差异巨大,模型训练时表现稳定,一到白天现场就频繁漏检。
采集规范里优先级最高的几件事:
- 固定光照环境:用环形光源加漫射板,消除板面反光和阴影干扰。PCB板表面的铜箔反光很厉害,光源角度稍微变一点,图像上缺陷的对比度就会差很多。
- 固定相机与镜头参数:曝光时间、增益、光圈全部锁定,拍摄距离和焦距固定,保证不同批次图像的光照分布、清晰度基本一致。
- 固定板子摆放方向:PCB板是有方向性的,但检测模型最好对旋转不敏感。前期可以统一方向采集,后期模型稳定了再逐步增加随机采样的方向。
- 覆盖不同批次、不同板型:同一个缺陷类别在不同批次的板材上,颜色、纹理、粗细差别很大,单一板型训练出来的模型换板型几乎必崩。
如果条件允许,建议采集的时候直接把缺陷坐标也记下来,用机械定位加人工确认的方式生成初版标注,这样能大幅减少标注工作量。
2.3 标注一致性怎么控制才不至于后期返工
标注环节看起来没有技术含量,实际上是最容易埋雷的环节。不同标注员对“这个算不算短路”“这条划痕标不标”的理解不一致,会直接导致模型学习到混乱的标签边界。
项目里我做了两个事情来控制标注质量。一是写了一份简明标注规范,明确每个缺陷类别的最小面积阈值和典型边界示例,最短的是一句判断式口诀,比如“线路之间搭接但仍有间隙的不算短路,只有铜箔直接相连的才算”。二是抽检制度,每天按一定比例对当天新增标注做二次审核,发现问题当天就打回给标注员修改。
标注工具选常见的开源标注软件就行,导出格式建议统一为 COCO 或者 YOLO 格式。我个人偏好 COCO 格式,因为后续做数据增强、评估、训练脚本对接都比较通用。格式统一的好处是你换模型框架的时候不用重新标注。
2.4 数据增强要克制:PCB板不是自然图像
很多做自然图像检测的同学习惯一上来就是随机旋转、随机裁剪、马赛克增强、HSV抖动全套招呼,这在PCB检测场景其实是有争议的。PCB板是刚性结构,线路和缺陷的方向具有物理意义,过大角度的随机旋转会让模型学到“板子可以是歪着的”这种不存在的规律。
我用下来效果比较稳的增强组合是:水平垂直翻转、小角度随机旋转(正负10度以内)、随机平移、小范围的亮度扰动。尺度缩放不建议做太大,因为微小缺陷在缩放过程中容易丢失纹理细节。马赛克增强可以用,但要注意在马赛克拼接时别让PCB板的纹理连接变得不自然。
对于缺陷样本不均衡的问题,增强也没办法彻底解决。公共数据里短路和断路样本一般多一些,腐蚀和多余物少一些。我的经验是按缺陷类别做过采样,把数量少的类别在训练时多抽几遍,比单纯生成一堆强增强样本更管用。
3. 模型选型:两阶段网络与单阶段网络在PCB场景的真实差距
3.1 不同技术栈的模型在这个任务上各有什么本事
做目标检测绕不开两个流派:两阶段检测器和单阶段检测器。两阶段代表如Faster R-CNN家族,思路是先通过区域提议网络生成候选框,再对每个候选框做分类和回归,精度上限高,尤其小目标和密集目标场景表现更稳,但推理速度慢,工程部署链路重。单阶段代表如YOLO家族和RetinaNet系列,一步到位直接回归出类别和框,速度快,适合实时场景,小目标检测能力相对弱一些,但近年来不断在补齐。
我在选型时画了一张对比表,列了几个关键维度:
| 维度 | 两阶段检测 | 单阶段检测(YOLO系) |
|---|---|---|
| 精度上限 | 高,小目标占优 | 中高,依赖输入分辨率与训练策略 |
| 推理速度 | 慢,需高端GPU才能上实时 | 快,边缘设备也可勉强实时 |
| 训练资源 | 高 | 中等 |
| 工程生态 | 一般,部署链路长 | 成熟,导出推理框架方便 |
| 数据需求 | 多,训练敏感 | 相对友好,数据增强空间大 |
实际项目里我最终选了YOLO系的模型,原因不复杂:第一,产线检测对实时性要求高,需要配合机械手臂分拣或者回流线速度,单阶段模型的推理延迟优势明显;第二,工程生态很关键,模型导出到推理引擎、C++调用、自定义后处理钩子都很顺畅,双阶段模型在这些环节往往要自己手动写更多胶水代码。
当然,如果条件允许且缺陷类别极其考验小目标识别能力,也可以考虑在YOLO框架基础上引入一些两阶段的辅助机制,比如在特征融合阶段加注意力模块。我的实验数据里,加注意力机制对mAP的提升只有1到2个百分点,但对个别微小缺陷类别的召回率提升明显得多。
3.2 我选用的这个模型结构里,哪些改动真正有效
以YOLOv8为基础的话,框架本身已经做得相当好了。Anchor-Free的设计让模型少了很多调参烦恼,解耦检测头对提升精度也有帮助。真正需要你花心思的往往是细节配置,而不是去改模型主结构。
训练初期我发现一个明显问题:对相距很近的相邻目标,模型会倾向合并成一个框或者漏掉其中一个。PCB板上密集的走线和小焊盘很容易出现这种情况。排查下来,问题出在NMS的IoU阈值设置上,阈值太高容易保留重复框,阈值太低会把相邻缺陷框误杀。我最后把NMS的IoU阈值调到0.45,效果是最稳的。
输入分辨率对检测效果的影响比想象中大得多。默认的640分辨率对于缺孔、划痕这类几毫米大小的缺陷来说,特征表达是不够的。把输入分辨率提到1280以后,微小缺陷的mAP提升非常显著,我从72%直接拉到82%,代价是训练时间和显存占用翻了将近一倍。产线硬件如果允许,这个分辨率提升是性价比最高的优化手段。
3.3 预训练权重的迁移学习策略
从头训练一个检测器在工业场景基本属于浪费时间。我有一次尝试不加载预训练权重,在公开PCB数据集上从头训练YOLOv8n,loss下降极慢,最后mAP比加载预训练权重的版本低了十多个点。
所以强烈建议使用COCO预训练权重做迁移学习。迁移学习时冻结策略也很简单:数据量比较小时,把backbone前几层冻结不动,只训练深层特征和检测头,能有效防止模型在有限数据上忘掉通用特征;数据量足够丰富时,全部层一起微调,效果会更好。
我在两批数据上做过对照。第一批公开数据约两千张,冻结前两层比全量微调mAP高了大约3个点。第二批加了产线数据约五千张,全量微调反而更好。这说明冻结策略取决于数据量,你需要自己跑两组实验对比,不要盲目照搬别人的结论。
4. 训练调参与指标解读:从loss曲线到产线可接受标准
4.1 训练配置与硬件选择
训练阶段我用的是一张中高端显卡,显存24G。模型选了YOLOv8s中间档,输入分辨率1280,batch size设为8,刚好卡在显存边缘。如果显存不够,可以减batch size或者退回到YOLOv8n,但微小缺陷能力会打折。
优化器用AdamW还是SGD,其实在YOLO框架里差距不大,我用的是SGDMomentum配合余弦退火学习率。初始学习率0.01,加了500步的预热Warm-Up,让模型在训练开始时避免因为大学习率导致loss震荡。Loss曲线训练到第80轮左右开始进入平台期,我设了早停机制,验证集mAP连续15轮不提升就停止训练,避免了过拟合还省时间。
固定随机种子这件事千万别偷懒。不固定种子的时候,同样参数下两次训练mAP能差两三个点,这对实验对比是致命的。在代码开头手动固定全局随机种子,涉及NumPy、PyTorch和Python的random模块,三个都要设置。
4.2 评估指标应该怎么看才不容易被骗
很多人只看mAP@0.5一个数字,说实话这是最容易被骗的指标。mAP@0.5只要求预测框和真值框的IoU超过0.5就算检测成功,这对于大目标很宽容,但PCB缺陷属于小目标,IoU算分很容易不稳定,mAP@0.5的高分不能说明模型小目标检测能力好。
更可靠的指标组合是:mAP@0.5、mAP@0.5:0.95、每一类缺陷的召回率、误检率。特别是单类召回率,在缺陷类别样本不平衡的项目里,总体mAP可能被样本多的类别拉得很高,但样本少的“腐蚀”类召回率可能只有30%,这种缺陷恰恰是产线最不希望漏掉的。
我在项目后面加了一个统计脚本,专门输出每个类别在给定置信度阈值下的召回率和误检框数量,用这个数据来动态决定置信度阈值。产线场景里漏检的代价远大于误检,所以我把置信度阈值从默认的0.25调低到0.1,模型会多出一堆低置信度预测框,再用后处理规则筛选掉明显不合理的框,这套组合比单纯提高模型置信度靠谱得多。
4.3 最难啃的骨头:微小短路和划痕检测
项目里最难处理的缺陷类型是微小短路和细小划痕。微小短路指的是两条相邻线路之间出现极其细小的铜桥连接,宽度可能只有十来个像素;细小划痕则是板面基材或铜箔上细长的表层损伤。
这类缺陷的困难在于特征太弱了。一个缺陷在1280分辨率下可能只占不到全部面积的百分之二,模型主干网络下采样到最后的特征图上时,这个缺陷可能已经退化到三四个特征像素,特征表达严重不足。IoU分配策略对小目标也不友好,一个微小目标即使定位偏差几个像素,IoU可能就从0.5掉到0.1了,导致它难以被分配为正样本参与训练。
针对这个情况,我用了三管齐下的策略。第一,把切片策略引入训练,将1280原图切成四个640的patch,每个patch单独参与训练,等于放大了缺陷在图像中的相对比例;第二,对微小缺陷类别做了基于复制粘贴的样本增强,从另外的图像里裁出微小缺陷区域,随机合成到正常板子图像中;第三,推理阶段对原图和切片图分别预测,再做一次全图尺度的结果融合。这套方案把微小缺陷的召回率从72%提到了90%左右,代价是推理耗时增加了将近一倍。
如果你对实时性要求很高,我建议优先选切片训练加高分推理,全图加切片的融合推理适合离线抽检,不适合每条产线全检。
5. 部署环节:从PyTorch模型到产线上能稳定跑的检测服务
5.1 模型导出和推理加速的细节
训练好的PyTorch模型不能直接扔给产线,还需要过一道模型转换的坎。我先把模型导出为ONNX格式,再转成推理引擎的加速格式,在保持FP16精度的情况下,单张1280x1280图像的推理延迟从PyTorch直接推理的80毫秒降到了20毫秒左右,基本满足产线每秒处理3到5张的速度要求。
这里有几个导出和转换过程中的坑值得注意。第一,ONNX导出时动态轴设置要准确,固定batch size为1省事,但模型在转换时如果没指定好动态分辨率,推理阶段输入尺寸一旦变化就会报错。第二,FP16精度下部分小型缺陷的置信度会略微下降,我做了对比实验,FP16比FP32的mAP掉了大约0.5个点,可以接受。第三,推理引擎的batch size设置为1就行,PCB检测是单张处理场景,别去追求高并发。
5.2 工业相机接入和图像预处理流水线
产线上相机采集到的原始图像不能直接送进模型,还需要做对齐的预处理。我用的是工业相机SDK直接取流,触发模式设置为硬件触发,到了固定位置就拍一张,保证每次拍到板子的物理位置一致性,减少后续图像配准的难度。
图像格式和预处理环节的常见错误是直接按OpenCV默认方式读取灰度图,再三通道复制。工业相机输出的往往是8位或者12位灰度图,12位数据需要先做位深转换再归一化,否则图像对比度下降得非常厉害。正确的流水线是:相机原始数据转8位灰度图、校正像素格式、根据标定参数做ROI裁剪、归一化到0到1的浮点范围、再转成模型输入需要的张量格式。
如果相机画面里板子会有轻微偏移,可以在预处理里加一个基于模板匹配的ROI对齐步骤。我一开始没有加,结果板子在传送带上左右偏了十几个像素,模型预测框也跟着偏移,后处理统计缺陷位置时全乱了。加了模板匹配校正之后,这个偏移问题基本消失。
5.3 后处理规则引擎:模型只是前端,业务判级才是兜底
模型输出的一堆检测框,直接判废的话误杀率会很高。我在检测服务里加了一个规则引擎,流程是这样的:先过滤置信度低于阈值的检测框,再做非极大抑制合并重叠框,然后计算每个检测框的缺陷面积和位置信息,最后根据业务规则判级。
规则引擎的判级逻辑是灵活配置的,我常用几个规则是:微小缺陷如果面积超过一定阈值且处于关键线路区域,判为废品;同一种缺陷如果在连续几块板的同一位置反复出现,触发预警并通知上游工序排查;孤立的、极小面积的低置信度缺陷框,标记为观察级,不判废但需要人工抽检。
这套后处理流程在项目中后期发挥的作用比模型调参还大。加了规则引擎之后,误检率降低了40%左右,而且因为规则可配置,产线工程师可以自己调整阈值,不用每次改模型重训练。这才能让系统真正在业务场景里被接受。
6. 论文与项目文档:技术实现之外,如何让整套系统显得可信
6.1 文档该怎么组织才不像课程作业
项目标题里带了“论文+部署文档+讲解”,说明交付物不只是可运行代码,还包括系统的完整描述和论证。我在写配套文档时首先强调的不是模型效果,而是系统需求定义和整体架构。一张清晰的系统架构图,比几千字描述管用得多。
文档结构我建议按这样的顺序:项目背景与需求分析、总体系统架构设计、数据集描述与统计分析、模型选型与实验对比、训练与评估结果分析、部署与性能测试、业务规则与运维设计。每一部分都不要写成纯理论复述,而是结合系统里真实的参数和实验数据。
数据集部分一定要附带统计表:类别数量、图像总数、划分比例、增强策略。这能表明你在数据上做了系统性的工作,而不是拿了一堆图片随手训练。模型选型部分放一张实验对比表,记录不同模型、不同输入分辨率、不同增强策略下的mAP、召回率、推理耗时,这是项目最有力的可信度证明。
6.2 验收时我被问得最多的几个问题
做项目答辩或者给技术负责人汇报时,高频问题几乎集中在模型的泛化能力和故障兜底上。第一次汇报时我被问“你这个模型换一条产线还能不能保持这个精度”,当场有点愣住。后来我补做了一组交叉验证实验,用A产线数据训练,B产线数据测试,把掉点幅度记录下来作为泛化性能的参考依据,虽然掉点不少,但这个数据远比说“可以”有说服力。
另一个常见问题是“漏检了怎么办”。这个问题不能只回答“提高模型精度”,要讲清楚系统里有什么机制兜底:置信度阈值动态调整、后处理规则预警、人工复检工位。模型做不到100%,但系统可以设计成“模型初检加规则过滤加人工复检”的分层筛选机制,这才是工程上的解决思路。
论文写作这块还有一个容易被忽略的点:不要只展示最好的实验结果,应该把踩过的坑和失败的实验也写进去,比如初次调节NMS阈值时的失败案例、增强策略失控导致精度下降的实验记录。这些内容反而能体现你对问题的理解深度,也方便后来人避开同样的坑。
6.3 讲解视频里最值得讲的不是代码
标题里提到“讲解”,很多同学会把讲解重点放在代码逐行解释上,这是我认为最不值得花时间的做法。代码是死的,理解才是活的。讲解里有价值的是决策过程的重现:为什么选这个模型、为什么调这个阈值、为什么用切片增强而不用旋转增强。这些决策链条才是做项目最值钱的思考方式。我会在讲解中穿插失败案例,把一个坑从现象到定位到解决的全过程讲一遍,比单纯讲一遍正确代码的传授价值大得多。
交付时别忘了把运行环境和依赖版本完整锁住,我吃过版本不兼容的亏。modelscope时代不同,但在工业项目里,模型训练代码、推理代码、依赖环境这三个部分用同一套环境配置来约束,能免掉后面一大堆环境问题。
最后聊点实际感受。这套系统从零到基本可用,我花了大概两个月。训练和调参加起来不到两周,大部分时间耗在了数据采集一致性、标注返工和部署链路这些问题上。模型选型本身不是瓶颈,真正拉开差距的是数据规范性和系统兜底能力。如果你准备做类似项目,我建议在最开始就搭建一套完整的数据采集标定流程,宁可多花两周把数据侧做好,也不要后期反复返工。产线上只看最终漏检率和误检率,这两个数字背后,绝大多数是数据与工程的问题,而不是模型结构的问题。