





一、数据集基本信息表
| 项目 | 内容 |
|---|---|
| 数据集名称 | 无人机光伏太阳能板缺陷检测数据集(红外 + 可见光配对) |
| 总图像数量 | 650 张(红外与可见光图像严格一一对应,共 650 对 → 1,300 张图像) |
| 模态类型 | 双模态配对数据:• 红外热成像(Infrared)• 可见光图像(RGB) |
| 标注格式 | YOLO 格式(.txt 文件,适用于 YOLOv5/v8/v11 等) |
| 数据划分 | 未明确说明,建议按 7:2:1 划分(可自行分割) |
| 应用场景 | 光伏电站智能巡检、缺陷定位、运维决策支持 |
二、缺陷类别详细说明表
| 类别编号 | 类别代码 | 推测中文全称 | 英文解释 | 缺陷特征 |
|---|---|---|---|---|
| 0 | dmjrb | 电池片隐裂 | DianChi Pian YinLie (Cell Micro-crack) | 电池片内部微裂纹,红外中可能无温升,可见光需高分辨率识别 |
| 1 | ns | 热斑 | Hot Spot | 局部过热区域,红外图像显著高温,可见光可能无异常 |
| 2 | dyrb | 二极管故障 | ErJiGuan GuZhang (Bypass Diode Failure) | 导致整串电池发热,红外呈条状高温区 |
| 3 | ejgdl | 二极管过电流 | ErJiGuan GuoDianLiu (Diode Over-current) | 与 dyrb 类似,但程度更严重 |
| 4 | zw | 遮挡 | ZheWu (Shading) | 树影、鸟粪、灰尘等导致局部发电下降,红外呈低温区 |
| 5 | yyzd | 组件引线短路 | YinXian DuanLu (Junction Box Wiring Short) | 连接线异常发热 |
| 6 | ygfs | 组件玻璃破碎 | BoLi PoSui (Glass Fracture) | 可见光明显破损,红外可能因散热变化出现异常 |
| 7 | ycdw | 异常低温 | YiChang DiWen (Abnormal Low Temperature) | 发电异常停止区域,温度低于周围 |
| 8 | dmjrb_ycdw | 隐裂 + 异常低温 | Micro-crack + Cold Spot | 复合缺陷:隐裂导致断路,表现为低温 |
| 9 | dyrb_ycdw | 二极管故障 + 异常低温 | Diode Fault + Cold Spot | 二极管开路导致无电流,温度偏低 |
注:缩写为拼音首字母组合(如
dmjrb= 电/电池片隐裂)ycdw(异常低温)常出现在断路、严重隐裂、接线失效等场景。复合类别(如dmjrb_ycdw)表示同一区域同时存在两种缺陷特征。
三、数据集结构建议(YOLO 格式)
pv_defect_dataset/
├── images/
│ ├── infrared/ # 红外图像(.jpg)
│ └── visible/ # 可见光图像(.jpg)
├── labels/
│ └── visible/ # 通常以可见光为基准标注(.txt)
└── data.yaml
提示:实际使用中,可选择:仅用可见光训练(若标注基于可见光)融合红外 + 可见光(需多输入模型,如双流 CNN)。
四、data.yaml 示例
# pv_defect_dataset/data.yaml
train: ./images/visible/train
val: ./images/visible/val
nc: 10
names:
- 'dmjrb' # 电池片隐裂
- 'ns' # 热斑
- 'dyrb' # 二极管故障
- 'ejgdl' # 二极管过电流
- 'zw' # 遮挡
- 'yyzd' # 引线短路
- 'ygfs' # 玻璃破碎
- 'ycdw' # 异常低温
- 'dmjrb_ycdw' # 隐裂 + 低温
- 'dyrb_ycdw' # 二极管故障 + 低温
五、主要应用领域
| 应用场景 | 说明 |
|---|---|
| 1. 光伏电站智能巡检 | 无人机自动飞行采集红外 + 可见光图像,AI 实时识别缺陷,替代人工 |
| 2. 缺陷精准定位与分类 | 区分热斑、隐裂、遮挡等,指导运维优先级(如热斑需紧急处理) |
| 3. 发电量损失评估 | 结合缺陷类型与面积,估算发电效率损失 |
| 4. 预防性维护 | 早期发现隐裂、接线松动,避免故障扩大 |
| 5. 保险定损与质保索赔 | 提供客观、可追溯的缺陷证据链 |
| 6. 数字孪生电站建设 | 构建光伏组件健康状态数字档案 |
六、技术优势
- 红外 + 可见光融合:
- 红外 → 检测 热异常(热斑、二极管故障)
- 可见光 → 检测 物理损伤(破碎、遮挡、隐裂)
- 复合缺陷标注:提升模型对复杂故障的理解能力
- 小样本高效学习:650 对图像在工业场景已具备实用价值
七、核心工具实现
1. 红外 - 可见光图像配准脚本
目标:将红外图(Infrared)对齐到可见光图(Visible),实现像素级对齐 方法:SIFT 特征提取 + RANSAC 单应性变换(适用于无人机视角变化)
依赖安装
pip install opencv-python numpy matplotlib scikit-image
image_registration.py
# -*- coding: utf-8 -*-
"""
红外 - 可见光图像配准脚本
输入:一对红外图 + 可见光图(同一场景)
输出:配准后的红外图(与可见光对齐)
"""
import cv2
import numpy as np
import os
from skimage import exposure
def preprocess_images(ir_img, vis_img):
"""预处理:增强对比度,便于特征匹配"""
# 红外图:直方图均衡化
ir_eq = exposure.equalize_adapthist(ir_img.astype(np.uint8), clip_limit=0.03)
ir_eq = (ir_eq * 255).astype(np.uint8)
# 可见光图:转换为灰度
if len(vis_img.shape) == 3:
vis_gray = cv2.cvtColor(vis_img, cv2.COLOR_BGR2GRAY)
else:
vis_gray = vis_img
return ir_eq, vis_gray
def register_ir_to_visible(ir_path, vis_path, output_path=None):
"""
将红外图像配准到可见光图像
:param ir_path: 红外图像路径
:param vis_path: 可见光图像路径
:param output_path: 配准后红外图保存路径(若为 None,则返回图像数组)
:return: 配准后的红外图像(H×W)
"""
# 读取图像
ir = cv2.imread(ir_path, cv2.IMREAD_GRAYSCALE)
vis = cv2.imread(vis_path, cv2.IMREAD_COLOR)
if ir is None or vis is None:
raise FileNotFoundError(f"图像未找到:{ir_path} 或 {vis_path}")
# 预处理
ir_proc, vis_gray = preprocess_images(ir, vis)
# 初始化 SIFT 检测器(OpenCV 4.5+ 支持)
sift = cv2.SIFT_create()
# 提取特征点和描述子
kp1, des1 = sift.detectAndCompute(ir_proc, None)
kp2, des2 = sift.detectAndCompute(vis_gray, )
des1 des2 (kp1) < (kp2) < :
()
ir
FLANN_INDEX_KDTREE =
index_params = (algorithm=FLANN_INDEX_KDTREE, trees=)
search_params = (checks=)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=)
good_matches = []
m, n matches:
m.distance < * n.distance:
good_matches.append(m)
(good_matches) < :
()
ir
src_pts = np.float32([kp1[m.queryIdx].pt m good_matches]).reshape(-, , )
dst_pts = np.float32([kp2[m.trainIdx].pt m good_matches]).reshape(-, , )
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, )
H :
()
ir
h, w = vis.shape[:]
ir_registered = cv2.warpPerspective(ir, H, (w, h))
output_path:
cv2.imwrite(output_path, ir_registered)
()
ir_registered
__name__ == :
ir_file =
vis_file =
out_file =
registered = register_ir_to_visible(ir_file, vis_file, out_file)
matplotlib.pyplot plt
vis = cv2.imread(vis_file)
plt.figure(figsize=(, ))
plt.subplot(, , ); plt.imshow(cv2.imread(ir_file), cmap=); plt.title()
plt.subplot(, , ); plt.imshow(vis[:, :, ::-]); plt.title()
plt.subplot(, , ); plt.imshow(registered, cmap=); plt.title()
plt.tight_layout()
plt.savefig(, dpi=)
plt.show()
2. 双模态 YOLO 融合模型代码(YOLOv8 + 双流 CNN)
思路:分别用 CNN 提取红外和可见光特征,在特征层融合(concat + 1x1 conv)接入 YOLOv8 Head 进行检测
依赖安装
pip install ultralytics torch torchvision
dual_modal_yolo.py
# -*- coding: utf-8 -*-
"""
双模态 YOLO 模型:融合红外 + 可见光进行光伏缺陷检测
基于 YOLOv8 架构改造
"""
import torch
import torch.nn as nn
from ultralytics.nn.tasks import DetectionModel
from ultralytics import YOLO
from pathlib import Path
class DualModalYOLO(nn.Module):
"""
双模态 YOLO 模型
输入:[B, 1, H, W] 红外 + [B, 3, H, W] 可见光
输出:YOLO 检测头输出
"""
def __init__(self, num_classes=10, model_size='s'):
super().__init__()
self.num_classes = num_classes
# 加载预训练 YOLOv8 backbone(仅用于特征提取)
base_model = YOLO(f'yolov8{model_size}.pt').model
self.backbone_vis = base_model.model[:6] # 取前 6 层作为可见光主干
self.backbone_ir = self._copy_backbone() # 红外主干(独立权重)
# 融合层:将红外(1 通道)特征映射到 3 通道再融合
self.ir_proj = nn.Conv2d(1, 3, kernel_size=1)
self.fusion_conv = nn.Conv2d(6, 3, kernel_size=1) # concat 后 3+3=6 → 3
# 共享后续 YOLO 层
self.shared_layers = base_model.model[6:]
self.detection_head = base_model.model[-1]
def ():
base_model = YOLO().model
nn.Sequential(*(base_model.model[:]))
():
feat_ir = .backbone_ir(.ir_proj(x_ir))
feat_vis = .backbone_vis(x_vis)
fused = torch.cat([feat_ir, feat_vis], dim=)
fused = .fusion_conv(fused)
out = .shared_layers(fused)
out
torch.utils.data Dataset, DataLoader
os
PIL Image
numpy np
():
():
.img_size = img_size
.image_pairs = []
vis_dir = os.path.join(image_dir, )
ir_dir = os.path.join(image_dir, )
f os.listdir(vis_dir):
f.endswith():
name = f.replace(, )
.image_pairs.append({
: os.path.join(vis_dir, f),
: os.path.join(ir_dir, f),
: os.path.join(label_dir, f.replace(, ))
})
():
(.image_pairs)
():
pair = .image_pairs[idx]
vis = Image.(pair[]).convert()
ir = Image.(pair[]).convert()
vis = vis.resize((.img_size, .img_size))
ir = ir.resize((.img_size, .img_size))
vis = torch.from_numpy(np.array(vis)).permute(, , ).() /
ir = torch.from_numpy(np.array(ir)).unsqueeze().() /
boxes, classes = [], []
os.path.exists(pair[]):
(pair[]) f:
line f:
cls, x, y, w, h = (, line.strip().split())
boxes.append([x, y, w, h])
classes.append((cls))
ir, vis, torch.tensor(boxes), torch.tensor(classes)
():
dataset = DualModalDataset(
image_dir=,
label_dir=,
img_size=
)
dataloader = DataLoader(dataset, batch_size=, shuffle=)
model = DualModalYOLO(num_classes=).to( torch.cuda.is_available() )
optimizer = torch.optim.Adam(model.parameters(), lr=)
()
()
__name__ == :
model = DualModalYOLO(num_classes=)
dummy_ir = torch.randn(, , , )
dummy_vis = torch.randn(, , , )
output = model(dummy_ir, dummy_vis)
(, [o.shape o output])
八、使用建议
| 任务 | 推荐方案 |
|---|---|
| 快速上线 | 先用 可见光单模态 YOLOv8 训练(650 张已足够) |
| 高精度需求 | 使用 配准后红外 + 可见光,训练双模态模型 |
| 部署优化 | 导出 ONNX/TensorRT,红外 + 可见光拼接为 4 通道输入(R,G,B,IR) |


