光伏缺陷检测实战:PVEL-AD数据集从标注转换到mAP评估的落地复盘
光伏缺陷检测实战:PVEL-AD数据集从标注转换到mAP评估的落地复盘
【免费下载链接】PVEL-ADPhotovoltaic cell defect detection项目地址: https://gitcode.com/gh_mirrors/pv/PVEL-AD
拿到数据集授权的那一刻,我以为训练模型只是时间问题。真正动手才发现,从36,543张光伏缺陷检测图像到一份经得起复现的检测结果,中间隔着标注格式转换、长尾分布处理和评估口径统一三道坎。这篇文章是我用PVEL-AD数据集跑完光伏缺陷检测全流程的复盘——每道坎怎么过的、踩过哪些坑,一次讲清。
3个数字,先看清PVEL-AD数据集的家底
PVEL-AD(Photovoltaic Electroluminescence Anomaly Detection)是目前光伏缺陷检测领域规模最大的公开数据集之一,由河北工业大学与北京航空航天大学联合发布。它的核心参数:
- 36,543张近红外电致发光(EL)图像,按真实产线缺陷分布采样
- 12类缺陷+ 1类无缺陷图像
- 40,358个人工标注的边界框
- 长尾分布:最少的类别只有个位数样本
图1:PVEL-AD覆盖的12种缺陷——线裂、星裂、指状中断、黑芯、错位、短路等,每种缺陷用不同颜色的边界框精确标注
从训练集标注分布就能直观感受长尾有多严重:
| 类别 | 样本数 | 类别 | 样本数 |
|---|---|---|---|
| finger | 2958 | vertical_dislocation | 137 |
| crack | 1260 | star_crack | 135 |
| black_core | 1028 | printing_error | 32 |
| thick_line | 981 | corner | 9 |
| horizontal_dislocation | 798 | fragment | 7 |
| short_circuit | 492 | scratch | 5 |
最少的 scratch 只有 5 个样本,是最多的 finger(2958 个)的约六百分之一。这个分布本身就是在提醒你:别把通用目标检测的套路直接套上来。
顺带说一个利好:官方近期已公开 test 标注。此前测试要上传到官方评测平台,现在本地就能跑完整的光伏缺陷检测评估闭环。
第一关:把XML标注转成模型能吃的TXT 🔧
拿到数据后第一件事不是选模型,而是处理标注格式。数据集给的是 VOC 风格的 XML,而 YOLO、Faster R-CNN 等主流框架更习惯读 TXT。仓库里的get_gt_txt.py就是干这个的。
先 clone 仓库,再按 README 流程申请数据集:
git clone https://gitcode.com/gh_mirrors/pv/PVEL-AD然后运行转换脚本:
python get_gt_txt.py这里有个坑必须提醒:这个脚本不接受命令行参数,路径全是写死的。它默认从VOCdevkit/VOC2007/ImageSets/Main/test.txt读图片清单、从同目录的Annotations读 XML,输出到./input/ground-truth/。所以要么按 VOC 目录结构摆数据,要么直接改脚本里的路径——别指望--input之类的参数。
脚本里还留了两个很实用的开关:
- difficult 标记:XML 中标了 difficult=1 的框,输出时会带
difficult后缀,后续评估会区别对待 - 类别筛选:如果标注里混了无关类,取消
get_classes相关代码的注释,用 classes.txt 做过滤
第二关:水平翻转增强,最划算的样本翻倍法 🎲
长尾问题光靠重采样不够,数据增强是更稳的手段。仓库的horizontal_flipping.py做的是图像与标注同步水平翻转——它不是简单地cv2.flip一下,而是把 XML 里每个框的 xmin/xmax 按新图像宽度重算,保证翻转后标注依然精确。
为什么 EL 图像特别吃水平翻转?因为电池片的缺陷(线裂、指状中断、错位)大多没有方向先验,翻转后依然是语义合理的样本。这一招相当于免费把训练样本翻倍。
但注意,脚本里写的是 Windows 绝对路径(E:\\Users\\yolov5-develop\\...),Linux 下直接跑会报错。把imgreadpath、xmlreadpath等四个路径改成自己的目录即可。如果你用的是 YOLO 的 txt 格式,也可以照这个思路写个同步翻转版本——核心逻辑就一行:xmin' = 图片宽 - xmax。
第三关:直面长尾,别让5个样本的缺陷毁掉整体分数 📉
图2:组件级 EL 图像示例,一块组件中分布着多种缺陷,检测系统需要同时完成定位与分类
长尾分布下,常规训练最常见的结局是:finger、crack 这类大类 AP 很高,scratch、fragment 这类小类几乎全漏。我实践下来最有效的三招:
- 类别加权损失:给稀有类更高权重,让梯度不再被大类垄断。但权重别设太极端,否则大类精度会被拖垮
- 两阶段训练:先用全量数据训出基线,再在稀有类样本上微调,比一上来就加权更稳
- 针对性增强:对稀有类做更强的扰动(旋转、对比度、随机裁剪),把"5 个样本"变成"5 个样本的多种形态"
模型选择上,除了 YOLO 这类通用检测器,论文里专门为光伏缺陷检测设计的 BAF-Detector(互补注意力机制)在稀有类上优势明显,官方论文报告的罕见缺陷 F1 达到 0.89。如果对漏检零容忍,Faster R-CNN 这类两阶段模型的稳定性更适合做工业兜底。
第四关:用AP50-5-95.py给出经得起复现的分数 📏
训练完别急着说"效果不错",用仓库里的AP50-5-95.py统一评估。它的机制值得先搞懂:
- 从
input/ground-truth/读真值(就是 get_gt_txt.py 的输出) - 从
input/detection-results/读预测(每行格式:类别 置信度 xmin ymin xmax ymax) - 自动跑 IoU 从 0.50 到 0.95、步长 0.05 的 10 档 mAP,最终输出平均的AP50_5_95
python AP50-5-95.py脚本源自 mAP 计算的开源实现,额外做了两件事:把 0.5:0.95 的 10 个阈值一次性算完,并在 results 目录输出每个类别的 AP、F1、Recall、Precision 明细。看结果时别只盯总 mAP,逐类看 AP——某类 AP 明显低于均值,就直接对应到训练策略去调。
脚本还支持--ignore忽略某些类、--set-class-iou给特定类单独设阈值,调试阶段很省事。
避坑清单:这些细节直接决定你的分数 ⚠️
把一路踩过的坑汇总成清单,省得大家重复交学费:
- 别改标注文件的编码与格式:评估脚本解析 TXT 很严格,多余空格、空行都可能静默出错
- 文件名必须一一对应:预测文件名要和 ground-truth 完全一致,否则直接报 "File not found"
- 增强后务必程序抽查标注:翻转脚本算出的新坐标用脚本验一遍,别信任肉眼
- 类别名要全局统一:finger 还是 finger_interruption?混用会让评估结果直接失真
- difficult 框别提前删:评估逻辑会单独处理它们,删掉反而拉低你的真实水平
这套流程适合谁、不适合谁 🎯
适合:想快速建立光伏缺陷检测基线的团队;研究长尾目标检测、开放世界检测的算法方向;需要对照公开数据集做模型选型评估的决策者。
不适合:追求像素级分割的场景(数据集是框标注,没有 mask);对缺陷成因做工艺级分析的场景(那是产线工艺数据该做的事,不是检测数据集能覆盖的)。
下一步:从"能跑"到"能上线" 🚀
数据集评测通过只是第一步。往产线走,还有三件事值得投入:
- 把评估脚本接进训练流程:每次实验自动出 AP50_5_95,用数字驱动迭代,而不是靠手感
- 尝试开放世界检测:PVEL-AD 本身就是 open-world 设定,可以让模型对未见过的缺陷给出"未知"信号,这在光伏工艺快速迭代期尤其有价值
- 做小样本与迁移实验:利用长尾特性做 few-shot 研究,把大类学到的特征迁移到新缺陷上
写在最后:建议你先跑通这条最小闭环
如果你想入局光伏缺陷检测,我的建议很具体:先 clone 仓库、申请数据、跑通 get_gt_txt.py → 训练 → AP50-5-95.py 这条最小闭环,用官方脚本把评估口径固定下来,再谈模型优化。如今测试标注已公开,复现门槛降到历史最低——剩下的,就是动手跑一遍。
【免费下载链接】PVEL-ADPhotovoltaic cell defect detection项目地址: https://gitcode.com/gh_mirrors/pv/PVEL-AD
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考