做工业AI质检一年多,我越来越觉得飞机表面缺陷识别是计算机视觉里最考验工程能力的落地场景之一。这几天在整理第10618期飞机表面裂痕识别yolo数据集时,我一边跑着训练,一边在想:为什么这类工业零部件自动化质检项目在论文里总显得很完美,到了现场却问题不断?模型结构不是秘密,公开代码一大把,真正的门槛其实全藏在数据组织、标注规则、部署链路这些没人愿意细讲的环节里。这篇内容我会完整拆解一套飞机表面缺陷识别项目的落地过程,包括数据集怎么整理、模型怎么训练、产线怎么部署、以及我实际踩过的几个大坑,适合刚接触工业视觉,或者正打算用yolo做缺陷检测的工程师收藏。
1. 飞机表面到底有哪些缺陷类型,为什么它们这么难识别
1.1 从蒙皮裂痕到铆钉区域损伤:工厂里最常见的几类表面缺陷
飞机表面缺陷识别这几年的热度一直很高,核心原因不难理解:民航客机、通航飞机的机体常年承受气压变化、气流冲击和温差循环,蒙皮、翼面、舱门周边的表面状态直接关系到飞行安全。一架飞机一次定检要拍上万张高清照片,靠人眼逐张看,疲劳、漏检、记录不标准的问题很难回避。所以"工业零部件自动化质检"这个方向,飞机表面其实是很有代表性的场景,它既有普通工业视觉的共性难点,又有大尺寸、高反射、缺陷极细微的额外挑战。
从实际巡检照片来看,最常见的缺陷类型大概有六类:
- 裂痕(crack):呈细长线条状,出现在蒙皮应力集中区域、舱门拐角、铆钉连线附近。这是所有缺陷里最考验模型分辨力的类型,因为宽度可能只有0.2毫米。
- 划痕(scratch):深度很浅,有时只是漆层受损,但容易在潮湿、盐雾环境下演变成腐蚀源。
- 腐蚀(corrosion):表面呈粉末状、砂纸状或水渍状,颜色偏灰白或棕红,边界模糊,与正常氧化层很难区分。
- 凹坑(dent):以雹击、地勤碰撞最为常见,表面有局部凹陷但漆层不一定破裂,侧光下才明显。
- 漆层剥落(paint peeling):大片剥落或起皮,视觉特征是边缘不规则的明暗跳变,面积通常比较大。
- 铆钉区域异常(rivet defect):包括铆钉松动、铆钉头缺失、周边蒙皮裂纹,这类缺陷尺寸小、背景复杂,是最容易漏检的一类。
你可能会觉得,这些缺陷看起来各有特征,分类应该不难。但真实拍摄条件下,它们往往并不"醒目"。裂痕细如发丝,漆层剥落的边界和正常漆面在灰度上非常接近,凹坑在正面光源下几乎隐形。所以标题里强调"缺陷类型精准识别",意思不只是识别出"有异常",还要分清是哪一类、有多严重。在我的经验里,分类做得准的前提是训练数据里的类别边界画得准,而这恰恰是很多数据集容易翻车的地方。
1.2 金属表面检测难在光学而不在模型:反光、拉丝纹理与弱对比度
很多刚接触这个方向的工程师容易把问题归结为"模型不够强",然后一路堆参数、换更大模型。实际跑过现场后你会发现,真正的瓶颈往往在成像端。
飞机蒙皮是带曲率的金属表面,在机库灯光或者室外阳光下会产生大面积高光反射。高光区域会把缺陷细节"洗掉",也会因为镜面反射产生和裂纹外观极其相似的线条伪影。另外,蒙皮表面有大量打磨拉丝纹理、蒙皮搭接缝、甚至贴膜边缘,这些都不是缺陷,但视觉上就是一条条线。模型如果没有见过足够的"难负样本",预测时就会把正常的接缝标成裂痕。
这就解释了一个关键问题:为什么飞机表面缺陷识别数据集不能只堆正样本。一份可用的yolo数据集,至少要包含"正常但看起来可疑"的负样本,以及同一缺陷在不同光照角度下的多张照片。我在整理这一期数据时有一个很深的感受:同一道裂纹,平行光照射和侧光照射画出来的标注框,虽然目标位置一致,但模型学到的特征完全不同。工业场景里,光源不固定,你的数据里如果只有单一光源下的图,上线后精度会掉得非常快。
因此,面对飞机表面这类高反光、细线条、弱对比度的目标,正确的思路是先把图像采集方案固定下来,再谈模型。这一条建议应该放到所有技术细节之前。
2. 一份可用的yolo检测数据集是怎么构建出来的
2.1 第10618期数据集的图像来源与类别分布
标题里的"第10618期"是某个系列数据集的期号标识,这种编号体系说明数据集是持续更新的,每一期针对一个细分工业场景。飞机表面缺陷识别这一期,我看到的图像主要来自三类渠道:定检工位的高清相机拍摄、移动式地面成像小车采集、以及无人机绕机巡检抓拍。这三类渠道各有特点。
- 定检工位相机:机位固定,光照相对可控,图像分辨率极高,缺陷细节保留最好,适合做模型的主训练数据。
- 地面成像小车:沿着机身弧面移动,视角变化大,能看到曲面部件的曲面变形,适合提升模型对不同视角的鲁棒性。
- 无人机巡检:距离远、速度快,图像分辨率会下降,但胜在覆盖面积大,适合发现明显的漆面损伤和凹坑。
在整理数据集时,三者比例需要刻意控制。如果无人机图占比过高,细裂痕样本就会被大头照淹没,模型对细小缺陷的召回率上不去。我一般建议:固定工位高清图占50%-60%,地面小车图占30%左右,无人机图占10%-20%。这样训练出来的模型在远中近不同采集尺度下都还有一定泛化能力。
从缺陷实例数量上看,裂痕和划痕因为外观相似、样本量通常最大,腐蚀次之,铆钉区域异常最少。类别不平衡是这个任务里逃不掉的问题。另外还有一点务必留意:很多公开数据集的"图片数量"看起来很大,但实际上同一缺陷被多角度重复拍了十几遍,真实的独立缺陷实例可能只有几百个。看数据集质量别只看张数,要看类别实例的多样性。
2.2 标注规范:细长裂痕的bbox怎么打才不浪费样本
这一节可能是最枯燥但最影响模型上限的部分。YOLO系列数据集默认以水平矩形框保存目标位置,而裂痕是细长条,这带来一个麻烦:水平框里大部分面积是背景。
举个例子,一道长30像素、宽3像素的裂纹,它的最小外接水平框面积是90像素左右,但裂纹实际只占框内面积的十分之一。模型在训练时会被迫去学"框内什么特征代表缺陷",如果标注不一致,有的框贴着裂纹画,有的框把周围的阴影、蒙皮纹理也圈进来,那么同一个类别在模型看来就是两种目标,精度必然打折扣。
我的实操建议分三步:
- 优先对细长裂痕使用旋转框标注。新版YOLO都支持OBB格式,如果推理链路不复杂,值得为裂痕单独走旋转框通道。水平框对细长目标的宽度信息完全浪费,旋转框能让模型学到"方向"这个关键特征。
- 如果团队工具和推理代码只支持水平框,那么不要强行让框贴紧裂纹,而是把包含裂纹的区域按固定比例适当外扩,并且所有标注者遵守同一外扩规则。一致性比贴合度更重要。
- 对特别细且长的裂纹,先把原图按滑窗切块放大,再在放大图上标注。这样能避免标注人员因为看不清边界而随手画框,也能让训练阶段直接获得高分辨率小图,不会因为resize把裂纹细节抹掉。
这里还要提一种特殊情况:一道裂纹跨过蒙皮接缝或者铆钉,视觉上被"切断"。原则上应该标成两个独立目标还是一个整体?我的经验是:如果视觉上明显被结构线断开,就标成两个框;如果只是灰度变化但连续性明显,就标成一个框。这类判断标准必须写进标注规范,不能靠标注员临场发挥,否则后期清理数据的成本比重新标注还高。
2.3 train/val切分与数据增强:别把验证集也一起做增强
数据准备好之后,切分策略也要动脑子。如果只是随机按train/val等于9:1切分,很容易出现同一个缺陷在不同角度、不同光照下的多张图同时跑进训练集和验证集,导致验证指标虚高,上线后被现实教育。
我更推荐的做法是按拍摄对象分组切分。例如把所有属于同一个飞机部件、同一次巡检的图像放在同一个group里,然后按group来划分train/val/test。这样验证集里的缺陷都是模型没有见过的拍摄实例,mAP才能反映真实泛化能力。很多团队忽略这个细节,最终模型在自家测试集上mAP很高,去了现场却掉得一塌糊涂,原因就在这里。
至于数据增强,很多人习惯把增强一股脑套在所有图上。这里有一个非常常见的错误:验证集和测试集不应该做随机的几何增强,尤其是裁剪、旋转、翻转这些操作会破坏真实推理时的空间语义。增强只作用于训练集,验证集只做尺寸resize和归一化,这样才能保证评估结果可解释。
对飞机表面这一类数据集,我常用的增强组合是:小角度旋转(±10°)、水平翻转、HSV色域扰动、轻微的仿射变换,以及针对细长目标的copy-paste。Copy-paste对缓解小样本类别不平衡特别有效,它把"正常表面 + 已知缺陷"的组合扩展得非常多,而飞机表面大量区域是干净的,贴上去几乎没有违和感。我所见到的很多项目,仅仅把copy-paste加好,细小裂纹的漏检就有明显下降。
3. 用yolov8训练裂痕检测模型的关键参数与调优实测
3.1 模型选型:为什么我选了yolov8而不是v5或v7
在确定数据集之后,模型选型很容易陷入"哪个版本分数高用哪个"的误区。以我自己的对比测试来看,YOLOv5、YOLOv7、YOLOv8在同一个飞机表面缺陷数据集上的mAP差距大概在1-2个百分点之间,真正拉开差距的是部署便利性和生态完整度。
我最终选了YOLOv8的nano和medium两个尺寸,原因有三个:
- 官方维护的代码库提供OBB检测头,细长裂纹的旋转框方案可以直接用,不用自己改模型结构。
- 导出链路成熟,torchscript、onnx、tensorrt一路走下来很少出问题,工业项目里调试时间比好奇心珍贵。
- v8的C2f结构在小目标上的表现整体优于v5的C3,对0.2毫米宽度的裂纹更友好。
如果团队里已经有成熟的v5推理框架,其实没必要为这几条强行迁移。模型只是链路中的一环,数据质量、后处理逻辑、反馈闭环对最终效果的影响更大。我在选型阶段做过一张粗略对比表,供参考:
模型 | 参数量 | 640x640输入推理耗时 | mAP50(同验证集) YOLOv5s | 7.2M | 约4ms | 0.79 YOLOv8s | 11.2M | 约6ms | 0.81 YOLOv8m | 25.9M | 约11ms | 0.84
这里mAP的绝对值跟数据集有关,不用纠结具体数字,重点是s和m之间的差距并没有想象中那么大,但推理耗时差距却是实打实的。所以工业项目里,我一般建议先用s跑通整个链路,交付演示时如果精度不够再换m,而不是一上来就猛上大模型。
3.2 训练参数与loss曲线的真实读数
训练参数上,我给出自己实际跑过的一套基线配置,这套配置在类似工业表面缺陷数据集上都可以作为起点:
表:YOLOv8m在飞机表面缺陷数据集上的基线配置
超参数 | 取值 | 说明 imgsz | 640 | 输入尺寸按切块图设定,不直接喂原始大图 batch | 16 | 根据显存大小调整,过小会导致BN统计不稳定 epochs | 100 | 前期mAP50在40轮后仍缓慢上升,100轮比较稳妥 optimizer | SGD | 数据量中等时SGD的收敛稳定性比AdamW好 mosaic | 1.0 | 训练中期保持开启,最后5轮建议关闭 copy_paste | 0.3 | 针对细长缺陷的增强概率 hsv_h / hsv_s | 0.015 / 0.5 | 模拟不同光照条件
loss曲线怎么读,比调参本身更重要。很多人只盯train_loss下降,却忽略val_loss的转折点。以我最后训练的模型为例,训练到第55轮左右val/box_loss开始出现轻微回升,val/cls_loss还在继续降,这个时候我选择在第60轮截断,用best.pt而不是last.pt。如果不做这个截断,mAP会出现几个百分点的回退。
另外,如果val上的precision很高但recall很低,说明模型越来越保守,只挑置信度最高的区域输出。这时候不要急着加数据,先检查是不是默认阈值太高,或者是增强太激进导致目标被切碎。这类问题在细裂痕任务里尤其常见,因为裂纹本身细,mosaic增强一旦把一个框切掉一半,模型就会学习到"残缺目标",推理时反而漏掉完整裂纹。
3.3 针对小目标裂痕的增强与推理策略
飞机表面的原图动辄几千万像素,不可能直接输入模型,所以数据环节要做切片,推理环节也要做切片。这里的关键是"切片重叠",而不是简单地把大图均匀切成不重叠的小块。
我用的方案是:把单张原图按512x512窗口滑窗切割,步长取256,即50%重叠。这样一条跨在切割边界上的裂纹,至少会在两张相邻切片里以完整形态出现一次。推理时,把相邻切片的检测结果映射回原图坐标,再用NMS合并跨切片的重复框。这个方案的代价是推理时间成倍增加。
如果产线要求单张图检测时间控制在2秒以内,就要认真权衡切片窗口大小和步长。我实测的经验是:窗口保持512或640不变,步长从50%降到30%,大图上的召回率会下降约5%,但推理时间能省掉大约35%。具体怎么取舍,取决于现场对漏检的容忍度。飞机表面这种场景,我倾向保留更高的重叠比例,因为漏一道裂纹比慢0.5秒严重得多。
对于铆钉区域异常这类小尺寸缺陷,还有一个实用技巧:先在整张低分辨率图上跑一轮粗检,找到铆钉区域的疑似位置,再对对应的高分辨率区域做第二轮细检。这本质上是一个级联检测,不需要额外训练模型,只需要在推理代码里加入ROI裁剪逻辑,效果比纯粹堆算力好得多。
4. 从数据集到自动化质检产线:推理部署与人工复核闭环
4.1 真实产线的图像采集与裁剪流程
模型在笔记本上跑得好,和产线上稳定跑,完全是两回事。飞机表面自动化质检的部署,我建议先画清楚物理流程,再写代码。
一个典型流程是这样的:成像设备完成拍摄后,原始图像会先经过预处理模块,做颜色校正、裁剪掉非机体区域、统一分辨率,然后进入检测服务。在这个环节里,有几个容易踩的坑:
- 非机体区域没裁掉。背景里的工具箱、地面标线如果进模型,推理时会消耗大量算力,还可能被误检成凹坑。简单做法是先用蒙版把机体区域mask出来,标注数据时也同步生成这张mask。
- 图像存储格式不一致。PNG和JPEG同一批次混用,会导致局部纹理差异,模型在JPEG压缩痕迹比较重的图上性能下降明显。尽量统一成PNG,或者统一压缩质量。
- 光照动态变化。机库门口和停机坪的光照差异非常大。我在预处理中加了简单的灰度直方图匹配,把每张待检图的亮度分布拉齐到训练集的平均水平,这个小处理让推理阶段的误报率下降了不少。
硬件选型方面,如果用GPU推理,一张800万像素的大图,做过50%重叠切片后大约等效于30次640输入。假设单次推理耗时6ms,加上IO和预处理,单张大图总耗时能控制在0.5秒左右。如果用CPU推理,时间会拉长到3-5秒,如果产线节拍是一分钟检一架次,勉强能用;如果要求连续快速过检,还是建议上GPU或者边缘加速卡。
4.2 推理阈值、NMS与误报控制
推理时的置信度阈值不能一成不变。飞机表面缺陷识别里,缺陷漏检的代价远大于误报,所以现场的置信度阈值通常要定得比训练时低一些。我在自动化流程里设置了三个档位:
- 置信度大于0.8:直接判定为缺陷,触发检修工单。
- 置信度在0.4到0.8之间:标记为疑似缺陷,进入人工复核队列。
- 置信度低于0.4且面积很小:不输出,但记录日志,用于后续难例分析。
NMS的IoU阈值也要针对细长目标单独调。裂纹是两个相邻框时,普通NMS可能会把同一道裂纹的两个片段合并,也可能把两条相距很近的平行划痕错误合并成一条。经验上,IoU阈值设在0.45左右比较中庸,但必须在现场数据上多测几次,不同拍摄角度下的最优值变化很大。
还有一个容易被忽略的细节:同一道裂纹在不同切片重叠区域被检出时,坐标映射回原图后可能偏移几个像素。合并逻辑不能只看IoU,还要看边界框的中心点距离和长宽比相似度。我最终实现的是一个简单级联匹配:先按类别过滤,再按IoU合并,最后用中心距离小于20像素且长宽比误差小于30%的条件做一次兜底合并。这样既能消除重复框,又不会把相邻缺陷误合成一个。另外还可以按类别单独设置输出阈值,细裂纹和凹坑的置信度分布差异很大,全局阈值往往顾此失彼。
4.3 人机协同闭环:低置信度结果怎么回流再标注
自动化质检可以做到"大部分缺陷机器判断,小部分缺陷机器怀疑、人工决定",但千万不能做成"机器出结果就完事"。
我比较推荐的做法是:把每天的低置信度结果和漏检案例汇总,交给复检人员快速标注或驳回,然后定期把它们补充进训练集。这个回流闭环,比单纯调阈值更能长期提升模型效果。因为现场的缺陷形态会随季节、航线、维护方式变化,只有通过回流才能让模型跟上真实分布。
具体执行时,回流数据不要一股脑全塞进训练集。先做一个简单聚类,把重复的相似样本剔除,只保留新的缺陷形态和新的背景形态。不然训练集会快速膨胀,训练时间翻倍,精度却不一定增长。我一般按两周一个周期做一次回流,每次新增样本控制在原训练集的5%-10%,效果比较稳定。如果一个批次里新增的负样本特别多,还要注意重新做类别平衡,否则模型会被某个容易识别的背景模式带偏。
5. 我踩过的坑:金属反光、小目标漏检与标注不一致
5.1 伪缺陷是怎么被当成真缺陷标注的
这一节写出来,可能很多做过工业检测的人都会会心一笑。我第一次做蒙皮数据标注时,模型训练完在验证集上mAP50高达0.93,自己还挺满意。结果拿到现场实拍图一测,模型对着一大堆"裂纹"框直发愣:那些全是蒙皮高光反射和打磨拉丝造成的伪缺陷。
问题出在两个方面。一是数据里把"疑似裂纹但实为反光"的负样本标成了正样本;二是训练集里大量正常蒙皮图片没有参与训练,模型完全没有见过"正常但有反光"究竟长什么样,自然选择把反光线条当作目标。这也是为什么我前文反复强调负样本的重要性。
事后我重新梳理了标注规范,专门加了一个"反光伪影"类别。这个类别在推理时不参与告警,但可以让模型学会"把这些区域归为背景",效果比单纯删掉负样本好得多。同样的思路也可以用来处理蒙皮接缝、贴膜边缘、漆面正常纹理等易混淆区域。如果你在训练中遇到莫名其妙的误报,先别急着调阈值,回去看看训练集里有没有足够的"像缺陷却不是缺陷"的样本。
5.2 标注一致性与审核机制到底有多重要
标注不一致是一个数据集的慢性病。两个标注员对同一道裂纹,一个框贴得很紧,一个框明显外扩,模型学到的就是同类别下两种不同的形态,最终表现是推理时框的置信度整体偏低,或者检测框飘忽不定。
解决这个问题,不能只靠写规范文档,更要在工具层面做约束。我给团队用的标注环境里增加了实时辅助线,标注时会把接近该类别平均长宽比的参考框显示出来,减少主观差异。另外,每一批标注完成后,我会抽5%-10%的图做交叉验证,计算两个标注员之间框的IoU,低于0.7的直接退回重标。
这套审核机制看似增加了工作量,但实际上节省的调试时间远超投入。一个客观、可量化的标注一致性指标,是你面对模型效果不好时最有用的排查依据。是模型问题还是训练数据问题,很多时候先看这个指标就能判断,不需要反复做实验。
5.3 数据回流:让模型越用越准的长期打法
最后说说长期维护。飞机表面缺陷识别这种项目,几乎不可能一次性交付完。上周的算法可能在新一批机型照片上就失灵,因为漆面颜色、纹理、表面处理工艺都不同。
我现在养成的习惯是:每个新机型或者新巡检任务上线后,先手工跑一遍现场数据,把分布差异大的图像筛选出来,补进数据集的负样本池。具体操作上,我会写一个小工具,用推理阶段的特征向量对现场图做聚类,挑出与训练集分布距离较大的成批图片,这些往往就是最好的新增负样本来源。这个过程不需要很多图,几百张高质量差异样本就能让模型在新环境里的表现明显提升。
我自己长期跑这个闭环的体会是:模型准确率提升80%靠的是最初的数据质量和标注规范,剩下20%靠的是长期回流和阈值调优。如果你正打算做飞机表面缺陷识别或者类似的工业质检项目,我建议把精力优先放在数据采集标准化和标注一致性上,模型选型反而是最不需要纠结的部分。想清楚这一点再去碰yolo,你的第10618期数据集才不会只是躺在硬盘里的又一份数字资产,而是真正能撑起整条自动化质检链路的底牌。