首页 / 资讯中心 / 文章详情

基于DINO-4Scale的齿轮端面缺陷检测与分类落地实践

基于DINO-4Scale的齿轮端面缺陷检测与分类落地实践 ★ FEATURED ARTICLE
齿轮端面质检是个很典型的“看着简单、落地痛苦”的工业视觉项目。我最近把DINO-4Scale这套检测结构真正跑到了这个任务上目标很直白端面上的划伤、磕碰、锈斑、麻点、裂纹在同一套模型里既给定位框又给分类结果同时保证单件的判定速度能跟上产线节拍。这篇文章把我的完整过程拆出来从方案选型、数据标注、训练配置到部署评估哪些参数是试出来的哪些坑是踩过才明白的都会写清楚。如果你正在做工业缺陷检测、缺陷分类或者想把基于Transformer的检测器落到实际产线上这篇应该能省你不少弯路。1. 项目背后的业务与技术选型1.1 为什么选“检测分类”而不是单纯做图像分类一开始有人问过我你要判断齿轮端面有没有缺陷直接做图像分类不行吗把图扔给一个分类网络输出“有缺陷/无缺陷”不是更简单单独做分类在产线上很难用。因为质量部门不只是想知道“这件货有没有问题”更想知道“什么问题、在哪个位置、面积多大、属于哪种工艺异常”。划伤可能来自上料磕碰锈斑说明防锈工艺失效麻点是材料气孔这些信息直接决定返修方案和工序追溯。分类模型给不了位置也给不了数量而端到端检测器一次推理就同时输出“框类别”下游MES系统直接拿坐标和类别去做判定和溯源。另外一个细节是缺陷往往不是单一出现的。齿轮端面可能同时存在一处磕碰和一片锈斑分类模型在这种“多标签共存”场景下很容易丢信息检测模型天然是多个对象并行输出反而更适合。1.2 DINO对比老检测器优势到底在哪目标检测路线有好几个流派我在这个项目里先做了一轮对比方案优点实际痛点传统CV算法找边缘、阈值分割、形态学可解释性强、无算力依赖端面纹理复杂、光照变化导致阈值极不稳定泛化差YOLO系速度快、部署生态成熟需要anchor调参和NMS后处理密集小缺陷容易漏误检要专门压老DETR系列不需要NMS、端到端训练收敛慢小目标能力偏弱工业数据量少时很难训稳DINO-4Scale收敛快、多尺度特征强、训练对象是“带位置先验的query”显存占用比YOLO大代码和工程化需要自己踩坑DINO全称是DETR with Improved DeNoising Anchor Boxes属于端到端检测器。它最明显的好处是省去了NMS后处理和anchor设计推理管线短一截加了denoising训练机制后收敛速度比老DETR快很多这在工业缺陷数据量不大的场景里非常关键。我们这边最终选择DINO-4Scale是因为它把“训练成本可控”和“端到端检测能力”平衡得比较好。1.3 4Scale的特征尺度够用吗目标检测的多尺度特征图决定了一个模型能“看多细、看多广”。齿轮端面上既有几毫米的细划伤也有覆盖大片区域的锈斑跨度很大单尺度必然吃亏。DINO的4Scale变体在工程上指的是使用四个不同stride的特征层级参与解码器交互分别是stride 8、16、32、64。这个组合在800x800的输入下最小的特征图也有100x100左右的空间分辨率细划伤在这个分辨率下依然能保留足够的特征响应。为什么不直接上5Scale甚至更多因为每多一个尺度backbone输出的特征就要多经过一层映射送进Transformer解码器跨尺度注意力计算量也会涨。工业项目跑在单张GPU上的情况比较多显存和算力都是真金白银。4Scale相对完整金字塔5层来说损失的那部分超高层特征主要影响超大尺寸目标而齿轮端面缺陷几乎不会大到需要stride 128这种感受野所以4Scale在这个场景下是性价比最高的配置。2. DINO-4Scale核心机制它凭什么训得稳、测得准2.1 Query不是玄学而是带位置先验的“锚点”理解DINO要先理解query。老DETR里的query是十几个随机初始化的内容向量模型在解码器里靠注意力机制“凭空”找目标。问题是这种设计收敛太慢在小数据集上表现非常挣扎。DINO把query从“纯内容向量”改成了“位置内容”的组合每个query在初始化时就是一个可学习的anchor box包含一个坐标位置和宽高先验相当于给模型发了一叠“预约登记券”我先大致知道应该去哪里找什么再去和图像特征交互。这个过程可以类比新员工进车间让他完全瞎逛找工具肯定效率低但如果先告诉他“大概在哪个工位、要找哪个形状的扳手”他上手就快得多。齿轮缺陷检测里缺陷位置虽然随机但尺寸分布是有谱的。DINO在训练时会根据数据里的框尺寸统计调整初始anchor分布这种位置先验对工业小目标非常友好。2.2 Contrastive DeNoising把训练变成“做找茬题”DINO在训练时引入了一个带噪对比去噪机制。具体做法是把真实标注框的坐标和类别加噪声制造出“被扰动过的正样本”同时构造一个和真实目标相近但没有交集的负样本让解码器在训练时学会把带噪正样本拉回真实标签同时拒绝负样本。这个机制对缺陷检测的价值很大。工业缺陷样本本来就稀缺单纯靠真实标注去训练每个类别能拿到的监督信号非常有限。Contrastive DeNoising相当于在训练过程中构造了大量“模拟考题”让模型在已有的真实样本上学习到更充分的特征映射。我在实际操作中观察到打开denoising训练的版本比关掉它提前了大概一半的epoch就能达到可用精度损失曲线也平滑很多。2.3 Look Forward Twice每一层都在“回头看”DINO解码器里还有一个容易被忽略的设计Look Forward Twice。常规Transformer解码器是每一层都输出预测但不同层的预测质量差异很大。DINO的做法是让当前层的预测框成为下一层query的锚点位置同时每一层都参与损失计算而不是只监督最后一层。这意味着梯度可以从多个尺度回传模型在训练早期就能获得明确反馈。对类别不均衡问题也有隐性帮助因为每一层都受分类损失监督少数类别的梯度路径不会被深层结构稀释。我在训练日志里看到的GIoU loss和分类loss同步下降基本就是这个机制在起作用。2.4 4Scale多尺度特征是怎么接进Decoder的在实现层面4Scale的特征融合用的是主干网络最后几个阶段的输出。以ResNet-50为例取C3、C4、C5三个阶段的特征再用一个额外的下采样卷积从C5生成更低分辨率的特征四个特征图过一个1x1卷积映射到统一的256通道后平铺拼接成Token序列送进解码器。这里有个实际操作中一定会遇到的坑输入尺寸必须能被所有stride整除否则特征图大小对不齐拼接时直接报错。DINO官方代码虽然做了尺寸校验但如果你自定义了输入尺寸比如为了加快推理用640x640得确认它能同时被8、16、32、64整除。我用的是默认的800x800短边resize这个尺寸本身是四个stride的公倍数所以没有额外麻烦。如果要换成768或者640记得先算一遍。3. 数据与标注缺陷检测项目里最容易翻车的一环3.1 类别划分要“工艺可解释”模型输出什么类别本质上是你标注时就定下的语言体系。如果标注类别和车间工人的叫法对不上模型训练得再好现场人员也不会认可。我做这个项目时和工艺、质检两边反复对了几轮最终把缺陷归成六大类并给每条都写清了形态描述和常见成因缺陷类别典型形态常见成因严重等级划伤线状、长短不一端面光泽变异上料磕碰、砂粒夹带中磕碰伤边角或平面上的块状缺损工序转运碰撞高锈斑黄褐色片状或点状防锈油失效、湿度过大中麻点密集小黑点、表面凹陷材料气孔、铸造缺陷中裂纹细长锯齿状沿晶界走向热处理应力严重多余物粘附在端面的异物清洗残留、毛刺低标注规范里有几条必须写进SOP框要紧贴缺陷实际边界不要习惯性地把整个齿坯都包进去同一片区域出现多个缺陷时按独立目标分别标如果一个目标同时有划伤和锈斑统一归为“主管缺陷”比如划伤上有锈就标划伤避免一个目标被重复赋予两个标签造成训练冲突。这套规则一旦定了就要让所有标注人员严格执行不然后期清洗数据会非常痛苦。3.2 负样本比例必须给足很多第一次做工业缺陷检测的人会忽视负样本觉得“我只要把正样本标好就能学会找缺陷”。但实际上模型要想真正理解“什么是正常”就必须大规模见过“正常”。齿轮端面有磨削纹路、油污残留、光照反光如果负样本太少模型会把所有没见过的表面状态都当成异常产生大量误检。我这边训练集的负样本比控制在25%左右也就是每三张图里有一张是正常的。如果只有正样本验证集上的误检率会非常难看特别是正常品在特定光照下的纹理经常被误报成划伤。后续调阈值的时候负样本还能起到校准作用这个比例建议至少不要低于20%。3.3 数据增强与合成缺陷的尺度和分寸齿轮是回转体零件端面在图像上做90度、180度、270度旋转都还是真实场景这类增强可以放心加。水平翻转、垂直翻转也安全基本不会产生“不可能出现的视角”。HSV增强里的饱和度、亮度扰动同样有效毕竟不同批次工件表面反光度会有差异。但要注意一点随机擦除类增强要慎用。我一开始加了RandomErasing结果模型把端面正常区域擦出来的黑色块当成了麻点缺陷严重干扰判断。真实缺陷样本确实很难凑够不得不做合成。我的做法是从真实缺陷图片上把缺陷patch抠出来用泊松融合贴到正常齿轮端面上贴的位置控制在端面环形区域而不是内孔和齿根处。合成数据占总数据的20%左右比例再高模型会对贴图边界产生偏置训练时会学到“边缘生硬缺陷”这种假规律。合成样本还有一个限制不要用合成的去扩充严重缺陷类别因为这类缺陷一旦漏检就被判定为质量事故最好全部用真实样本训。3.4 光照方案和数据采集要提前锁定这个项目里照明对模型效果的影响比很多人想象中更大。齿轮端面是高反光金属面不同角度光线下划伤呈现的对比度完全不同。我在数据采集阶段同时试了同轴光和低角度环形光最终发现低角度环形光对划伤、磕碰这类有深度凹陷的缺陷更友好而同轴光对锈斑和麻点这种颜色变化型缺陷更清晰。关键点是训练数据的光照条件必须和产线部署时保持一致。如果建模用的光照方案和生产现场实际布置的灯光不一样模型学到的是“特定光照下的缺陷外观”到现场就会明显掉点。最保险的做法是产线先确定光源和安装高度再按照同一套配置拍摄训练数据宁可后补数据也不要中途换光。4. 训练配置与实操过程4.1 环境准备与数据格式转换DINO官方仓库基于PyTorch我用的版本是Python 3.8 PyTorch 2.x CUDA 11.8单张24GB显存的卡完全够跑。数据标注工具导出的是标准COCO格式或者自定义JSONDINO训练前要统一转成COCO格式每个标注包含id、image_id、category_id、bbox、area。有一个细节容易被忽略area字段必须和bbox对应很多COCO工具会拿area做一些统计筛选如果填了占位值后面做数据均衡分析时会得到错误结论。类别id从1开始背景对应0。我把六大缺陷类按严重等级排成固定顺序类别顺序尽量别随意调整因为在保存模型checkpoint时类别映射是跟着权重走的中途改id顺序要么重新训练要么写一堆转换代码。4.2 训练参数速查表我最终稳定使用的配置贴在这里给个参考起点配置项取值说明骨干网络ResNet-50用ImageNet预训练权重输入尺寸短边800长边≤1333保证stride 8/16/32/64整除特征尺度stride 8/16/32/64 四层4Scale核心配置隐藏维度256和原论文一致Transformer解码器层数6过深容易过拟合num_queries300缺陷密集时够用优化器AdamWweight decay默认初始学习率1e-4Transformer和neck骨干网络学习率1e-5不能和主学习率一样Batch Size8单卡可跑Epochs100提前看验证集收敛情况Warmup500 iters起步不稳时很有用分类损失Focal Loss处理类别不均衡回归损失GIoU Loss匹配用Hungarian算法刚开始训练时可以把骨干网络冻结5个epoch只让neck和解码器先学。原因很简单预训练骨干已经具备基本特征提取能力上来就全参数微调在小数据量场景下容易把骨干的特征破坏掉导致后面怎么训都回不到最佳状态。5个epoch后解冻全部参数这时解码器已经稳住了局面再让骨干去微调适应齿轮端面的纹理细节。类别不均衡我当时在损失函数上做了加权划伤数量多、权重低裂纹数量少、权重高。权重不是拍脑袋设的而是按训练集各类别样本数的倒数做归一化避免极端放大少数类导致过拟合。4.3 训练过程怎么判断“是不是正常”只盯着总的loss曲线是不够的。DINO训练会有几个分项分类loss、GIoU loss、L1 loss、denoising loss。最健康的信号是GIoU loss和分类loss同时下降如果分类loss降但GIoU loss不动很大概率是匹配器一直在挑容易匹配的样本框的质量没有真正提高反过来GIoU降但分类不动可能是类别混淆在拖后腿。我在训练过程中每隔一定轮数存一次checkpoint并保存可视化预测结果到本地目录。查看的重点是预测框是否紧贴缺陷边界、类别标签是否和缺陷形态一致、有没有把加工纹理误认为缺陷。这一步非常关键因为loss曲线只能告诉你“整体在收敛”不能告诉你“模型看的是不是对的信息”。半精度训练建议打开显存能省将近一半推理速度也更快。但要注意如果训练过程中出现loss变成NaN优先排查是不是半精度混合训练梯度溢出我最终的办法是先退回FP32跑10个epoch确认没问题再开混合精度。4.4 推理部署与产线对接训练好模型以后导出推理图时要把输入尺寸固定下来不要沿用训练时动态resize。DETR系推理没有NMS直接根据置信度阈值取topK个预测输出输出数量就等于num_queries。把这个固定成300个候选再从里面按阈值筛选这样做的好处是推理时延稳定不会出现某些复杂图上目标多导致计算波动。我导出ONNX后用TensorRT做了FP16优化单张800x800的推理耗时在单卡上大约90ms左右算上前后处理和业务逻辑单件控制在200ms内完全能满足产线节拍。如果产线上对延迟更敏感可以把输入降到640x640再量化一次但小缺陷的召回会有一点损失trade-off要自己掂量。推理结果我最终输出成一个JSON结构包含缺陷类别、置信度、框坐标传进MES系统。这里有一个规范建议框坐标统一用像素坐标不要用归一化后的坐标因为现场不同工位相机分辨率可能不一样像素坐标更直观排查问题也方便。5. 效果评估与常见问题速查5.1 指标不能只看mAP现场要看过杀率和漏检率学术指标mAP0.5:0.95在模型选型时有用但工厂只看两个指标漏检率和过杀率。漏检是缺陷品被判定为合格这是质量事故过杀是合格品被判为缺陷这是产线产能损失。这两个指标和置信度阈值直接相关不能拍脑袋定。我的做法是拿验证集做置信度-指标曲线把阈值从0.1到0.9按0.05步长扫描画出漏检率和过杀率随阈值变化的曲线再结合产线对两类损失的不同容忍度选阈值。例如严重缺陷裂纹漏检容忍度为零那阈值就得放低哪怕多来一两个误检也可以接受普通划伤稍微漏掉一点边缘情况可以忍阈值可以适当抬高。每类缺陷单独定阈值不要所有类别共用一个值这样能把过杀率压到最低。5.2 常见问题速查表现象常见原因解决方向训练前几十个epoch不收敛学习率太高或太低、warmup没开先调回1e-4开500 iters warmup正常齿轮被大量误检负样本比例不足、阈值过低负样本加到20%以上用验证集扫描阈值细小划伤漏检增强过度、输入尺寸太小、特征尺度不够检查RandomErasing考虑输入从640提到800裂纹被分到划伤标注口径不统一、两类在局部表观相似重标数据集考虑合并为更高层级的“线性缺陷”推理时显存溢出batch size太大、输入分辨率过高固定输入尺寸用TensorRT FP16导出ONNX后结果和PyTorch不一致动态shape、坐标预处理未对齐固定输入尺寸统一图像归一化参数5.3 独门经验先跑基线再谈优化我在这个项目上最深的体会是不要一上来就调各种花哨策略。先关掉所有增强用最朴素的配置跑50个epoch出一个基线把预测框可视化看一遍。基线的目的不是追求最好精度而是给你一个正确的参照系。后续每改一个策略比如加合成数据、调类别权重、换4Scale配置都能明确知道这个改动到底是正向还是负向。我见过太多人改了一堆东西模型最后看不到一个干净的对比实验出了问题根本没法排查。另外一个经验是每迭代一轮数据清洗精度都会有明显提升。那些标得不够贴边的框、漏标的小缺陷、标错的类别对端到端检测器的伤害远大于普通分类网络。花两天时间清洗标注效果胜过加两周的训练时间。6. 项目落地后的思考这个项目做完后我个人的一个判断是DINO-4Scale这类结构在工业缺陷检测场景里还有很大空间但真正决定项目成败的已经不是模型结构本身而是数据标准化程度、照明方案和评价指标是否对齐。有一个后续方向我很推荐把每个缺陷的类别、坐标、置信度汇总成缺陷分布报表反过来对齐到工序参数上。比如某批次裂纹率上升就去看热处理曲线和设备状态某工位划伤增多就去看转运路径上的工装夹具。模型带来的不只是“质检自动化”更是给工艺改进提供了数据入口。如果你正在做类似的项目建议记住一条先锁光源再谈模型先订标注口径再谈增强先跑基线再谈优化。这套顺序走顺了缺陷检测项目的落地成功率会高出很多。
阅读完成 · 觉得有帮助?
咨询建站