ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

输电线路鸟巢检测数据集:2461张VOC标注与YOLO训练实战

输电线路鸟巢检测数据集:2461张VOC标注与YOLO训练实战 简介本资源为Pascal VOC格式的输电线路鸟巢目标检测数据集面向从事电力巡检、无人机航拍分析及深度学习目标检测的开发者与研究人员可用于训练和验证鸟巢识别模型解决输电线路隐患自动排查问题。压缩包共约2000个文件包含2461张jpg图片与2461个同名xml标注文件另附一份使用授权说明txt整体约814.44MBxml采用labelImg绘制矩形框仅含nest一个类别共标注2567个目标框图片与标注一一对应可直接接入VOC标准训练流程。目前已有1085人学习下载适合作为电力场景小目标检测的实战数据。读者可据此构建单类别检测基线验证模型在真实线路环境下的召回与误检表现并借助完整标注快速完成数据划分、格式转换与训练调参省去自行采集与标注成本。1. 输电线路鸟巢检测数据集2461 张 VOC 标注能不能直接开练输电线路巡检这个场景鸟巢检测是个典型的「小目标 单一类别 强背景干扰」任务。无人机拍回来的图里铁塔横担、绝缘子串、导线金具占了大半画面鸟巢往往只占几十个像素还经常被树枝、云层、光照变化糊住。我拿到这份数据集的第一反应是2461 张 jpg 配 2461 个 xml类别只有一个nest总框数 2567平均每张图 1.04 个框——这个分布很「干净」说明标注策略是「有鸟巢就框没有就不框」没有硬凑负样本也没有把整张图当背景框。对做输电线路智能巡检、电力视觉检测的团队来说这是一份可以直接进训练管线的 Pascal VOC 格式数据省掉了从视频抽帧、清洗、标框的脏活。它适合谁适合已经跑通过 YOLO 或 Faster R-CNN 基础流程、手里有 GPU 但缺行业数据的工程师也适合电力巡检方向的学生做课题因为类别单一、格式标准调试成本低。但别指望拿它直接出论文级精度——特别声明里写得很清楚不对模型精度作任何保证它提供的是「准确且合理标注」不是「调优过的 benchmark」。2. VOC 格式拆解2461 张图背后的文件结构与标注逻辑2.1 为什么这份数据用 VOC 而不是 YOLO txtPascal VOC 的核心是「一图一 xml」xml 里存的是绝对像素坐标xmin/ymin/xmax/ymax直接对应原图。YOLO 的 txt 则是归一化后的cx cy w h依赖图片尺寸做换算。这份数据集只给 jpg xml没有分割路径的 txt也没有 yolo 格式的 txt说明作者是按 labelImg 默认流程导出的保留了最原始的标注信息。对训练来说VOC 的好处是「信息无损」你可以随时转成 YOLO、COCO、CSV反过来从 YOLO txt 转回 VOC 会丢精度归一化坐标乘回宽高再取整边界框会漂。我一般会先把 VOC 当「母版」存着训练前再转成框架需要的格式。2.2 xml 文件里到底有什么拿一个典型的nest_firc_1670.xml来说结构是这样的annotation foldernest_firc/folder filenamenest_firc_1670.jpg/filename size width1920/width height1080/height depth3/depth /size object namenest/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin843/xmin ymin512/ymin xmax921/xmax ymax578/ymax /bndbox /object /annotationsize里的宽高是原图尺寸object可以出现多次这张图只有一个 nest。truncated和difficult在 labelImg 里默认是 0这份数据没有特别说明所以训练时一般忽略这两个字段。bndbox是绝对坐标左上角(xmin, ymin)右下角(xmax, ymax)宽 xmax - xmin高 ymax - ymin。2567 个框分布在 2461 张图上意味着有少量图有 2 个及以上鸟巢转换脚本要能处理多 object 的情况。2.3 目录组织与文件命名从正文列出的文件看命名规则是nest_firc_数字.xml对应的 jpg 应该是同名的nest_firc_数字.jpg。firc可能是项目代号或采集批次不影响训练。实际拿到手后建议先跑一遍文件配对检查# 检查 jpg 和 xml 是否一一对应 ls *.jpg | sed s/.jpg// | sort jpg_list.txt ls *.xml | sed s/.xml// | sort xml_list.txt diff jpg_list.txt xml_list.txt如果 diff 没有输出说明 2461 对文件完全配对如果有输出缺的那边就是脏数据训练前必须剔掉。我见过太多人直接开训结果 DataLoader 在某个 batch 报FileNotFoundError回头查才发现有 3 张图没有 xml。这种坑一次就够记一辈子。3. 从 VOC 到 YOLO转换脚本、划分策略与训练配置3.1 写一个能处理多 object 的 VOC→YOLO 转换脚本YOLO 训练需要images/和labels/两个目录label 是 txt每行class_id cx cy w h全部归一化到 0~1。下面这个脚本我用了很多次能处理一张图多个框也能跳过没有 object 的 xmlimport os import xml.etree.ElementTree as ET from PIL import Image # 类别映射这份数据只有 nest classes [nest] def convert_voc_to_yolo(xml_dir, img_dir, out_img_dir, out_label_dir): os.makedirs(out_img_dir, exist_okTrue) os.makedirs(out_label_dir, exist_okTrue) 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() filename root.find(filename).text img_path os.path.join(img_dir, filename) if not os.path.exists(img_path): print(fmissing image: {filename}) continue img Image.open(img_path) w, h img.size lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in classes: continue cls_id classes.index(cls_name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 归一化注意 YOLO 用中心点 宽高 cx (xmin xmax) / 2.0 / w cy (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) if lines: # 复制图片到输出目录 img.save(os.path.join(out_img_dir, filename)) txt_name os.path.splitext(filename)[0] .txt with open(os.path.join(out_label_dir, txt_name), w) as f: f.write(\n.join(lines)) convert_voc_to_yolo(annotations, images, yolo/images, yolo/labels)逻辑说明先读 xml 拿到原图宽高再遍历所有object把绝对坐标转成归一化中心点格式。classes列表顺序决定class_id这份数据只有nest所以 id 恒为 0。参数上xml_dir和img_dir是 VOC 原始目录out_img_dir和out_label_dir是 YOLO 输出目录。注意img.save会重新编码 jpg如果在意画质可以改成shutil.copy。转换完检查一下 label 文件数量是否等于 2461以及每行是否有 5 个字段。3.2 训练集/验证集划分别用随机 8:2 就完事输电线路巡检数据有个特点同一基铁塔、同一批次采集的图高度相似。如果纯随机划分验证集里会出现和训练集几乎一样的图指标虚高。我一般按「采集批次」或「文件名前缀」分组划分。这份数据文件名都是nest_firc_开头看不出批次那就退而求其次按文件名数字排序后每隔 5 张取 1 张做验证保证验证集覆盖整个编号范围。import os import random all_imgs sorted([f for f in os.listdir(yolo/images) if f.endswith(.jpg)]) val_imgs all_imgs[::5] # 每 5 张取 1 张 train_imgs [f for f in all_imgs if f not in val_imgs] with open(train.txt, w) as f: for img in train_imgs: f.write(os.path.join(yolo/images, img) \n) with open(val.txt, w) as f: for img in val_imgs: f.write(os.path.join(yolo/images, img) \n)这样大约 1969 张训练、492 张验证。如果要做更严格的评估可以再切一个 test 集但这份数据量不大验证集当 test 用也行只要不在训练中调参就行。3.3 YOLOv8 训练配置小目标检测的关键参数用 ultralytics 的 YOLOv8 跑这份数据data.yaml这样写path: ./yolo train: train.txt val: val.txt nc: 1 names: [nest]训练命令yolo detect train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16 patience20参数说明imgsz640是默认值但鸟巢目标小可以试imgsz960或1280显存不够就降 batch。patience20是早停验证集 mAP 20 轮不升就停。modelyolov8s.pt是轻量版如果精度不够换yolov8m.pt。注意这份数据类别只有 1 个nc1names顺序要和转换脚本里的classes一致。训练完看runs/detect/train/weights/best.pt用yolo detect val验证。4. 避坑与排查标注、转换、训练里最容易翻车的 5 个点4.1 现象转换后 label 文件是空的原因xml 里object的name不是nest或者脚本里classes列表写错。这份数据标注类别名称是[nest]但 labelImg 有时会带空格或大小写差异。解决先跑一遍统计脚本把所有name值打印出来确认。import xml.etree.ElementTree as ET import os names set() for f in os.listdir(annotations): if f.endswith(.xml): root ET.parse(os.path.join(annotations, f)).getroot() for obj in root.iter(object): names.add(obj.find(name).text) print(names)如果输出不是{nest}就要在转换脚本里做 strip 和 lower。4.2 现象训练 loss 正常但 mAP 一直是 0原因data.yaml里的names顺序和 label 里的class_id对不上或者nc写成了 0。这份数据只有一类nc1names: [nest]class_id必须是 0。解决打开一个 label txt确认第一列是 0再检查data.yaml的nc和names长度是否一致。4.3 现象验证集 mAP 很高但实际推理漏检严重原因划分验证集时用了随机划分验证集和训练集同源指标虚高。解决按文件名排序后等间隔取验证集或者按采集批次分组。如果数据里有同一基铁塔的多角度图最好把整基铁塔的图都划到同一侧。4.4 现象小目标框在训练中被过滤掉原因YOLO 默认的 anchor 匹配对小目标不友好或者imgsz太小导致鸟巢缩到几个像素。解决提高imgsz到 960 或 1280在data.yaml里加augment: True开启 mosaic 和 mixup如果还不行换用带 P2 检测层的模型如 YOLOv8-p2专门抓小目标。4.5 现象xml 里xmax小于xmin原因标注时手滑拖反了labelImg 有时会存成负宽高。解决转换脚本里加一行校验if xmax xmin or ymax ymin: continue把这种框丢掉。这份数据标注规则是「对类别进行画矩形框」理论上不会出现但批量数据里总有几颗老鼠屎。5. 进阶技巧用 2567 个框做小目标增强与模型验证这份数据只有 2567 个框直接训大模型容易过拟合。我一般会做两件事一是用「复制粘贴增强」把鸟巢实例抠出来随机贴到无鸟巢的输电线路背景上扩充正样本二是用「切片推理」在验证阶段把大图切成小块逐块检测再合并专门抓小目标。复制粘贴增强的代码不复杂用 OpenCV 按 bndbox 裁剪再随机缩放、旋转、调亮度后贴回原图同时更新 xml 或直接生成 YOLO label。注意贴的时候要避开已有鸟巢区域否则会重叠。切片推理更简单推理时把 1920×1080 的图切成 640×640 的块重叠 128 像素每块单独跑model.predict最后用 NMS 合并框。这两个技巧对鸟巢这种小目标提升明显但会拖慢训练和推理速度按需取舍。验证模型有没有真正学到鸟巢特征我习惯看两个东西一是runs/detect/train/val_batch0_pred.jpg看预测框和真值框的重合度二是用 Grad-CAM 画热力图确认模型关注的是鸟巢区域而不是铁塔横担。如果热力图集中在背景上说明模型在「抄近路」这时候要么加负样本要么换更强的 backbone。从那以后我每次拿到新数据集都强制走一遍「文件配对检查 → 类别统计 → 转换后抽样可视化 → 小批量过拟合测试」这四步确认管线通了再开全量训练。希望帮到你。本文还有配套的精品资源点击获取
返回列表