AeBAD航空发动机叶片异常分割数据集:从labelme标注到模型训练实践

发布时间:2026/10/19 9:05:00
AeBAD航空发动机叶片异常分割数据集:从labelme标注到模型训练实践
开局先说一个我自己的经历。接触AeBAD航空发动机叶片异常识别分割数据集之前我正在做一个发动机孔探图像的自动标注项目手里攒了几百张从内窥镜和工业相机拍下来的叶片照片想训练一个能自动圈出裂纹、缺口的模型。最开始我用目标检测的思路做矩形框倒是能标出来可裂纹是细长的、缺口是不规则的矩形框里一半都是背景模型特征学得很懵精度始终上不去。后来我把标注方式换成分割以一整套labelme格式的航发叶片异常数据集重新训练情况立刻不一样了。这篇就来聊聊AeBAD这类图像分割数据集从数据整理、标注规范到喂给模型训练的完整过程适合正在做工业缺陷检测、医学图像分割、或者刚接触labelme格式想入手分割任务的朋友参考。1. 数据集定位1149张分割图为什么值得关注1.1 叶片异常检测的行业痛点航空发动机叶片长期处在高温、高压、高转速的环境里产生裂纹、缺口、磨损这类异常几乎是必然的。检修环节最依赖的手段之一就是孔探检查也就是把内窥镜伸进发动机内部让维修人员盯着屏幕判断叶片状态。这个工作非常吃经验同一个缺陷有人判断是裂纹有人认为只是表面烧蚀痕迹误判带来的后果要么是过度换件增加成本要么是漏检带来安全隐患。我接触过的很多维修资料里对叶片异常的描述都非常依赖文字和少量典型照片实际孔探图像的角度、光照、油污覆盖情况千差万别靠人眼比对很吃力。这时就需要一个能自动把异常区域“抠”出来的模型。但要训练这种模型首先得有人把异常区域精确标注出来。AeBAD这类数据集的稀缺性正在于此——它提供了1149张已完成像素级标注的航发叶片图像并且标注格式直接是labelme格式拿到手就能用于训练分割模型。1.2 分割和分类、检测的差别在哪里用通俗一点的话说分类是回答“图上有没有裂纹”检测是回答“裂纹在哪里用框框住”而分割是回答“裂纹的每一个像素在哪”。叶片缺陷恰恰需要第三层答案一则因为裂纹和缺口形状极不规则矩形框的定位误差太大二则因为后续如果要计算缺陷面积、长度、宽度只有像素级的分割结果才能支撑量化判断。这个数据集把任务定义成了4类别的分割问题也就是每个像素要么属于正常的叶片区域要么属于某一种异常类别。在实际项目里我通常还会把背景单独列一类这样模型在训练时才能区分“叶片本身”和“背景环境”。如果你看过labelme的json文件会发现里面记录的正是每个目标的多边形轮廓点集这就是最原始的分割标注来源。1.3 4个类别的划分思路按常见实践推断标题明确了4个类别。从航发叶片异常的类型分布来看比较合理的划分是正常、裂纹、缺口、磨损/腐蚀这几类。这里我按自己做缺陷分割的惯例列一个对应表实际项目里类名可能略有差异类别典型形态标注时的几何特征主要难点正常叶片基体、无缺陷表面大面积连续区域往往作为背景中的目标主体边缘反光会造成误割裂纹细线状、树枝状、断续延伸长宽比极大像素宽度窄需要放大标注容易和划痕、拉丝纹混淆缺口/崩角叶片边缘的月牙形或锯齿形缺失沿轮廓凹陷主要出现在前缘、后缘边界不清楚需人工判断真实边缘磨损/腐蚀片状、斑块状表面材质退化面积偏大纹理与正常区域接近颜色变化轻微对比度低我在实际标注时会把“正常”类定义成叶片本身的全部区域而不是“不含异常的背景区”。这样分词的面不会重叠模型理解上也更清晰。假如你是拿到数据集的那一方建议第一时间查看json里的label名称和我的上述推断是否一致再决定训练时的类别映射关系。2. 从原始图像到labelme格式一次完整的标注工作流2.1 数据来源与筛选原则航发叶片异常数据集的原始图像来源常见的有两类一类是孔探设备拍摄的视频帧这类图像通常带有鱼眼畸变、光照不均、油污和金属反光另一类是叶片从发动机上拆下后在实验室用工业相机拍的画质更干净但缺陷形态和原位状态有差异。我们团队做那个模拟项目时拿到的原始图像大约是1300多张最终只保留1149张进入标注。筛选原则有三条第一是画面清晰度叶片主体模糊的帧直接舍弃第二是异常可见性如果叶片上存在明显缺陷但是被油污大面积遮盖、人眼都无法判断边界这类图保留价值低因为标注员只能靠猜第三是多样性同一个叶片的不同角度、不同光照、不同缺陷程度都要有代表避免数据集中在某几类相似画面上。这里建议后来做同类项目的人注意数据集数量固然重要但“每一类异常在构图、光照、缺陷尺度上尽量有覆盖”比单纯追求张数更重要。2.2 labelme工具的配置与标注约定labelme是图像标注的老牌工具了安装很简单Python环境下直接安装启动即可。它的优点在于标注结果以JSON保存里面记录的是每个多边形的顶点坐标和标签名既方便人工复查也方便后续转换成COCO、VOC或者其他训练格式。我的标注约定是这样的标注文件命名和原图保持一致例如blade_001.jpg对应blade_001.json。所有异常类别都用多边形勾勒不允许用矩形框代替。裂纹类标注时给每条裂纹单独建一个多边形不要把所有裂纹合并成一个对象。正常区域同样需要标注用较大且尽量贴合叶片轮廓的多边形表示。每张图至少由一名标注员完成初标再由另一人复核。对裂纹这种细长结构labelme的放大模式下逐点描边非常耗时但这一步不能省。因为后续训练分割模型时多边形越贴合真实缺陷边界模型的像素级精度就越高。我在实际标注中会用labelme的“编辑多边形”功能对裂纹的每个转折点进行微调虽然慢但效果远好于快速圈一圈完事。2.3 标注质量控制的三道关卡标注质量直接决定数据集的可用性。我们在流程里设置了三个关卡第一关是“复标”同一张图由两个不同标注员分别标注然后比较两个版本的重合度。这里不是简单看面积交并比而是重点检查裂纹、缺口这些细碎轮廓是否都覆盖到。第二关是“抽检”由项目负责人按比例抽样把标注多边形叠加在原图上逐张肉眼检查边界是否明显偏离真实缺陷。第三关是“数据一致性”检查用脚本统计所有JSON文件看看是否存在空标注、标签名拼写不一致、多边形顶点数异常少这类问题。我遇到最多的问题是标注员对“磨损/腐蚀”这类缺陷的边界判断不一致。正常区域和磨损区域往往没有明显分界线是渐变过渡的两个人框出来的范围可能差很多。这种情况我们最终靠“以可见纹理变化区域为边界”这个统一标准来约束并且在标注手册里贴了典型示例图。2.4 labelme文件的典型结构与转存检查拿到一个labelme格式的数据集你首先要能看懂JSON的内部结构。典型长这样{ version: 5.2.1, flags: {}, shapes: [ { label: crack, points: [[x1,y1],[x2,y2],...], group_id: null, shape_type: polygon, flags: {} } ], imagePath: blade_001.jpg, imageData: null }拿到手后建议写一个快速脚本逐张读取JSON并输出每个文件名对应有哪些标签、各标签多边形数量、平均顶点数。这一步能提前发现很多坑。我那个项目就遇到某几张图的points坐标异常超出图像尺寸这是标注过程中误操作导致的如果不检查训练时程序就会直接报错或生成错误的掩膜。3. 从JSON到训练掩膜格式转换与验证细节3.1 为什么最好不要直接用labelme的json训练主流的图像分割框架比如MMSegmentation、PaddleSeg或者自己写PyTorch训练循环都不会直接读取labelme的JSON文件训练通常需要转成更高效的数据格式。最常用的做法是把JSON转换成COCO格式的标注文件或者转换成每张图对应一个PNG掩膜图的“图片-掩膜”结构。我偏好掩膜方案把每个JSON里的多个多边形分别填充成不同灰度值一个异常类对应一个像素值比如裂纹像素值1、缺口像素值2、磨损/腐蚀像素值3、正常区域像素值4背景像素值0。这样做的好处是训练时数据读取非常直观配合数据增强也方便。转换时需要注意不同多边形的填充顺序不能覆盖尤其是裂纹穿过磨损区域这类叠加情况需要用覆盖策略要么禁止多边形相交要么在标注规范里定义好优先级。3.2 掩膜生成的核心代码逻辑如果你自己写转换脚本核心步骤大致是这样的先读入JSON再创建一个和原图同尺寸的全零数组遍历shapes用cv2.fillPoly把每个多边形的内部填充成对应类别值。下面是我常用的一个简化版本你可以直接参考import json import cv2 import numpy as np def labelme_to_mask(json_path, image_size): with open(json_path, r, encodingutf-8) as f: data json.load(f) mask np.zeros((image_size[0], image_size[1]), dtypenp.uint8) # 类别到像素值的映射按实际情况调整 label_to_value { normal: 4, crack: 1, notch: 2, wear: 3 } for shape in data[shapes]: label shape[label] value label_to_value.get(label, 0) if value 0: continue points np.array(shape[points], dtypenp.int32) cv2.fillPoly(mask, [points], value) return mask转换完成后一定要做一次“反向验证”把生成的掩膜叠加到原图上肉眼抽查几十张。我在这里栽过跟头有一张图像某个多边形的顶点顺序异常填充出来的区域直接跑到图像外面光看数值检测不出来叠加图一拉出来就发现了。这个问题在工业图像里尤其需要警惕因为很多标注员习惯先画大轮廓再局部微调微调时不小心把顶点拖到边界外是常有的事。3.3 类不平衡的早期发现掩膜生成之后顺手统计一下每张图、每个类别的像素占比。我处理模拟项目X时发现裂纹类虽然视觉上很显眼但像素占比经常不到整张图的1%而正常区域占了70%以上。这种极端的类不平衡会导致模型训练初期直接偏向预测“正常”异常区域全部漏掉。常用的解决办法有三种一是损失函数加权给裂纹、缺口这些小目标类别更高的权重二是采用带权重的采样策略让包含小缺陷的图在训练时更容易被抽到三是对掩膜做形态学膨胀扩大缺陷区域的监督信号。不过第三种办法会模糊边界精度一般不推荐在分割任务里使用我更倾向于用损失函数加权配合困难样本挖掘。4. 用数据集跑通分割模型我的完整实验路径4.1 模型选型先轻后重的策略针对1149张这种中小规模数据集不建议一上来就选特别大的模型结构。我在项目里第一版用的是轻量级UNet结构编码器采用预训练的MobileNetV3参数量小训练速度快能快速验证数据标注质量和整体流程是否通畅。这个阶段如果分割效果尚可说明数据本身没有大问题如果效果差得离谱多半是标注或掩膜转换环节出了问题这时候排查比调网络结构更重要。等第一版验证通过后我再换成带有自注意力结构的模型比如SegFormer或U-Net配合ResNet34编码器进一步拉高分割精度。这样做的理由是工业异常识别项目里时间成本和算力成本都是真实存在的先用小模型跑通、再用大模型提精是性价比最高的路线。4.2 训练配置与关键参数我实际训练时的超参数如下仅供参考参数数值说明输入尺寸512x512保留裂纹细节又不会显存爆炸批量大小8RTX级别显卡可接受优化器AdamW配合warmup更稳定初始学习率1e-4使用Cosine衰减损失函数CrossEntropy 0.5*DiceLoss兼顾像素级分类与区域重叠训练轮数60加了早停验证集指标不再上升就停数据增强随机翻转、旋转、颜色抖动模拟真实拍摄角度变化训练集、验证集、测试集按8:1:1划分划分时要注意按图像而不是按像素划分避免同一张图既出现在训练集又出现在验证集。由于原始图像来自连续视频帧同一个叶片的相邻帧可能非常相似如果随机划分这些相似帧会同时出现在训练集和验证集里看起来验证指标很漂亮但实际上模型有作弊嫌疑换到真实场景就露馅。这里建议划分前先对图像做相似度聚类把相似帧放进同一集合。4.3 评估指标看什么分割任务最常看的是mIoU平均交并比和Dice系数。我那个项目的最终结果大致是这样的正常类mIoU超过0.92裂纹类mIoU在0.68左右缺口类mIoU在0.74左右磨损/腐蚀类mIoU约0.70整体mIoU约0.76。裂纹相对难分割是因为细长结构只要有几像素的偏差交并比就掉得很快这是形态学特性决定的不是模型能力差的唯一原因。另外我特别关注一个容易被忽略的指标过分割率。也就是模型把正常区域误判成异常区域的像素比例。在维修场景里这种假阳性会带来不必要的换件成本甚至让检修人员失去对系统的信任。所以我在部署前会专门统计每个类别预测结果中落在正常区域的比例如果超标就通过类别权重或后处理形态学开运算来控制。4.4 推理时的后处理技巧模型输出的分割图是像素级的类别概率直接取argmax往往存在零散噪点。我的做法是先对预测概率做一次阈值过滤比如只有预测概率大于0.5的像素才认为是异常再对裂纹这类预期连通的小区域做连通域分析去除像素总数少于20个的小块。这一步能明显降低误检率。如果是裂纹还可以利用骨架化提取裂纹长度辅助判断是否需要维修这个下游量化任务就建立在分割结果的基础上。5. 部署前必须知道的边界与坑5.1 光照和清晰度泛化问题模型在数据集自带的测试集上表现不错不代表在现场就能直接用。我遇到过一个很典型的情况训练数据里大部分图像光照均匀叶片表面反光不强但实际孔探画面里常常出现局部高光裂纹会被反光完全掩盖模型输出直接漏检。另外孔探图像的分辨率和训练图的差异也会导致精度下降分辨率降低后裂纹只有一两个像素宽分割效果几乎不可用。对这个问题的应对思路有两条一是在训练阶段加入模拟高光、模糊、低分辨率的图像增强让模型见过这些变化二是在部署环节强制做图像质量判断如果清晰度或亮度不达标直接提示用户重新拍摄而不是硬着头皮推理。5.2 4分类任务中“其他异常”怎么办实际工作中叶片异常不止4类还会有烧蚀、打伤、涂层脱落等形态。一旦模型遇到没见过的异常类型像素级分类器很可能会把这种未知异常硬归到某个已知类别里。我在项目里额外加了一个“未知异常”的处理策略对预测结果做置信度统计如果某个连通域的预测概率整体偏低就标记为“需要人工复核”而不是直接输出某一类别。这本质上是把“硬分类问题”改成“分类加拒识问题”在工业场景里拒识比错判安全得多。5.3 标注噪声对训练的持续影响即便有复标和抽检标注噪声也不可能完全消除尤其是磨损和腐蚀这种边界模糊的类别。噪声体现在训练里就是损失函数在部分像素上反复波动收敛变慢模型边界也就不够锐利。我用过一个小技巧在训练后期冻结主干网络只微调解码器部分并降低学习率这样能在一定程度上抵消个别不规则标注带来的干扰。另一个思路是采用置信度学习统计每个样本对损失的贡献把那些频繁造成异常损失的糟糕标注样本识别出来重新人工检查。6. 数据集复用与扩展的实操建议6.1 在labelme基础上做二次标注如果你拿到AeBAD这类labelme数据集不一定要完全重新开始。我常用的做法是先让现有模型在所有图片上做一次预测然后人工修正预测错误的区域只在局部做多边形调整。这样做比从零标注快很多标注员只需要检查模型标得对不对而不是逐点描边。对于磨损这类大块缺陷这种半自动方式尤其省力。6.2 跨数据集融合与类别对齐航发叶片的拍摄条件相对固定但如果有机会融合多个来源的数据注意先把所有标注统一成同一套类别体系。比如某份旧数据把“缺口”叫“dent”AeBAD里叫“notch”融合前必须建立映射表否则会引入两个同义类标签模型学到的是割裂的特征空间。我建议所有类别名在项目一开始就用英文短词统一管理避免中文标签和英文标签混用带来的编码问题。6.3 从分割结果到量化指标的管线分割本身不是终点。我最终交付的成果里除了输出分割图还额外计算了每个异常连通域的面积占比、裂纹的总长度、缺口的最大深度估计。这些量化指标离不开分割掩膜的准确性所以我会在保存掩膜时保留原始图像元信息比如分辨率、拍摄焦距这样后续计算时才能把像素面积换算成真实物理面积。你可以把这条管线理解成分割模型负责把异常从图像里“抠”出来量化模块负责告诉检修人员“这个缺陷大概多大多长”两者结合才真正构成一个可用的检测工具。我在实际使用AeBAD这一批labelme数据的过程中最大的体会是“标注规范决定模型上限模型结构只是逼近这个上限的工具”。数据集的1149张看起来不算海量但只要保证类别覆盖合理、边界标注准确、训练验证划分合理、后处理贴合场景效果完全可以达到初步辅助检修的要求。最后再说一点拿到任何分割数据集后第一件事永远是写下你自己的数据检查脚本把每张图、每个标签、每个多边形从头到尾过一遍。这一步看起来很初级但它是决定整个项目成败的细节所在。