简介:这份资源面向光伏运维、工业质检与AI算法学习者,提供光伏板缺陷检测的完整数据集与配套模型,覆盖裂纹、脏污、热斑、遮挡、破损等常见缺陷类型,可直接对接YOLO等主流检测框架,用于训练、验证与无人机巡检图像分析。压缩包为7z格式,共2000个文件,约43.16MB,其中1626个txt标注文件、359张jpg与7张png图像构成训练与验证样本,另有3个yaml配置、2个py脚本、2个pt权重及1个csv训练日志,兼顾数据、代码与模型权重。已有64人学习下载。读者可借助现成标注数据与权重快速复现缺陷检测流程,结合训练曲线与预测可视化图排查模型效果,省去从零采集与标注的成本,适合作为课程设计、科研实验或电站智能巡检方案的基础素材。
1. 光伏板缺陷检测数据集与模型:从“能用”到“好用”的落地拆解
光伏板缺陷检测这个方向,这两年从实验室走向产线的速度比很多人预想的快。我接触过的几个做电站巡检的团队,早期靠人工拿热成像仪扫,一天下来眼睛都快看瞎,漏检率还压不住。后来大家开始上视觉方案,核心就两件事:一是有一份标注靠谱的缺陷数据集,二是有一个能跑起来、精度够用的检测模型。这次拆的这个资源包,标题写得很直白——光伏板缺陷数据集、模型,还带检测代码。它解决的就是从零搭一套缺陷检测流程时,最耗时间的那段:找图、标图、训模型、写推理脚本。适合谁?做新能源巡检的算法工程师、想拿光伏缺陷检测当毕设或练手项目的学生、以及需要快速验证产线视觉方案可行性的技术负责人。Python 和 YOLO 是这套东西的主轴,下面我按实际复现的顺序,把数据、训练、推理和坑点一层层拆开。
2. 数据集结构与 YOLO 格式转换:别让标注拖后腿
2.1 光伏板缺陷的典型类别与数据组织
先搞清楚这份数据集里有什么。光伏板缺陷常见的有几类:隐裂、断栅、热斑、脏污、二极管故障。不同来源的数据集类别定义会有差异,有的把隐裂和断栅合并成“内部缺陷”,有的把热斑单独拎出来。拿到资源包后第一件事不是急着跑代码,而是打开标注文件看一眼类别索引。YOLO 格式的标注是每张图对应一个.txt,每行class_id x_center y_center width height,坐标全部归一化到 0 到 1 之间。如果资源包里给的是 VOC 的 XML 或者 COCO 的 JSON,就得先转。我一般会先统计一下每个类别的框数量,类别极度不均衡的话,后面训练策略要提前调整。
数据目录的常见组织方式是这样的:
dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml是 YOLO 训练时的入口配置文件,里面写清楚训练集、验证集路径和类别名称。这个文件看着简单,但路径写错、类别数和标注对不上,是新手翻车最多的地方。
2.2 从 VOC/COCO 转 YOLO 的脚本与参数说明
如果资源包里是 XML 格式,用下面这个脚本转。我习惯把转换和校验放在一起做,转完立刻检查有没有越界框和空标注。
import os import xml.etree.ElementTree as ET from PIL import Image # 类别映射,必须和 data.yaml 里的 names 顺序一致 CLASS_MAP = {"crack": 0, "broken": 1, "hotspot": 2, "dirty": 3} def voc_to_yolo(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(xml_dir, xml_file)) root = tree.getroot() # 图片尺寸从原图读取,不要信 XML 里的 size,有些标注工具会写错 img_name = root.find("filename").text img_path = os.path.join(img_dir, img_name) with Image.open(img_path) as im: w, h = im.size lines = [] for obj in root.iter("object"): cls_name = obj.find("name").text if cls_name not in CLASS_MAP: continue cls_id = CLASS_MAP[cls_name] bbox = obj.find("bndbox") x1 = float(bbox.find("xmin").text) y1 = float(bbox.find("ymin").text) x2 = float(bbox.find("xmax").text) y2 = float(bbox.find("ymax").text) # 裁剪到图像边界,防止越界框导致训练报错 x1, y1 = max(0, x1), max(0, y1) x2, y2 = min(w, x2), min(h, y2) if x2 <= x1 or y2 <= y1: continue xc = (x1 + x2) / 2.0 / w yc = (y1 + y2) / 2.0 / h bw = (x2 - x1) / w bh = (y2 - y1) / h lines.append(f"{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}") out_path = os.path.join(out_dir, xml_file.replace(".xml", ".txt")) with open(out_path, "w") as f: f.write("\n".join(lines)) voc_to_yolo("annotations/xmls", "images/all", "labels/all")这段代码里几个关键点:CLASS_MAP的顺序必须和data.yaml里的names完全一致,否则模型学出来的类别是错位的;图片尺寸从原图读而不是从 XML 读,是因为部分标注工具导出的size字段和实际图片对不上;越界框直接裁掉而不是丢弃,能保留部分有效信息。转完之后跑一个校验脚本,统计每个类别的框数、宽高分布,宽或高小于 0.001 的框基本是标注噪声,建议清掉。
2.3 数据增强策略与划分比例
光伏板图像有个特点:背景相对固定,但缺陷尺度差异大。隐裂可能只占几十个像素,脏污可能覆盖大半个板面。所以增强不能无脑上。我一般用 Mosaic 加随机缩放,但会把缩放范围控制在 0.5 到 1.5 之间,太大容易把隐裂这种小目标缩没。HSV 抖动可以开,但饱和度别调太狠,热斑的颜色特征比较敏感。翻转要看情况,水平翻转一般没问题,垂直翻转要谨慎,因为光伏板的栅线方向有语义。
训练集、验证集、测试集按 7:2:1 分。如果总图量少于 2000 张,验证集可以再小一点,把更多图留给训练。划分的时候要保证每个类别在三个集合里都有出现,别出现某个类别只在训练集里有、验证集里一个都没有的情况,那样验证指标会失真。
3. YOLO 模型训练:参数怎么设、日志怎么看
3.1 环境准备与依赖版本
资源包里的检测代码大概率是基于 Ultralytics 的 YOLOv5 或 YOLOv8。这两个版本 API 有差异,先看requirements.txt或者代码里的 import 语句确认。我一般用 conda 建一个干净环境,Python 3.8 到 3.10 都行,PyTorch 版本跟着 CUDA 走。如果机器上没有 GPU,CPU 也能跑,但训练时间会拉长很多,建议至少拿一张 8G 显存的卡做验证。
conda create -n pv_defect python=3.9 -y conda activate pv_defect pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics opencv-python pillow pyyaml装完之后跑一句python -c "import torch; print(torch.cuda.is_available())",返回 True 才说明 GPU 可用。这一步没过,后面训练会默认走 CPU,速度差一个数量级。
3.2 训练命令与关键参数解读
假设用的是 YOLOv8,训练命令大概长这样:
yolo detect train \ data=dataset/data.yaml \ model=yolov8s.pt \ epochs=150 \ imgsz=640 \ batch=16 \ lr0=0.01 \ lrf=0.01 \ patience=30 \ device=0 \ project=runs/pv \ name=exp1逐个说:model选yolov8s还是yolov8m,看你的显存和精度要求,光伏缺陷检测里小目标多,s版本在 640 分辨率下对小目标的召回有时候不够,可以试试m或者把imgsz提到 1024。batch设 16 是 8G 卡的保守值,显存够可以往上加。lr0初始学习率 0.01 是默认值,如果 loss 震荡厉害,降到 0.005 试试。patience设 30 表示 30 轮验证指标不提升就早停,防止过拟合。lrf是最终学习率因子,和lr0配合做余弦退火。
训练日志里重点看三个东西:box_loss、cls_loss和mAP50。box_loss降不下去,说明框回归有问题,检查标注质量;cls_loss高,可能是类别不均衡或者类别定义模糊;mAP50是主要指标,光伏缺陷检测里能到 0.85 以上就算可用,0.9 以上算不错。如果训练集 mAP 很高但验证集低,过拟合了,加增强或者减模型容量。
3.3 训练过程监控与中断恢复
训练跑起来之后,runs/pv/exp1/下面会有weights、results.csv和几张可视化图。results.csv可以用 pandas 读出来画曲线,比盯着终端刷屏直观。如果训练中途断了,用resume=True接着跑:
yolo detect train resume model=runs/pv/exp1/weights/last.pt这里有个坑:resume依赖last.pt里保存的优化器状态和 epoch 信息,如果手动改过data.yaml或者换了数据集路径,resume 可能会报错。稳妥做法是中断前把整个exp1目录备份一份。
4. 推理与部署:从权重文件到可用接口
4.1 单图推理与批量推理脚本
训练完拿到best.pt,先跑单图看看效果:
from ultralytics import YOLO model = YOLO("runs/pv/exp1/weights/best.pt") results = model.predict( source="test_images/", conf=0.25, # 置信度阈值,低于这个值的框不输出 iou=0.45, # NMS 的 IoU 阈值,重叠框合并 imgsz=640, save=True, save_txt=True # 同时输出 YOLO 格式的预测结果 )conf设 0.25 是通用起点,光伏缺陷里如果误检多,提到 0.4 试试;如果漏检多,降到 0.15。iou控制重叠框的合并程度,缺陷密集的场景可以适当调低,避免把相邻缺陷合并成一个。save_txt=True输出的预测结果可以用来做后续的统计和对比。
4.2 推理结果可视化与误检分析
预测完在runs/detect/predict/下会有带框的图。我习惯把误检和漏检的图单独挑出来看,误检通常是背景纹理被当成缺陷,漏检多半是小目标或者低对比度缺陷。针对误检,可以在训练集里加一些纯背景的负样本;针对漏检,把imgsz提上去或者用切片推理(SAHI)对小目标做专门处理。
4.3 导出 ONNX 与推理加速
如果要在产线部署,PyTorch 权重直接跑效率一般,导出 ONNX 再用 ONNXRuntime 或者 TensorRT 推理会快不少:
yolo export model=runs/pv/exp1/weights/best.pt format=onnx opset=12 simplify=Trueopset=12兼容性比较好,simplify=True会做一层图优化。导出之后用onnxruntime加载跑一遍,确认输出和 PyTorch 一致。注意导出时的imgsz要和训练时一致,否则精度会掉。
5. 避坑与常见问题排查
5.1 标注类别与 data.yaml 不一致导致训练崩溃
现象:训练启动几轮后报IndexError或者AssertionError,提示类别索引越界。原因:标注文件里的class_id超过了data.yaml里names的长度,或者顺序对不上。解决:跑一个统计脚本,把所有标注里的class_id最大值找出来,和names长度对比,不一致就重新映射。
5.2 图片路径含中文或空格导致读取失败
现象:训练时提示找不到图片,或者cv2.imread返回 None。原因:数据集路径里有中文、空格或特殊字符,OpenCV 和部分数据加载库处理不了。解决:把数据集放到纯英文、无空格的路径下,比如/data/pv_defect/,别放在桌面或者带中文的文件夹里。
5.3 显存不足导致 batch 调不下去
现象:训练一开始就 OOM,或者跑几轮后显存爆掉。原因:batch设太大,或者imgsz太高。解决:先把batch降到 8 甚至 4,同时开amp=True混合精度训练;如果还不行,把imgsz从 640 降到 512,但要注意小目标召回会受影响。
5.4 验证集 mAP 虚高但实际推理效果差
现象:训练日志里mAP50很高,但拿新图推理时漏检严重。原因:训练集和验证集划分时没有按场景分,验证集里的图和训练集太像,指标虚高。解决:重新划分数据集,确保验证集里的图来自不同电站、不同拍摄条件,别让模型“背题”。
5.5 导出 ONNX 后精度下降明显
现象:PyTorch 推理正常,ONNX 推理结果差很多。原因:导出时的opset版本、imgsz和预处理方式不一致。解决:导出时显式指定imgsz和opset,推理时用同样的归一化和通道顺序,别一边 BGR 一边 RGB。
6. 进阶技巧:用切片推理把隐裂小目标召回拉上来
隐裂这类小目标在 640 分辨率下经常只有几个像素,直接整图推理召回率上不去。我试过的一个有效办法是切片推理,把原图切成有重叠的小块,每块单独推理再合并结果。SAHI 这个库就是干这个的,和 YOLO 配合用:
from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model = AutoDetectionModel.from_pretrained( model_type="yolov8", model_path="runs/pv/exp1/weights/best.pt", confidence_threshold=0.25, device="cuda:0" ) result = get_sliced_prediction( "test_images/crack_01.jpg", detection_model, slice_height=320, slice_width=320, overlap_height_ratio=0.2, overlap_width_ratio=0.2 ) result.export_visuals(export_dir="sahi_out/")slice_height和slice_width设 320,相当于把 640 的图切成四块,每块里的目标相对变大。overlap设 0.2 是为了避免目标正好落在切片边界被切断。这个方法的代价是推理时间成倍增加,产线部署要权衡。我一般只在离线巡检分析里用,实时检测还是走整图。
验证切片推理有没有效果,别只看 mAP,把同一批测试图分别用整图和切片跑一遍,统计小目标(框面积小于 32x32 像素)的召回率变化。如果提升不到 5 个百分点,说明你的小目标占比没那么高,不值得上切片。从那以后我每次调完推理参数,都强制走一遍分场景的召回统计,不再只看一个总 mAP 就下结论。希望帮到你。
本文还有配套的精品资源,点击获取