做风机巡检的工程师,十有八九都经历过这种场景:无人机飞一圈回来,存储卡里塞了几百张叶片照片,晚上坐办公室一张一张点开看,裂纹、腐蚀、前缘磨损、雷击损伤,看得眼睛快贴在屏幕上。更要命的是,看完还要手动框出缺陷位置,写成巡检报告,一个风场几十台风机下来,胳膊和眼睛一起酸。我一直觉得这事不该这么干,后来在多个巡检项目里反复打磨,陆续整理了一批风力叶片缺陷图像识别数据集,一直迭代到第10077期,同时提供了YOLO格式和VOC格式的标注文件。这篇就把这个数据集背后的设计思路、标注规范、训练实操和踩坑经验一次性讲透,给正在做风电叶片视觉检测、无人机自动巡检、或者刚入门工业目标检测的朋友做个参考。
1. 数据集的设计思路:无人机巡检图像为什么难做成公开数据集
1.1 从“人工看片”到“机器看片”,数据集是怎么被逼出来的
风力机叶片缺陷检测看着是个图像分类问题,实际上链路上的麻烦远超想象。无人机航拍虽然解决了“人上不去”的问题,但每台风机拍回来的照片数量非常可观:一只叶片分前缘、后缘、叶根、叶中、叶尖几个区域,加上不同高度和角度,单台风机就能产出几十到上百张有效照片。一个50台机组的场站巡检完,保守估计有几千张图等着人工判读。
判读人员要在几秒钟内准确找到叶片表面细小的裂纹、砂眼、雷击灼伤点,这对注意力和经验要求极高。疲劳之后漏检率会明显上升,不同人员之间的判读标准也很难统一,同一个缺陷有人标“开裂”,有人标“表面损伤”。数据集最初就是为了解决这个标准问题:把典型缺陷的类型、位置、大小统一框出来,让模型学到一个相对稳定的判读基线。
数据集来源于两部分:一部分是无人机实际巡检拍摄的原始影像,包含不同风机机型、不同飞行高度、不同天气光照下的真实画面;另一部分是对原始大图切片后筛选出的有效样本。相比网上零散爬来的图片,这种数据更贴近真实作业环境,模型在落地时不容易出现“实验室效果好、现场一测就废”的尴尬。
1.2 图像来源与多样性:航拍数据的几个关键变量
航拍巡检图像的难点在于多样性维度太多,每一个维度都会直接影响模型泛化能力:
- 拍摄高度:无人机在25米、50米、80米高度拍摄,同一个缺陷在画面里的大小差异可能达到三四倍,小目标问题在风电巡检里非常突出。
- 拍摄角度:正对叶面、斜侧方、逆光、顺光,缺陷形状和纹理表现差别很大。
- 天气光照:晴天强阴影、阴天均匀光、黄昏低照度,都会改变缺陷的对比度。
- 叶片表面状态:有的叶片刚清洗过,有的积灰严重,灰尘和油污会掩盖细小裂纹,也会带来大量伪缺陷干扰。
- 风机机型差异:不同厂商、不同长度型号的叶片,表面涂装颜色、纹理、logo位置都不同,模型训练时如果机型单一,换一个风场性能下滑会很明显。
这期数据集在整理时特别注意保留了这些变量的代表性,而不是只挑“好看清楚”的图。训练数据里故意放了一些模糊、反光、阴影遮挡的样本,短期看会拖低训练指标,长期看反而提升了模型在不同场站之间的迁移能力。
1.3 为什么同时提供YOLO格式和VOC格式
很多做工程的朋友一上来就问:到底用哪个格式?其实两个格式的内容完全一致,只是组织方式不同。VOC格式是早期检测领域最通用的标注协议,每个图片对应一个XML文件,用xmin、ymin、xmax、ymax记录目标边界框的绝对像素坐标,标签名直接写在标签节点里,人类可读性好,也很适合做数据可视化检查和二次编辑。YOLO格式则是目前主流的训练格式,把边界框归一化到0到1之间,用类别编号加中心点x、中心点y、宽度、高度的组合表示,训练时读入效率高,数据增强也更方便。
我在项目里同时保留两种格式的核心原因,是为了兼容不同的工作流。VOC格式适合老牌检测框架和精细化的标注修正工具,YOLO格式适合直接丢进当前主流的训练管线里跑。对于没有精力写转换脚本的团队来说,拿到手就能用,省掉了格式转换这一步最容易出错的环节。
提示:如果只是做YOLO系模型训练,直接用txt格式就够了。但如果要做可视化分析、手工复核、或接入一些老平台,XML格式仍然是最稳的中间格式。
2. 数据集结构与标注规范
2.1 目录结构与文件组织
拿到数据集后,第一件事是搞清楚目录组织方式。这一期的结构沿用了YOLO系列训练集的标准思路,同时也保留了VOC的完整标注目录:
wind_turbine_blade_defect_10077/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── voc_annotations/ │ ├── train/ │ ├── val/ │ └── test/ ├── classes.txt ├── data.yaml └── README.mdimages目录存放JPEG格式的航拍切片图,labels目录存放对应的YOLO格式txt文件,voc_annotations目录存放对应的VOC格式XML文件。这样设计的好处是,直接用YOLO训练时只需要配置data.yaml路径,做传统检测框架验证时用voc_annotations里的XML也完全不冲突。
2.2 标注字段怎么读,踩过的格式坑
VOC格式的XML核心结构长这样:
<annotation> <filename>blade_0382.jpg</filename> <size> <width>1280</width> <height>720</height> <depth>3</depth> </size> <object> <name>crack</name> <bndbox> <xmin>612</xmin> <ymin>288</ymin> <xmax>734</xmax> <ymax>421</ymax> </bndbox> </object> </annotation>YOLO格式的txt对应内容是:
0 0.525781 0.492361 0.095313 0.184722这行数字的含义是:类别编号0,边界框中心点x坐标归一化到0.5258,中心点y坐标归一化到0.4924,框宽度归一化到0.0953,框高度归一化到0.1847。归一化方式是把像素值除以图像宽度或高度,而不是除以最大边长,这一点最容易搞混,写转换脚本时一旦除以了错误的尺度,训练时错得无声无息,损失曲线看起来正常但mAP永远上不去。
2.3 识别类别怎么定义才实用
这期数据集一共定义了五类缺陷,都是风电叶片巡检里出现频率高、维修价值和安全性影响比较大的类型:
| 类别名称 | 标签id | 典型表现 | 风险等级 |
|---|---|---|---|
| crack | 0 | 表面线性开裂,长度不一 | 高 |
| erosion | 1 | 前缘磨损、材料剥落 | 中高 |
| pollution | 2 | 油污、鸟粪、积灰附着 | 低 |
| lightning | 3 | 雷击灼伤、烧蚀黑斑 | 高 |
| delamination | 4 | 分层鼓包、蒙皮翘起 | 高 |
类别定义时有一个非常重要的取舍:不要把缺陷分得太细。早期版本里我尝试把“裂纹”继续细分成“横向裂纹”“纵向裂纹”“网状裂纹”,结果标注人员自己都吵起来了,模型效果也并没有因为细分而变好。缺陷检测任务里,类别边界越清晰,模型越容易学,现场运维人员也更关心“有没有问题”和“问题严不严重”,而不是教科书式的分类学。所以更细的等级判断交给人工复核阶段去做,模型只需要把可疑区域圈出来。
2.4 训练集、验证集、测试集的划分策略
数据集划分遵循了约70%训练、20%验证、10%测试的比例。划分时有一个关键原则,我反复强调过很多次:必须保证来自同一台风机、同一次巡检航次的图像不要同时出现在训练集和验证集里。否则模型会通过背景纹理、光照风格等非缺陷特征“作弊”,验证分数虚高,到了陌生场景立刻现出原形。最稳的做法是按拍摄时间线聚类,先按航次分组,再整体切分数据集。
另外一个容易被忽略的点是,测试集要保留一批“极端样本”,比如严重反光的、低光照的、远处小目标的。这些图单独拿出来做鲁棒性评测,比测试集全用清晰图更有参考价值。模型能扛住这些脏数据,说明真的学到了缺陷本身的特征,而不只是记住了数据集里的图像风格。
3. 基于数据集的模型训练实操
3.1 环境准备与工具链选型
拿到数据集之后,很多初学者会陷入一个误区:非要自己从零写检测网络。实际上现阶段用现成框架做迁移学习才是效率最高的路径。我在多个项目里用的主力框架是YOLOv8系列,理由非常朴素:一是训练和推理效率高,二是部署到边缘设备(比如机载端或地面站工控机)时资料多、问题好查,三是前后处理接口稳定,省去很多造轮子的时间。
环境方面,推荐Python 3.10以上,配合PyTorch 2.x,显卡显存建议至少8GB。显存不够的时候也不需要硬着头皮上大模型,使用YOLOv8s甚至YOLOv8n级别,配一个相对轻量的输入尺寸,在叶片缺陷这种目标比较明确的任务上跑出来的效果并不会比大模型差太多。叶片缺陷检测并不需要理解复杂场景语义,中低容量的模型反而训练更快、迭代更灵活。
3.2 数据配置:改一个yaml就能开跑
用YOLO格式训练时,最关键的就是data.yaml:
path: ./wind_turbine_blade_defect_10077 train: images/train val: images/val test: images/test nc: 5 names: ['crack', 'erosion', 'pollution', 'lightning', 'delamination']注意path字段使用的是数据集根目录的相对路径,train和val则填写相对于根目录的图片文件夹路径。这里有个小坑:如果服务器环境里路径写的是绝对路径,换一台机器或者换用户目录后经常直接报错找不到文件,相对路径配合软链接是更省心的方案。
VOC格式转YOLO格式时,核心是读取XML里的object节点,依次提取name、bndbox的四个坐标值,然后除以图片宽高做归一化,最后写入txt文件。写转换脚本时建议先挑选三张图人工对比转换前后的框位置,确认坐标落在正确区域再批量处理,不要一上来就跑全集。
3.3 训练参数与数据增强怎么设
我在风电叶片场景下的常用参数配置如下:
yolo detect train \ data=data.yaml \ model=yolov8s.pt \ epochs=120 \ imgsz=1280 \ batch=16 \ lr0=0.01 \ mosaic=1.0 \ fliplr=0.5 \ scale=0.5输入尺寸imgsz设置在1280而不是默认的640,原因非常直接:叶片裂纹这类缺陷的原始像素尺寸太小,640分辨率下很多细节直接被压缩没了。虽然1280会带来训练显存和耗时的增加,但对小目标检测的提升是肉眼可见的。如果显存紧张,可以先用640跑通全流程,再用1280做精调。
数据增强参数里mosaic保留到1.0,这一项能让模型在小样本条件下学到更丰富的上下文信息。但要特别注意,如果训练集中同一张原图切片出的多个小图被mosaic拼接在一起,容易出现“语义泄漏”问题,模型可能会偷懒地根据色调去猜位置。我的处理做法是在训练集中做了简单的去重,保证参与增强的样本独立性。
3.4 训练过程中的指标观察
训练时我主要盯三类指标:loss曲线、精确率和召回率曲线、验证集mAP。loss曲线持续下降且没有剧烈震荡,说明训练基本正常;验证集mAP50能稳定在0.70以上,基本可以认为这个数据集的有效信息被模型吸收了。如果loss降不下去,先不要急着加数据,检查一下标注框是否有错位、类别是否有误标,多数情况下是数据问题而不是模型问题。
训练结束后,记得用测试集做一个独立评估,测试集不参与验证过程,专用于模拟真实场景的泛化表现。测试集mAP50和验证集mAP50相差2个百分点以内算正常,如果差距过大,大概率是过拟合了,需要回退增强策略或增加正则化。
3.5 推理测试和结果可视化
模型训练完成后,可以用YOLO模式直接跑推理:
yolo detect predict \ model=best.pt \ source=images/test \ save=True \ conf=0.25 \ iou=0.45 \ imgsz=1280conf阈值设0.25是我现场验证下来的一个平衡点。阈值太低会冒出一堆误检框,阈值太高会把小裂纹漏掉,0.25配合后续人工复核,比单一抠阈值安全得多。预测时保存的标注框图像直接用于生成巡检报告,格式上比纯数据文件友好很多,交付给运维团队也更容易理解。
4. 常见问题与排查技巧
4.1 坐标对不上图?先查归一化分母
实际操作中反馈最多的问题就是标注框位置偏移。这类问题绝大多数出在归一化处理上:有人把坐标统一除以了图片长边,有人除以了短边,还有人直接除以了网络输入尺寸,不同做法导致的结果天差地别。YOLO格式的要求是x坐标除以图片宽度、y坐标除以图片高度,只有先确认了这一点再写转换脚本,才谈得上后续训练。排查方法很简单,把txt标注读回来画在图上,眼睛扫一遍比调试大半天都有效。
4.2 小目标漏检:切图是性价比最高的办法
无人机航拍图分辨率高,叶片缺陷占比往往极小。一整张1280x720的图里,一条裂纹可能只有30x80像素,直接整图训练,模型很难聚焦到这个尺度。我的经验是做滑窗切图:把原图切成若干个1024x1024或640x640的重叠子图,重叠比例大概10%到20%,同时对子图重新生成标注框。推理时也用同样的滑窗方式,再把所有窗口的结果合并回原图坐标系,重叠区域的框用NMS去重。这个方法不需要改任何模型结构,是工程上处理小目标最稳的路径。
4.3 把焊缝、防雷条误检成裂纹怎么办
风电叶片表面有很多非缺陷的结构纹理,比如叶片接缝、防雷导电条、甚至贴纸和修补痕迹,这些结构在视觉上和裂纹有相似性。早期实验里误检率最高的就是焊缝边缘,模型把它当作裂纹报了。解决办法不是简单加“负样本”这个概念,而是专门收集一批“带结构纹理但没有缺陷”的纯背景图,不标任何框,直接加入训练集作为无目标样本。模型在训练中会学习到这些背景不该产生预测输出,误检率能下降一半以上。
4.4 类别不均衡怎么平衡
五类缺陷里,pollution样本量可能远大于delamination,直接训练会让模型偏向多数的类别。处理手段分两步:第一步是用过采样或复制的方式让少样本类别达到一定的底数;第二步是在损失函数层面给少数类别分配更高的权重系数。在YOLO框架里,这个可以通过调整类别权重实现。更实用的做法是优先保证少数类别的验证集召回率,这类缺陷往往是不常见但最危险的那一类,漏检代价远高于误检。
4.5 现场新增风机机型,模型掉点怎么办
换一个叶片厂商的机组,涂装风格变化可能让mAP掉十几个点,这会让人非常头疼。经验是保留一部分新机型照片做“小样本微调”,用已经训练好的权重作为预训练,对新样本训练50个epoch以内,学习率降到原来的五分之一。新鲜数据量不需要很多,通常一百来张典型图就能把效果拉回来。这个方法在多次项目里验证都有效,比重新标注几千张新图再全量训练划算太多。
4.6 问题排查速查表
| 现象 | 可能原因 | 排查思路 |
|---|---|---|
| 训练loss不下降 | 标注框错位、类别标签错误 | 画框可视化抽查,核对XML字段 |
| 验证mAP高但现场效果差 | 数据切分混入同航次图 | 按航次聚类重新划分数据集 |
| 小裂纹一直漏检 | 输入分辨率不够 | 改到1280或做滑窗切图 |
| 焊缝被误报为裂纹 | 缺少无缺陷背景样本 | 补充负样本图嵌入训练 |
| 新机型表现明显变差 | 跨域差异过大 | 小样本微调预训练模型 |
5. 从数据集到业务落地,还可以再往前走几步
模型训练出来只是第一步,真正到现场落地,还有一个完整链路要走。后端检测结果要能自动合并成巡检报告,把缺陷类型、所在叶片、大概位置、建议处置方式结构化存下来。缺陷截图、置信度、拍摄时间、风机编号这些字段都应该进入数据库,方便后续对比叶片的历史缺陷变化趋势。某个裂纹上一次巡检时多长,这次有没有扩展,这类量化分析对运维决策价值远大于一次性的检测框。
这期数据集还可以作为迁移学习的底座。我用它做过跨任务验证:把叶片缺陷模型的特征提取层拿到输电线路绝缘子检测上做冷启动,效果比从ImageNet预训练权重开始迁移要好不少。如果你是做其他工业构件外观检测的,不妨先用这套数据集练出手感,再迁移到自己的私有数据上,路会顺很多。
如果说有什么最想分享的个人体会,那就是做工业数据集,不要贪图数量庞大,标注干净、场景贴近真实、划分合理,这三件事远重要于文件数量。第10077期这个版本能解决叶片巡检里的大部分常见问题,但没有任何数据集能覆盖所有现场。拿它做起点,不断的从实际巡检中补充你的私有样本,持续微调,模型的价值才会越来越大。