
简介本数据集面向电力场景下的遥感图像目标检测任务适用于从事输电线路巡检、电杆塔识别的研究者与算法工程师可解决电力设施遥感影像中杆塔目标标注样本不足的问题。资源采用Pascal VOC与YOLO双格式组织包含400张jpg遥感图片并配套400个VOC格式xml标注文件与400个YOLO格式txt标注文件标注类别为sdgt单一类别共680个矩形标注框全部由labelImg工具人工绘制。压缩包为7z格式内含1202个文件以jpg图像、xml与txt标注文件为主整体约136.93MB目录结构清晰便于直接接入主流检测框架训练与验证。目前已有605人学习下载适合需要快速构建电力杆塔检测基线、开展模型对比实验或扩充遥感数据集的读者参考使用。1. 电力遥感电杆塔检测数据集400 张 VOCYOLO 双格式到底能跑出什么做电力巡检算法的人多半遇到过这种局面项目催着要一个能识别电杆塔的检测模型公开数据集要么是通用 COCO 里零星几张要么是航拍大场景里杆塔小到只有十几个像素标完一轮发现根本训不动。这份 firc_dianli 电力场景遥感电杆塔检测数据集就是冲着这个缺口来的——400 张 jpg 图片配套 400 个 Pascal VOC 格式 xml 和 400 个 YOLO 格式 txt单类别 sdgt总框数 680用 labelImg 画的矩形框。它不承诺任何模型精度只保证标注本身准确合理这个态度反而比那些吹得天花乱坠的数据包靠谱。适合谁用一是手头有电力巡检、遥感目标检测任务需要快速搭一个单类别 baseline 验证流程的工程师二是想练 YOLO 训练全链路、又不想在数据清洗上耗三天的新手。400 张不算大但双格式齐全意味着你既能走 VOC 那条老路也能直接喂给 YOLOv5/v8省掉一次格式转换的折腾。下面按「这数据长什么样 → 怎么转怎么训 → 坑在哪 → 怎么验证」的顺序拆开讲。2. 数据集结构与 VOC/YOLO 双格式的选型逻辑2.1 目录里到底有什么先数清楚再动手拿到压缩包解压后常见做法是先别急着写训练脚本而是把文件数量对齐一遍。这份数据集的核心构成很干净图片、VOC 标注、YOLO 标注三者数量一致都是 400。文件名形如firc_dianli_250.jpg编号不连续正文里能看到 146、147、148、149、240、250、251、257、375 这些说明是从更大的池子里筛出来的不是流水线顺序生成这点对训练分布其实是好事——随机采样比连续帧更不容易过拟合到某个场景。资源项数量格式说明图片400jpg遥感/红外电力场景VOC 标注400xmlPascal VOC含 bndboxYOLO 标注400txt归一化 cx cy w h类别数1—类别名 sdgt总框数680—平均每图 1.7 个框注意这里有个容易忽略的点摘要里明确写了「不包含分割路径的 txt 文件」也就是没有 train/val 划分清单。这意味着划分得你自己做别指望解压完就有train.txt、val.txt。我一般会按 8:2 切并且固定随机种子保证每次复现一致。2.2 为什么同时给 VOC 和 YOLO选哪个VOC 格式的 xml 是「绝对坐标 文件名 尺寸」的结构可读性强labelImg 原生输出就是它适合人工复核、做数据审计、或者喂给那些还吃 VOC 的老框架比如早期 Faster R-CNN 实现。YOLO 格式的 txt 是「归一化中心点 宽高」一行一个框类别索引 cx cy w h直接对应 YOLO 系列的标签读取逻辑训练时零转换。选型上我的建议很直接如果你用 YOLOv5/v8/v11直接用 txt别绕 xml 再转一遍多一次转换就多一次坐标精度损失和类别索引错位的风险。如果你要做标注质量抽检、或者团队里有人要用 VOC 工具链那就以 xml 为准txt 作为派生。两者内容应当一致但实践中我见过不少数据包 xml 和 txt 对不上框数不一致、类别名映射错所以下面专门给一段校验代码。2.3 用脚本核对双格式一致性在正式训练前跑一段校验脚本把「xml 框数 txt 框数」这件事验证一遍能省掉后面 loss 不降时的一堆玄学排查。import os import xml.etree.ElementTree as ET img_dir images xml_dir annotations_xml txt_dir labels_yolo mismatch [] total_boxes 0 for name in os.listdir(xml_dir): if not name.endswith(.xml): continue stem os.path.splitext(name)[0] # 解析 VOC xml统计 bndbox 数量 tree ET.parse(os.path.join(xml_dir, name)) root tree.getroot() xml_boxes root.findall(.//object) # 读取对应 YOLO txt 行数 txt_path os.path.join(txt_dir, stem .txt) if not os.path.exists(txt_path): mismatch.append((stem, txt missing)) continue with open(txt_path) as f: txt_lines [l for l in f.readlines() if l.strip()] if len(xml_boxes) ! len(txt_lines): mismatch.append((stem, len(xml_boxes), len(txt_lines))) total_boxes len(xml_boxes) print(总框数:, total_boxes) print(不一致条目:, mismatch)逻辑说明脚本遍历 xml 目录用 ElementTree 找所有object节点得到 VOC 框数再去对应 txt 数非空行。参数上img_dir只是占位真正参与比对的是 xml 和 txt。如果mismatch为空且total_boxes打印出 680说明这份数据的双格式是对齐的可以放心往下走。若总框数不是 680先别训回去查是不是解压丢文件了。3. 从 VOC 转 YOLO 与 YOLOv8 训练全流程3.1 自己写转换脚本时最容易错的两件事虽然这份数据已经给了 YOLO txt但很多人拿到的是纯 VOC 版本或者想验证自带 txt 是否正确所以转换脚本还是得会写。VOC 转 YOLO 的核心公式就三行cx (xminxmax)/2/widthcy (yminymax)/2/heightw (xmax-xmin)/widthh (ymax-ymin)/height。听起来简单翻车点集中在两处一是没读图片真实宽高直接拿 xml 里的size字段而有些 xml 的 size 是错的二是类别名到索引的映射没固定导致 sdgt 一会儿是 0 一会儿是 1。import os import xml.etree.ElementTree as ET from PIL import Image classes [sdgt] # 类别顺序必须固定训练配置要一致 xml_dir annotations_xml img_dir images out_dir labels_yolo os.makedirs(out_dir, exist_okTrue) for name in os.listdir(xml_dir): if not name.endswith(.xml): continue stem os.path.splitext(name)[0] tree ET.parse(os.path.join(xml_dir, name)) root tree.getroot() # 用真实图片尺寸别信 xml 里的 size img_path os.path.join(img_dir, stem .jpg) w, h Image.open(img_path).size lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in classes: continue cls_id classes.index(cls_name) bb obj.find(bndbox) xmin float(bb.find(xmin).text) ymin float(bb.find(ymin).text) xmax float(bb.find(xmax).text) ymax float(bb.find(ymax).text) 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}) with open(os.path.join(out_dir, stem .txt), w) as f: f.write(\n.join(lines))逻辑说明classes列表决定类别索引单类别时 sdgt 固定为 0这一点必须和训练时的data.yaml完全一致否则模型学到的全是错的。坐标保留 6 位小数是 YOLO 官方推荐的精度够用且不冗余。用 PIL 读真实尺寸而不是 xml 的 size是血泪经验——遥感数据里 xml 尺寸和实际图片对不上的情况并不罕见。3.2 划分训练集验证集并生成 data.yamlYOLOv8 不认 VOC 那套目录约定它要的是images/train、images/val、labels/train、labels/val这种结构外加一个 yaml 描述文件。400 张按 8:2 切就是 320 训练、80 验证。# 建立 YOLO 目录结构 mkdir -p dataset/images/train dataset/images/val mkdir -p dataset/labels/train dataset/labels/val # 用固定种子随机划分保证可复现 python - PY import os, random, shutil random.seed(42) imgs sorted([f for f in os.listdir(images) if f.endswith(.jpg)]) random.shuffle(imgs) val set(imgs[:80]) for f in imgs: stem os.path.splitext(f)[0] split val if f in val else train shutil.copy(fimages/{f}, fdataset/images/{split}/{f}) shutil.copy(flabels_yolo/{stem}.txt, fdataset/labels/{split}/{stem}.txt) print(done) PY逻辑说明random.seed(42)是固定划分的关键团队协作时大家用同一个种子验证集才可比。80 这个数字来自 400 的 20%如果你数据更少验证集别低于 10%否则指标抖动大到没法看。# data.yaml path: ./dataset train: images/train val: images/val nc: 1 names: [sdgt]参数说明nc是类别数这里必须是 1names的顺序要和转换脚本里的classes完全一致。path用相对路径方便整个目录打包迁移。3.3 启动 YOLOv8 训练与关键参数环境配好后pip install ultralytics一条命令就能起训。400 张图属于小数据集别一上来就堆大模型。yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ seed42 \ projectruns/power_tower \ nameexp1参数说明modelyolov8n.pt是最小的 nano 版本400 张图用 n 或 s 足够上 m/l 只会过拟合imgsz640是默认输入尺寸遥感小目标如果杆塔像素偏小可以试 1024但显存要跟上patience20表示 20 轮没提升就早停小数据集上这个能省不少时间seed42和划分种子一致保证可复现。训练完看runs/power_tower/exp1/下的results.csv和confusion_matrix.png重点看 sdgt 这一类的 mAP50 和召回单类别下混淆矩阵只有一行一列主要看漏检。4. 训练与标注环节的避坑排查4.1 现象loss 一直不降mAP 卡在接近 0原因最常见的是类别索引错位。data.yaml 里names: [sdgt]对应索引 0但你的 txt 里写的是 1模型学的是「背景 vs 1」而 1 从来没出现过自然学不动。其次是图片路径没对上YOLO 找不到图会静默跳过训练集实际为空。解决先跑 3.1 的校验脚本确认 txt 第一列全是 0再用yolo detect train ... verboseTrue看它实际加载了多少张图数量对不上就是路径问题。我一般会在训练前手动head一个 txt 文件肉眼确认第一列。4.2 现象验证集 mAP 高得离谱一上真实场景全漏原因400 张图如果划分时没打乱或者图片本身来自连续帧训练集和验证集高度相似指标虚高。这份数据文件名不连续风险相对小但仍要警惕。解决划分时强制 shuffle 并固定种子如果发现验证指标异常高比如 mAP50 0.95 而实际测试很差把验证集换成完全独立的场景图再测一遍。别拿验证集当最终结论。4.3 现象框位置整体偏移检测框总是偏一角原因转换时用了 xml 里的size而不是真实图片尺寸两者不一致时归一化坐标就全错。遥感数据尤其常见因为图片可能被重新裁剪或缩放但 xml 没更新。解决回到 3.1 的脚本坚持用 PIL 读真实宽高。已经转完的重新转一遍别在错误标注上继续训。4.4 现象训练中途报显存不足或 batch 崩溃原因imgsz调太大或batch设太高。400 张图用 640 加 batch 168G 显存基本够如果改成 1024batch 得降到 4 或 8。解决先降 batch 再降 imgsz或者用yolo detect train ... ampTrue开混合精度。别硬扛小数据集上 imgsz 从 640 提到 1024 的收益往往不如多训几十轮。4.5 现象标注框有大量重叠或超出边界原因labelImg 手画时难免有框超出图片边缘归一化后坐标会小于 0 或大于 1YOLO 虽然能容忍一部分但过多会导致训练不稳定。解决写个清洗脚本把cx/cy/w/h超出 [0,1] 的框裁掉或修正同时统计每张图的框数分布异常多的图比如一张图几十个框单独看一眼是不是误标。5. 用验证脚本量化标注质量与一个提点技巧数据到手除了训模型更值钱的是先量化标注质量。我习惯在训练前跑一个统计脚本把每类框的宽高分布、每图框数、坐标越界情况全打出来这样后面指标异常时能快速定位是数据问题还是模型问题。import os import numpy as np txt_dir labels_yolo widths, heights, per_img [], [], [] for name in os.listdir(txt_dir): if not name.endswith(.txt): continue with open(os.path.join(txt_dir, name)) as f: lines [l.split() for l in f if l.strip()] per_img.append(len(lines)) for parts in lines: _, cx, cy, w, h map(float, parts) widths.append(w) heights.append(h) if not (0 cx 1 and 0 cy 1 and 0 w 1 and 0 h 1): print(越界:, name, parts) print(每图框数 min/mean/max:, min(per_img), np.mean(per_img), max(per_img)) print(宽 mean/median:, np.mean(widths), np.median(widths)) print(高 mean/median:, np.mean(heights), np.median(heights))逻辑说明这段脚本不依赖任何框架纯标准库加 numpy跑完你能得到三个关键画像——每图平均框数这份数据是 680/4001.7、框的宽高中位数、以及有没有越界框。如果宽高中位数特别小比如小于 0.02说明杆塔在图中占比很小属于小目标训练时imgsz就得往上提或者用切片推理。一个提点技巧小目标检测里与其盲目换大模型不如先把输入分辨率提上去再配合mosaic增强YOLOv8 默认开。400 张图数据量小增强是刚需但mosaic对小目标有时会把目标拼到边缘导致截断可以试close_mosaic10最后 10 轮关掉增强让模型在真实分布上收尾。这个参数在 YOLOv8 里直接加在训练命令后面即可。从那以后我每次拿到新数据集都强制先跑一遍框数校验和分布统计再动训练脚本——省下来的排查时间远比写脚本的十分钟值。希望帮到你。本文还有配套的精品资源点击获取