简介本数据集面向电力巡检、遥感图像分析与目标检测方向的开发者与研究者聚焦输电线路电杆塔的自动识别任务。资源采用Pascal VOC与YOLO双格式标注包含400张jpg图像、400个VOC格式xml文件与400个YOLO格式txt文件标注类别为sdgt共680个矩形框全部由labelImg工具完成画框标注可直接用于主流检测框架的训练与验证。压缩包为7z格式共1202个文件除图像与标注外还附带说明类txt整体约136.93MB目录结构简洁便于快速接入现有数据管线。目前已有605人学习下载适合作为电力场景目标检测的入门练手或小规模实验数据帮助读者省去自行采集与标注的成本快速验证模型在电杆塔识别上的表现。1. 电力场景遥感电杆塔检测数据集400 张 VOCYOLO 双格式到底能训出什么电力巡检的遥感图像里电杆塔是个很尴尬的目标它细长、密集、背景杂乱还经常被树冠、山体阴影和输电线路切割得七零八落。很多团队第一次做电杆塔检测卡住的地方不是模型选型而是手里没有一份标注干净、格式对得上、能直接喂进 YOLO 的小数据集。这份「电力场景遥感电杆塔检测数据集 VOCYOLO 格式 400 张 1 类别」解决的正是这个起步问题——400 张遥感图单一类别电杆塔同时提供 VOC 和 YOLO 两套标注省掉格式转换那一步。它适合两类人一是想快速验证电杆塔检测可行性的算法工程师二是需要一个小规模基准来对比模型改进效果的研究者。400 张不算多但作为冷启动和 pipeline 打通的第一块砖够用。2. 电杆塔检测数据集的结构拆解VOC 与 YOLO 两套标注差在哪拿到一个压缩包第一件事不是解压完就开训而是先搞清楚里面标注的组织方式。VOC 和 YOLO 虽然描述的是同一批图但坐标表达、文件组织、类别编码完全不同搞混了就是训练 loss 不降、mAP 恒为零的血泪经验。2.1 VOC 格式的目录约定与 XML 字段含义VOC 格式的核心是每张图对应一个 XML 文件目录通常长这样dataset/ ├── JPEGImages/ # 原始图像jpg/png ├── Annotations/ # 对应的 XML 标注 └── ImageSets/ └── Main/ # train.txt / val.txt 等划分文件一个电杆塔的 XML 标注关键字段如下annotation filenametower_0001.jpg/filename size width1024/width height1024/height depth3/depth /size object nametower/name !-- 类别名本数据集只有 1 类 -- poseUnspecified/pose truncated0/truncated !-- 是否被截断 -- difficult0/difficult !-- 是否难样本 -- bndbox xmin312/xmin ymin208/ymin xmax356/xmax ymax402/ymax /bndbox /object /annotation这里要盯紧三个点name必须和你的类别表一致bndbox是绝对像素坐标且xminxmax、yminymaxdifficult字段在评估时是否忽略取决于你用的框架YOLO 系列默认不读这个字段。电杆塔目标细长标注框经常贴着目标边缘如果标注时框太松会引入大量背景训练时模型学到的是「一大片区域里有杆塔」而不是「杆塔本身」。2.2 YOLO 格式的归一化坐标与类别索引YOLO 格式每张图对应一个 txt每行一个目标class_id x_center y_center width height全部是相对图像宽高的归一化值范围 0~1。单类别时class_id恒为 0。目录一般是dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/images和labels下的文件名必须一一对应只是扩展名不同。YOLO 不存图像尺寸所以归一化时用的宽高必须和实际图像严格一致否则框会整体偏移。电杆塔这种细长目标width往往只有 0.02~0.05height能到 0.3 以上归一化后数值很小用文本编辑器肉眼看不出对错必须靠可视化验证。2.3 两套格式的对应关系与转换校验VOC 转 YOLO 的公式很直接x_center (xmin xmax) / 2 / W y_center (ymin ymax) / 2 / H width (xmax - xmin) / W height (ymax - ymin) / H但真正容易翻车的是类别映射和文件名匹配。VOC 的name是字符串YOLO 要的是整数索引单类别时映射成 0 即可但如果你后面要扩类这个映射表必须固定下来。另外 VOC 的JPEGImages里可能有.png而 YOLO 的images里如果统一转成.jpg文件名对不上就会导致「图片找不到标签」的静默失败——训练照跑但那个样本的 loss 是 0等于白喂。提示拿到双格式数据集后先各抽 5 张做可视化叠加确认 VOC 和 YOLO 的框在同一位置再开始训练。这一步花 10 分钟能省掉后面几小时的排查。3. 用这份数据集跑通 YOLOv8 训练从环境到第一个 mAP数据集结构清楚了接下来就是把它喂进模型。这里以 YOLOv8 为例因为它的数据配置最简洁社区资料也最全。整个流程分环境准备、数据配置、启动训练、看结果四步。3.1 环境准备与目录重组先建一个干净的环境避免和已有项目冲突conda create -n tower python3.10 -y conda activate tower pip install ultralytics装完后验证yolo checks这一步会打印 PyTorch 版本、CUDA 是否可用。如果CUDA显示不可用训练会退回 CPU400 张图虽然能跑但速度慢到怀疑人生。确认 GPU 可用后把数据集整理成 YOLO 训练要求的目录mkdir -p datasets/tower/images/train datasets/tower/images/val mkdir -p datasets/tower/labels/train datasets/tower/labels/val # 假设原始 YOLO 格式已按 8:2 划分好直接拷贝 cp -r raw_yolo/images/train/* datasets/tower/images/train/ cp -r raw_yolo/labels/train/* datasets/tower/labels/train/ cp -r raw_yolo/images/val/* datasets/tower/images/val/ cp -r raw_yolo/labels/val/* datasets/tower/labels/val/如果拿到的是 VOC 格式需要先转换。下面这个脚本处理单类别电杆塔同时做文件名对齐import os import xml.etree.ElementTree as ET from PIL import Image VOC_IMG_DIR VOC/JPEGImages VOC_XML_DIR VOC/Annotations OUT_IMG_DIR datasets/tower/images/train OUT_LBL_DIR datasets/tower/labels/train CLASS_MAP {tower: 0} # 单类别扩类时在这里加 os.makedirs(OUT_IMG_DIR, exist_okTrue) os.makedirs(OUT_LBL_DIR, exist_okTrue) for xml_file in os.listdir(VOC_XML_DIR): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(VOC_XML_DIR, xml_file)) root tree.getroot() filename root.find(filename).text img_path os.path.join(VOC_IMG_DIR, filename) if not os.path.exists(img_path): print(fmissing image: {filename}) continue W, H Image.open(img_path).size lines [] for obj in root.findall(object): name obj.find(name).text if name not in CLASS_MAP: continue bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) # 裁剪到图像边界防止越界标注 xmin, ymin max(0, xmin), max(0, ymin) xmax, ymax min(W, xmax), min(H, ymax) xc (xmin xmax) / 2 / W yc (ymin ymax) / 2 / H bw (xmax - xmin) / W bh (ymax - ymin) / H lines.append(f{CLASS_MAP[name]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) # 图片和标签同名只换扩展名 stem os.path.splitext(filename)[0] Image.open(img_path).convert(RGB).save( os.path.join(OUT_IMG_DIR, stem .jpg)) with open(os.path.join(OUT_LBL_DIR, stem .txt), w) as f: f.write(\n.join(lines))这段脚本的关键处理有三处一是CLASS_MAP把类别名映射成索引单类别固定为 0二是坐标裁剪到图像边界遥感标注里偶尔会出现框超出图像的情况不裁剪会导致归一化值大于 1YOLO 会直接报错或静默丢弃三是图片统一转成 RGB 的 jpg避免灰度图或 RGBA 图在训练时通道数不匹配。转换完记得抽查几个 txt确认每行 5 个值、坐标都在 0~1 之间。3.2 data.yaml 配置与关键参数YOLOv8 靠一个 yaml 文件描述数据集path: /abs/path/datasets/tower train: images/train val: images/val nc: 1 names: 0: towerpath用绝对路径最稳相对路径在不同工作目录下启动训练时容易找不到。nc是类别数必须和names的条目数一致单类别就是 1。names的键是类别索引和 txt 里的class_id对应。启动训练yolo detect train \ datadatasets/tower/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/tower \ nameexp1参数逐个说modelyolov8n.pt用 nano 版400 张图从零训容易过拟合用预训练权重迁移学习更稳imgsz640是输入分辨率遥感图如果原始尺寸很大比如 1024 或 2048缩到 640 后电杆塔可能只剩十几个像素这时要么提高imgsz到 1024要么先切图batch16看显存V100 上可以拉到 32 甚至 64lr00.01是初始学习率小数据集上如果 loss 震荡降到 0.001patience20表示 20 轮没提升就早停防止无效训练。3.3 训练过程监控与 mAP 解读训练启动后终端会打印每轮的 box_loss、cls_loss、mAP50、mAP50-95。电杆塔检测里box_loss反映定位精度cls_loss反映分类单类别时cls_loss通常很快降到接近 0如果它一直不降八成是标签里的class_id不是 0 或者标签文件根本没被读到。mAP50是 IoU 阈值 0.5 时的平均精度电杆塔这种细长目标IoU 对框的偏移非常敏感mAP50能到 0.7 以上就算不错。mAP50-95更严格通常会低不少。如果训练到 50 轮mAP50还在 0.1 以下先别怀疑模型去查标签用下面的脚本把预测框和真实框画在一起看。from ultralytics import YOLO import cv2 model YOLO(runs/tower/exp1/weights/best.pt) results model.predict(datasets/tower/images/val, conf0.25, saveTrue) # 预测结果默认存到 runs/detect/predict打开保存的图如果真实框位置对但预测框乱飞是训练不充分如果真实框本身就画错了那就是标注或转换的问题。这一步是排查的后悔药别跳过。4. 小数据集训电杆塔的避坑清单从标签静默失败到过拟合400 张图、单类别看起来简单但实际踩的坑一点不少。下面 5 条是我在类似规模数据集上反复遇到的按「现象 → 原因 → 解决」写清楚。4.1 训练 loss 正常但 mAP 恒为 0现象训练能跑完box_loss 在降但验证集 mAP50 一直是 0。原因最常见的是标签路径没对上。YOLO 找标签的规则是把images替换成labels、扩展名换成.txt如果目录结构不是标准的images/trainlabels/train或者文件名大小写不一致标签就静默读不到模型学的是「所有图都没有目标」。解决训练前用脚本统计标签数量确认每张图都有对应 txt且 txt 非空。另外检查data.yaml里的train/val路径是相对于path的别写成绝对路径又叠加了path。4.2 电杆塔框大量重叠导致 NMS 后只剩一个现象推理时一张图里明明有多个电杆塔结果只输出一个框。原因电杆塔密集排列时标注框之间 IoU 可能超过默认 NMS 阈值 0.7被当成重复框抑制掉了。解决推理时调高iou参数比如model.predict(..., iou0.9)或者训练时就用较大的iou阈值。如果目标确实重叠严重考虑换用 soft-NMS但 YOLOv8 默认不支持需要改后处理。4.3 小目标在 640 分辨率下消失现象原始遥感图里电杆塔只有几十像素缩到 640 后 mAP 极低。原因下采样把目标缩没了特征图上只剩几个像素卷积核根本提取不到有效特征。解决提高imgsz到 1024 或 1280或者先对原图切块比如 512×512 带重叠把电杆塔变成中等目标再训。切图时注意重叠区域的目标要完整保留在一个块里否则标注会被切断。4.4 过拟合训练 mAP 0.95验证 mAP 0.3现象训练集指标很高验证集惨不忍睹。原因400 张图对 YOLOv8 来说偏少模型容量相对数据量过大记住了训练样本。解决用更强的数据增强mosaic、mixup、随机旋转YOLOv8 默认已开 mosaic可以再加degrees、translate或者换更小的模型nano 已经很小了再小就是 tiny 级别还可以冻结 backbone 前几层只训 head。另外早停patience设小一点别让它一直训到过拟合。4.5 验证集划分不合理导致指标虚高现象mAP 看起来不错但换一批新图就崩。原因验证集和训练集来自同一区域、同一批采集分布几乎一样模型只是记住了这个场景。解决划分时按区域或按采集批次分让验证集包含训练集没见过的背景。如果数据本身来自多个区域用分层抽样如果只有一个区域至少按时间或拍摄角度分。400 张的规模验证集留 80~100 张比较合适太少指标波动大。5. 把 400 张用出 4000 张的效果切图、增强与迁移的实操组合小数据集的出路不是硬训而是把每一张图的价值榨干。我一般会按「切图扩样本 → 增强提泛化 → 迁移省数据」这个顺序做实测能把有效样本量放大好几倍。先说切图。遥感图往往是大场景电杆塔只占一小块直接缩放会丢细节。用滑动窗口切图窗口 640×640、重叠 128 像素一张 2048×2048 的图能切出 9~16 张子图目标在子图里变成中等尺寸检测难度大幅下降。切图时用下面这段逻辑保证标注跟着走import os from PIL import Image def slice_image(img_path, lbl_path, out_dir, size640, stride512): img Image.open(img_path) W, H img.size stem os.path.splitext(os.path.basename(img_path))[0] # 读取原始 YOLO 标签并还原成绝对坐标 boxes [] with open(lbl_path) as f: for line in f: c, xc, yc, bw, bh map(float, line.split()) boxes.append((c, xc * W, yc * H, bw * W, bh * H)) idx 0 for y in range(0, H, stride): for x in range(0, W, stride): x2, y2 min(x size, W), min(y size, H) x1, y1 max(0, x2 - size), max(0, y2 - size) crop img.crop((x1, y1, x2, y2)) new_boxes [] for c, xc, yc, bw, bh in boxes: # 目标中心落在窗口内才保留 if x1 xc x2 and y1 yc y2: nxc (xc - x1) / size nyc (yc - y1) / size nbw bw / size nbh bh / size # 裁剪到 0~1防止越界 nxc, nyc min(max(nxc, 0), 1), min(max(nyc, 0), 1) nbw, nbh min(nbw, 1), min(nbh, 1) new_boxes.append(f{int(c)} {nxc:.6f} {nyc:.6f} {nbw:.6f} {nbh:.6f}) if new_boxes: crop.save(f{out_dir}/images/{stem}_{idx}.jpg) with open(f{out_dir}/labels/{stem}_{idx}.txt, w) as f: f.write(\n.join(new_boxes)) idx 1这段代码的核心判断是「目标中心落在窗口内才保留」避免一个目标被切成两半后两边都标不完整。重叠 stride 设成 size 的 0.8 倍左右保证边缘目标至少完整出现在一个窗口里。切完图400 张能变成 3000~5000 张子图训练时 batch 里的样本多样性明显提升。再说增强。YOLOv8 内置的 mosaic 会把 4 张图拼成一张对电杆塔这种细长目标拼接后可能出现杆塔被截断的情况但整体上利大于弊。额外可以加degrees10小角度旋转遥感图方向不固定、translate0.1、scale0.5。注意别开flipud上下翻转遥感图有固定的拍摄方向上下翻转会造出不存在的场景反而害了模型。最后是迁移学习。yolov8n.pt是在 COCO 上训的虽然 COCO 没有电杆塔这个类但底层卷积特征边缘、纹理、形状是通用的。冻结 backbone 前 10 层只训 head 和后面的层在 400 张图上收敛更快也不容易过拟合。等 mAP 稳定后再解冻全部层做微调学习率降到 0.001。验证这套组合是否有效别只看 mAP。我会额外做两件事一是把验证集按「训练中见过的区域」和「没见过的区域」分开统计看泛化差距二是用conf0.1的低阈值跑一遍看漏检和误检的分布如果误检集中在树冠和阴影上说明模型还没学会区分杆塔和相似背景需要补这类负样本。这套流程我在几个类似规模的数据集上跑过400 张起步、切图加增强后电杆塔检测的 mAP50 能从 0.5 出头提到 0.75 左右代价是训练时间翻倍。值不值得取决于你的场景对漏检的容忍度——电力巡检里漏一个杆塔可能意味着一条线路的盲区我倾向于把数据榨干再谈模型改进。希望帮到你。本文还有配套的精品资源点击获取