1. 项目缘起产线包装质检中的真实痛点做工业视觉的人大多遇到过这类需求某卷烟厂或印刷厂的包装车间生产线每分钟能过几百个烟盒过去主要靠质检员肉眼抽查漏检率和误判率都让人头疼。烟盒包装上的品牌logo、警示语、条码区域、封口贴位置稍有偏移、缺色、脏点、褶皱就要被判定为不合格品。传统机器视觉方案用模板匹配做对光照变化和烟盒摆放角度极其敏感调一次产线就得重配一次参数维护成本比算法本身还高。我们接到的这个项目目标很明确在尽量不改动现有产线结构的前提下用目标检测模型替代人工目检对进入相机视野的烟盒包装进行实时缺陷识别。所谓香烟包装检测可不只是把烟盒框出来——它需要同时检测出烟盒主体区域、印刷缺陷区域、封口异常区域还要对每个检测框给出分类结果和置信度方便后端机械臂做剔除动作。这里最麻烦的是小目标缺陷比如一条细小的划痕、一个0.5毫米左右的漏白在1280分辨率图像里可能只占几十个像素如果模型不够敏感很容易漏过去。经过一段时间的方案对比最终选定了YOLOv8作为基线模型并在此基础上引入了一个自研的注意力分支模块HAFB也就是高注意力特征分支High Attention Feature Branch。整条技术链路从数据采集、标注、模型改造、训练调参一直做到产线推理部署前后花了大概六周。这篇文章把整个过程复盘一下重点讲清楚HAFB模块的嵌入逻辑和踩坑细节给做工业质检的兄弟们一个可直接参考的实践范本。2. 技术选型推演从YOLOv8基线到HAFB增强的决策过程2.1 为什么锁定YOLOv8而不是YOLOv5或RT-DETR工业项目选型我通常先看三点检测精度是否满足缺陷等级要求、推理速度能否跟上产线节拍、部署生态是否成熟。YOLOv8在这三点上确实均衡得让人没法拒绝。YOLOv8在C2f模块中把梯度流做成了分叉再拼接的结构比YOLOv5的C3模块特征复用效率更高这让它天然适合小目标检测这类需要丰富底层特征的任务。我们用同一批烟盒数据进行过快速对比实验在只调整anchor相关参数的情况下YOLOv8的mAP0.5比YOLOv5s高出了大约2.3个点尤其在条码区域印刷偏移这类需要细粒度特征的缺陷类别上优势更明显。RT-DETR虽然是无anchor方案理论上部署也方便但它对训练数据量的要求偏高我们的缺陷样本总量才一万多张硬上Transformer结构容易过拟合而且TensorRT部署时某些自定义算子支持不完善产线那边的工控机性能有限风险太大直接pass。至于YOLOv8n、s、m、l、x几个版本的选择产线用的是NVIDIA Jetson AGX Orin单帧推理预算大概15毫秒左右这个算力水平下YOLOv8s是最优解精度比n版本高出一个档次速度比m版本快一倍以上。考虑到后面还要挂HAFB分支推理时间会增加几个毫秒所以基线必须留出余量。2.2 HAFB模块的定位不是取代主干而是给主干加一个放大镜最初测试YOLOv8s基线模型时整体mAP到了89.7%看着不错但细看各类别指标就会发现端倪烟盒主体定位这类大目标AP有97%以上唯独封口贴气泡和烫金划痕这两类缺陷AP只有62%和58%。原因不难理解——这两类缺陷面积小、对比度低有些气泡在图像里几乎就是一片模糊的灰阶变化主干的特征金字塔虽然有多尺度融合但在深层特征图上这些小缺陷的信息已经被压缩得所剩无几了。传统做法无非是加检测头、加注意力机制比如给backbone后面接SE模块或者CBAM。这些方法的共性问题在于注意力权重是在主干特征图上直接计算的相当于在已经缩水的信息上面做筛选。我们想要的是在原始分辨率附近额外保留一份高细节信息让模型在判断小缺陷时能回去看一眼原图的纹理细节而不是只依赖于下采样后的特征。HAFB的设计思路就是从这里来的它不是去修改backbone而是在backbone的浅层特征图旁边并行挂一个独立分支用轻量级的自注意力机制保存高分辨率细节再通过一个门控融合单元把这份细节特征嵌入到检测头。类比来说主干网络负责看大局HAFB分支相当于质检员手里拿的放大镜——平时不参与主要判断但一旦需要确认可疑区域它能把细节拉出来供决策使用。2.3 HAFB对推理延迟的影响估算加分支必然带来额外计算量这是绕不开的。我们做设计时提出了一个硬性要求HAFB引入后整体推理时间增幅不能超过20%。以YOLOv8s在AGX Orin上约12毫秒的推理时间计算HAFB的预算只有2.4毫秒。为了达到这个目标分支设计上全部采用深度可分离卷积和共享权重的自注意力特征图分辨率控制在输入图像的1/4即320×320通道数限制在64。实际测试下来完整模型在TensorRT FP16精度下推理时间为14.2毫秒增幅约18.4%符合预期。但要注意如果直接用PyTorch的Eager Mode跑这个数字会飙到22毫秒以上所以部署时必须走TensorRT。这一点后面在部署章节会详细展开。3. 数据集构建工业质检项目成败的真正分水岭3.1 采集方案与样本构成很多团队做算法第一步就栽在数据上尤其是工业场景缺陷样本总是稀缺的。我们这次运气不错合作方过去两年积压了大量人工质检时拍摄的缺陷照片大概有八千多张覆盖了十二大类常见缺陷。但我们没有直接拿这些历史照片训练原因很简单不同时期相机的分辨率、光源角度不一致直接用会造成严重的域偏移。最终的数据采集方案是重新拍摄在产线上搭建了一个固定工位使用1200万像素的工业面阵相机配合两个条形光源形成低角度漫射照明总共拍摄了约一万八千张图像。其中合格品样本七千张缺陷样本一万一千张。缺陷样本的分布刻意做了不均匀处理——常见缺陷如封口错位占多数罕见的如烫金划痕每类只保留几百张这是为了和真实产线的缺陷出现频率对齐同时通过重采样保证模型不会对头部类别过拟合。标注工作用的是某开源的图像标注工具标注类别分为五类烟盒主体cigarette_pack、条码区偏移barcode_offset、封口贴气泡seal_bubble、烫金划痕foil_scratch以及外包装褶皱wrinkle。这里有一个通用做法值得分享对于烟盒主体这一类我们强制要求标注框紧贴烟盒边缘不要留背景空隙。这么做的原因是后续需要利用检测框做透视校正和缺陷定位框太松会把背景算进主体区域导致误检。3.2 数据增强策略的取舍工业缺陷检测里数据增强要非常谨慎。常规的随机旋转90度、水平翻转在我们这个场景中不能无脑用——烟盒上的文字方向是固定的翻转后模型会学到错误的文字朝向先验反而降低真实场景下的鲁棒性。我们最终只使用了三类增强轻微随机平移±5%、轻度缩放±10%以及HSV色域微调其中色相偏移控制在±5度以内避免把烟盒原本的色调改得面目全非。针对小缺陷样本不足的问题我们做了一个看起来很笨但很有效的操作在训练集中对包含气泡和划痕的图像做2×2裁剪把缺陷区域放大后再作为独立样本加入训练。这样做等于在不改变缺陷形态的前提下主动让模型看到更多的放大后的缺陷细节弥补HAFB分支在高分辨率特征上的训练数据缺口。3.3 数据集划分的细节数据划分上我们没有用最朴素的随机划分而是采用了按时间切片的策略把整个采集时间段分成前80%和后20%分别作为训练集和验证集。这是模仿真实上线场景——产线的光照、设备状态会随时间漂移用随机划分得到的验证集会高估模型性能因为同一时间段内的图像高度相似。按时间切片后验证集会包含更多环境变化因素虽然刚开始跑出来的指标会低一些但上线后不会出现测试指标很好看、产线一跑就露馅的尴尬。最终数据集规模为训练集14500张验证集3500张。其中验证集中故意混入了一部分完全合格品用来观察模型的误检率——这一个指标在工业场景中往往比mAP更能反映模型是否可上线。4. HAFB模块的实现细节与嵌入位置选择4.1 模块结构拆解HAFB模块在代码层面分成三个子模块细节保持分支Detail Preservation Branch、自注意力增强单元Self-Attention Enhancement Unit和门控融合单元Gated Fusion Unit。细节保持分支的输入是backbone第二层也就是分辨率最高的那层特征图尺寸为160×160先经过一个1×1卷积把通道数降到64然后连续通过两个3×3深度可分离卷积进一步提取边缘和纹理响应。这个分支的目的说白了就是保留原图级的细节但又不引入太大的计算量。因为只用深度可分离卷积这一段的参数总量大约只有0.12M比主干网络动辄几M的参数小一个数量级。自注意力增强单元是HAFB的核心。对细节分支输出的64通道特征图我们分别用三个1×1卷积生成query、key、value然后做标准的点积注意力。这里的关键trick是注意力计算只在空间维度的下采样版本上进行32×32分辨率算出的注意力权重再上采样回160×160作用于value。这样既能让模型捕捉到划痕虽然小但其周围的纹理结构有特殊性这类全局上下文关系又把自注意力的计算复杂度控制在合理范围。如果不做这个下采样160×160的空间维度自注意力在训练时几乎跑不动。门控融合单元的职责是把增强后的细节特征注入到检测头使用的特征金字塔中。我们选择的注入位置是PANet的P3层对应80×80分辨率因为P3层本身就是负责小目标的检测层把高分辨率细节补充到这一层算是各得其所。融合过程不是简单的相加而是先通过sigmoid生成一个0到1的门控权重再用门控权重对细节特征和原有P3特征做加权求和相当于让网络自己学习什么时候需要放大镜、什么时候不需要。4.2 嵌入YOLOv8的工程实现要点YOLOv8的模型结构在开源仓库里定义得比较清晰改造时只需要修改三个地方前向传播时把backbone第二层特征额外传给HAFB在PANet的P3层输出处接入门控融合单元在yaml配置文件中注册新的模块类方便后续导出模型时被序列化工具识别。这里要特别提醒如果后续打算导出到TensorRT要避免在模块中使用Python原生控制流比如if-then-else否则ONNX导出时会报不支持动态图的错误。我们的门控融合实现里直接用torch.where替代了条件判断这一步看似无关紧要实际上能省掉后面部署时的大量返工。另外一个容易踩坑的点是BatchNorm的同步。YOLOv8默认用的是SyncBatchNorm来处理多卡训练但我们加上HAFB后如果继续使用SyncBNDDP训练时显存占用会暴涨原因是自注意力单元在反向传播时同步梯度的开销很大。实际项目里我们最终放弃了SyncBN改回普通BatchNorm用单卡A100训练batch size设为64并没有发现精度损失。如果你的训练环境本来就是多卡建议先把HAFB的自注意力单元里的归一化层换成GroupNorm这样能避免跨卡同步的通信瓶颈。4.3 为什么选择P3层而不是所有特征层看过一些类似方案的读者可能会问既然细节重要为什么不把HAFB同时注入到P3、P4、P5所有层我们确实试过这种全层融合的做法结果颇为反直觉——精度不升反降。分析下来P4和P5层本身负责中等和大目标烟盒主体这类大目标已经有了足够强的语义特征再把细节特征强塞进去反而干扰了分类头的判断导致烟盒主体AP从97%掉到94%。这说明注意力增强模块不是哪里都能加的必须根据目标尺寸分布来选择注入位置。对于烟盒检测任务小目标缺陷是主要矛盾所以把全部细节特征集中注入P3层是最合理的方案。如果未来遇到缺陷尺寸跨度更大的场景建议的做法是把HAFB的输出先通过一个可学习的权重层分配到P3和P4两层而不是简单复制粘贴。5. 训练过程纪实超参调整与收敛曲线解读5.1 训练环境与基础超参所有实验在一台配置了双路A100 80GB的服务器上进行单卡训练PyTorch 2.0以上的版本CUDA 11.8。YOLOv8s基线权重使用Open Images预训练权重没有从头训练。超参设置上输入图像固定为640×640训练轮数设为200轮。初始学习率0.001采用warmup策略前3轮从0.0001线性升到0.001之后用余弦退火衰减到0.00001。优化器选择SGDmomentum 0.937weight_decay 0.0005。批量大小64对应单卡显存占用约42G恰好在上限之内。需要注意的是如果显存不够优先降低batch size而不是降低图像分辨率——图像分辨率直接决定了小缺陷的像素占比降到512×512会让气泡类缺陷的AP再掉5个点以上。损失函数沿用YOLOv8默认的组合损失分类用BCE回归用CIoUDFL权重设为默认。我们在开跑前最担心的是HAFB的门控融合单元会不会抢主导权导致主干网络训练不充分。实际看了第一个epoch的loss曲线才放心主干部分的loss下降速度跟基线几乎一致门控权重在初始阶段稳定在0.4左右并没有出现一端倒的情况。5.2 训练过程中的关键观察前50轮是最平淡的阶段整体mAP从0缓慢爬升到62%左右此时HAFB的优势还完全体现不出来。转折点出现在第80轮之后基线模型的mAP增速明显放缓而HAFB模型的曲线仍然保持一个较高的上升斜率。这说明HAFB提取的细节特征需要经过一段时间的预热才能让检测头学会如何利用它们。到第150轮时HAFB模型的mAP0.5达到了93.6%比基线YOLOv8s的90.1%高出3.5个百分点。再看各类别AP差距最大的依然是此前让人头疼的烫金划痕类从58%提升到了79.4%封口贴气泡从62%提升到了81.2%。在开销只有18%推理延迟的情况下这个收益足够令人满意。不过有一个数据要泼冷水合格品误检率False Positive Rate从基线的2.1%略微上升到2.4%。原因也很直观——HAFB给模型提供了太多细粒度信息导致一些合格品的正常纹理变化比如包装纸本身的纤维纹路被误判为划痕。这个问题最后是通过调整置信度阈值来压制的具体做法后面再讲。5.3 训练后的过拟合与泛化能力检验工业质检最怕的不是训练集表现差而是训练集表现好得离谱、上线一塌糊涂。所以训练完成后我们没有急着打包部署而是做了一次跨批次验证另外从产线上抽了500张新鲜拍摄的图像涵盖白天和夜晚两种光照条件作为外部测试集。在这个集上HAFB模型的mAP为91.8%相比内部验证集只下降了1.8个百分点说明泛化能力在可接受范围内。最主要的光照落差出现在夜晚批次——工厂的荧光灯在相机里会形成色温偏冷的效果部分气泡缺陷在冷光下对比度更低AP掉了4.6个百分点。后来针对这个问题我们建议产线在相机前加了一块偏振片压制镜面反射缺陷对比度明显回升。6. 实验结果对比与典型误检案例复盘6.1 基线模型与HAFB模型的完整对比为了排除偶然性所有对比实验都跑了三次取平均值。下表列出了在验证集上的核心数据模型mAP0.5烟盒主体AP条码偏移AP封口气泡AP烫金划痕AP褶皱APYOLOv8s基线90.1%97.3%94.2%62.1%58.4%93.8%YOLOv8s HAFB93.6%97.9%95.8%81.2%79.4%95.6%YOLOv8m基线91.4%97.5%94.9%67.7%64.2%94.5%最值得注意的对比是加入HAFB的YOLOv8s参数量约11.2M在整体精度上超过了不加HAFB的YOLOv8m参数量约21.6M而推理速度却快了近1倍。这说明HAFB带来的计算效率远超简单堆叠模型容量。从部署角度看一个更小更快更准的模型意味着产线上只需要一块中端工控机而非昂贵的专业推理卡经济效益是实打实的。6.2 气泡缺陷误判问题从漏检到过度敏感的平衡最初HAFB模型在验证集上有一类特殊的预测错误把烟盒包装覆膜上的不规则褶皱光斑识别为封口贴气泡。人工复查后发现产线上的光源虽然名义上是漫射照明但覆膜的光滑表面在特定角度下仍然会形成局部高光区这种高光区在图像上呈现的纹理和气泡非常相似。解决思路有两个方向一是增加负样本专门采集了大量覆膜高光图像加入训练集二是给HAFB增加一个光照一致性约束做法是在训练时随机把图像的亮度通道做局部扰动强迫模型不要依赖绝对灰度来判断气泡。最终两个方向都做了效果更明显的是第二个方向——增加亮度扰动后气泡类别的误检率降低了接近38%而召回率只下降了1个百分点。这个经验对于所有涉及光滑表面缺陷检测的项目都适用不要让你的模型过度依赖灰度绝对值。6.3 折线图之外的细节检测框质量分析除了mAP指标我还习惯单独看一个指标检测框的边界贴合度用预测框和真实框的IoU分布来衡量。基线模型在烟盒主体这类大目标上IoU普遍在0.88以上但烫金划痕的IoU中位数只有0.71原因在于划痕形状细长矩形标注框很难贴紧。HAFB模型在这个类别上的IoU中位数提升到了0.82推测是因为高分辨率细节让边界回归头更容易定位划痕的起止位置。这个数据提醒我们在做质检类项目时不要只盯着mAPIoU的改善可能意味着后端剔除机构能够更精确地定位缺陷位置减少误切好品造成的浪费。7. 部署落地从PyTorch模型到产线实时推理7.1 模型导出链路的三个关键坑训练完成后进入部署环节这一步才是真正考验工程功力的地方。我们选定的部署路径是PyTorch - ONNX - TensorRT在AGX Orin上以FP16精度运行。第一个坑出现在导出ONNX时HAFB里的自注意力单元包含多处resize操作ONNX导出时这些操作会被拆分成多个子图导致TensorRT解析时无法融合算子。解决办法是在导出前用onnx-simplifier对模型进行图优化把冗余的resize节点合并。这一步不做的话即使模型能跑推理延迟也会从14毫秒飙到27毫秒。第二个坑是FP16精度下的数值溢出。HAFB的门控权重在初始阶段会输出接近0.5的值在FP16下这类小数精度足够但一旦训练完成门控权重趋近于0或1某些极端情况在FP16下会发生精度损失。排查下来发现是Gate输出经过sigmoid后数值非常接近1FP16表示不了足够小的小数增量。最后通过在门控单元前加一个可选的缩放因子固定为0.1将数值拉回安全范围问题解决。第三个坑更隐蔽TensorRT在动态batch模式下会对输入尺寸做对齐处理我们固定输入640×640但推理时图像来自相机是1280×1024分辨率需要先做letterbox。YOLOv8官方仓库的letterbox用的是cv2.resize会把帧率拖慢。我们改成在GPU上用CUDA加速的resize算子配合NPP库整体图像预处理时间从5.5毫秒降到了1.1毫秒。7.2 产线端到端延迟预算最终端到端的处理管道包括相机采集帧0帧延迟用硬触发- GPU预处理 - TensorRT推理 - 后处理NMS阈值过滤- 结果可视化与剔除信号输出。实测在AGX Orin上单帧总延迟稳定在16毫秒左右对应产线最高节拍60帧/秒的相机还有约33%的算力余量。NMS后处理我们直接使用了TensorRT自带的EfficientNMS插件也避免了自定义后处理算子带来的额外调度开销。置信度阈值的最终设定为0.35这是在漏检率和误检率之间反复权衡后的结果。阈值设低到0.25时气泡召回率能到91%但误检率飙到5.2%产线上每天要多废几十个合格烟盒阈值抬高到0.45误检率降到1.5%但漏检率又到了3.4%。最终在0.35这个点取得平衡漏检率1.8%误检率2.0%。这里要特别说明阈值不是固定的应该根据产线当月缺陷率的统计动态调整我们做了一个简单的经验公式当连续三天的平均误检率超过3%时自动上调阈值0.02。7.3 实际产线运行的稳定性记录连续跑了三周约19个工作日模型总共处理了约165万帧图像触发剔除动作3172次其中确认为真实缺陷的有2854次实际准确率90%。模型本身的稳定性也经受住了考验三周内没有出现一次因模型推理崩溃导致产线停机的故障。不过我们注意到一个现象随着产线设备的老化振动相机画面在高频段出现了小幅抖动这导致一部分褶皱缺陷的检测框位置随时间偏移。后续考虑在预处理中加入快速图像配准模块来消除抖动影响不过这是项目二期的事情了。8. 复盘心得做工业视觉检测项目这些教训值回票价整个项目下来最大的体会有三个。第一注意力机制不能迷信。HAFB之所以有效不是因为用了注意力这个事实而是因为它恰到好处地补足了主干网络在小目标细节上的信息损失。盲目堆叠注意力模块甚至到处都插入只会让模型学到的特征越来越钝。我见过很多团队把CBAM、SE、CoordConv一股脑全加进去最后指标不升反降原理跟我们在P4/P5层加HAFB的情况完全一致。第二数据分布决定了模型上限。YOLOv8和HAFB只是把精度从90%拉到了94%但从58%到79%的划痕AP提升一半功劳要记在2×2裁剪增强和光照扰动增强上。算法工程师在工业项目里往往花了80%的时间在调模型结构实际上应该花更多时间去理解数据是怎么产生的、缺陷是怎么形成的。第三部署环节的坑永远比你想象的多。如果你准备做类似的YOLOv8自定义模块的部署一定要在模型设计阶段就想清楚最终要部署到什么平台、用什么推理引擎。我们的HAFB里大量使用resize和上采样操作虽然在PyTorch里跑得很欢快但转换到TensorRT时花费的时间几乎赶上了模型训练的时间。建议后续项目在设计网络时尽可能用部署框架原生支持的算子比如用步长卷积代替上采样能省去大量转换调试精力。第四也是最务实的一点工业项目一定要和现场工程师保持高频沟通。我们最初设计的缺陷类别其实是七类后来现场工程师指出其中两类缺陷在工艺上几乎不可能同时出现合并成一类后不仅模型负担减轻后端的剔除逻辑也简化了很多。这不只是技术问题更是项目管理的经验。如果你正在做类似的质检检测项目希望这份复盘能帮你少走几步弯路。特别是HAFB那种并行分支门控融合的思路不一定要局限在烟盒包装场景任何对细节敏感的目标检测任务都可以借鉴——比如PCB板焊点检测、织物表面瑕疵识别。方法本身不复杂复杂的是把它嵌入到你的数据流、产线节拍和维护节奏里。