ARTICLE DETAIL

资讯详情

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

输电线异物检测数据集:VOC/YOLO双格式转换与YOLOv8训练避坑指南

输电线异物检测数据集:VOC/YOLO双格式转换与YOLOv8训练避坑指南 简介输电线异物检测数据集面向输电线路巡检与计算机视觉目标检测实践适合电力行业算法工程师、科研人员及深度学习学习者旨在弥补输电线异物公开标注数据不足。资源提供1300张输电线路现场图片及对应标注覆盖气球、风筝、鸟巢、垃圾四类常见异物总标注框数达1319个全部通过labelImg完成矩形框标注。包内文件共2000个其中含1300个Pascal VOC格式XML标注文件和700个YOLO格式TXT标注文件并附带使用前必读说明压缩包大小831.71MB。目前已有967人学习/下载。该数据集同时给出VOC与YOLO两种标注格式可直接接入主流目标检测框架省去格式转换步骤约15%的标注样本经过数据增强有利于提升模型泛化性能。需特别说明数据集仅保证标注准确合理不对训练精度作任何承诺适用于算法验证、模型微调及输电线路智能化巡检项目。1. 输电线异物检测数据集VOCYOLO双格式一次到位做输电线路巡检的同行应该都有体会模型训练这件事本身不难难的是数据。线路异物这类目标——风筝、塑料薄膜、鸟巢、施工机械——场景分散标注成本高好不容易攒了一批图还得面临格式转换的坑。VOC的xml是一套写法YOLO的txt又是另一套两边坐标换算不对训练出来的模型就莫名其妙漏检。这份《输电线异物检测数据集VOCYOLO格式1300张4类别.7z》解决的就是这个痛点1300张真实巡检影像4个类别VOC和YOLO两种格式都给你备好了解压之后直接用省掉最耗时的那一步。适合正在做电力巡检视觉检测、毕设选题或算法预研的工程师尤其是想快速验证YOLO系列模型效果的场景这份数据能让你直接跳过数据治理直接进训练。2. 解压后先看结构和格式两种标注各自怎么读2.1 VOC格式的三个目录Annotations、JPEGImages、ImageSetsVOC格式是目标检测领域最经典的标注体系解压后你会看到三个核心目录。Annotations里放的是xml标注文件每个xml对应一张图片文件名和图片名完全一致。打开xml里面的关键节点是object一个框一个块name存类别名bndbox里分别是xmin、ymin、xmax、ymax这四个值直接就是像素坐标没有归一化读起来直观。JPEGImages放的就是原图1300张图的原始尺寸可能不统一这个不用管YOLO训练时会自动resize。ImageSets/Main这个目录容易被忽略它里面是划分好的txt文件train.txt、val.txt、trainval.txt每行一个图片名。注意这里存的是不带扩展名的文件名路径拼接的时候要自己补.jpg。有些数据集还会带test.txt训练前看一眼如果测试图片混进训练集最后的mAP会虚高这个坑后面细说。2.2 YOLO格式images和labels目录配对txt里那五个数字YOLO格式的标注是txt文件每行对应一个目标框格式是五个数字类别id、中心点x、中心点y、框宽、框高。这里有个容易搞混的关键点x、y、w、h全部是归一化后的比例值是相对于图片宽高的比例不是像素坐标。比如图片宽640、高480一个框宽320像素那txt里写的是0.5而不是320。这份数据集用VOC和YOLO双格式意味着它在转换时已经帮你做完了坐标换算。拿到YOLO目录images/train和labels/train必须一一对应一张图对应一个同名txt。txt里的类别id从0开始编号对应关系看data.yaml或classes.txt。2.3 解压后第一时间做的四步核对清单先不要急着训练我一般拿到数据集第一件事是核对下面四项十分钟能做完的事能省后面一天的排查时间对比Annotations下xml数量和JPEGImages下图片数量是否都是1300多一个少一个都说明文件有缺失。抽查3到5个xml逐条看name里的类别名确认4个类别和你预期一致。标题写的是4类具体是哪四类以xml实际值为准有的数据集类别是风筝、塑料薄膜、鸟巢、施工异物有的可能是飘挂物、防鸟刺、绝缘子破损之类不确认清楚训练脚本里names填错就全废了。看ImageSets/Main里的划分比例train和val按多少分如果val只有100张以下验证结果波动会很大建议自己重新划分。随机打开一张YOLO目录下的txt检查坐标值范围全部在0到1之间是正常的出现负数或大于1的数说明标注或转换有问题需要清洗。提示.7z是7-Zip的压缩格式Windows下用7-Zip或Bandizip解压Mac用The Unarchiver或Keka。别用系统自带的解压工具硬解容易提示压缩包损坏。3. VOC转YOLO自己动手写转换脚本顺便做一遍质检3.1 为什么还要自己转一次双格式数据集也有标注错位我知道数据集已经给了YOLO格式那为什么还要自己写转换脚本两个原因。第一很多双格式数据集是脚本批量转出来的某个xml里坐标写反、类别名有大小写差异、少一个object节点这些在转换时都会悄悄变成错误数据落到txt里训练的时候模型学一堆错误特征。第二自己过一遍转换逻辑你才会真正理解两种格式的差异后面换数据集、加新类别、修标注都能自己动手不用到处找教程。另外有时候YOLO格式目录里的labels可能有损坏的txt空文件、只有三个数、坐标超界这类文件在训练时不会报错但会让loss曲线莫名跳一下。所以我的习惯是从VOC侧重新生成一份labels用生成的覆盖数据集自带的YOLO标签。3.2 转换脚本解析xml、归一化坐标、写入txt下面这个脚本处理VOC转YOLO的常规情况。核心逻辑是遍历Annotations下所有xml解析每个object的类别和坐标中心点用(xminxmax)/2算出像素值再除以图片宽高得到归一化值最后写成YOLO格式的txt。import os import xml.etree.ElementTree as ET from pathlib import Path # 类别列表顺序就是YOLO的id编号。按数据集xml里的实际name填写 CLASS_NAMES [kite, plastic_wrap, bird_nest, construction_machinery] def convert_voc_to_yolo(xml_path, out_txt_path): tree ET.parse(xml_path) root tree.getroot() # 从size节点读取图片真实宽高转YOLO必须用它做归一化分母 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text.strip() if name not in CLASS_NAMES: print(f跳过未知类别: {name} 在 {xml_path}) continue cls_id CLASS_NAMES.index(name) box obj.find(bndbox) # xml里读出来是字符串必须转float否则除法会出错 xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 中心点坐标和宽高都归一化保留6位小数足够 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(out_txt_path, w, encodingutf-8) as f: if lines: f.write(\n.join(lines) \n) # 主流程遍历Annotations输出到labels目录 annotations_dir Path(Annotations) output_dir Path(yolo_labels) output_dir.mkdir(exist_okTrue) for xml_file in annotations_dir.glob(*.xml): out_txt output_dir / (xml_file.stem .txt) convert_voc_to_yolo(xml_file, out_txt) print(f转换完成共处理 {len(list(annotations_dir.glob(*.xml)))} 个xml文件)参数和逻辑说明一下CLASS_NAMES的顺序非常关键YOLO格式的第一个数字就是这个列表的索引顺序不能乱。如果数据集xml里有你不在列表里的类别脚本会跳过并打印提示——这其实是质检的第一道关卡能帮你发现漏标的类别。坐标归一化那三行是核心公式记牢中心x就是(xminxmax)/2除以宽宽就是(xmax-xmin)除以宽。最后写入tt文件时如果xml里没有目标文件就是空的这种情况要留意。3.3 转完必须做的三类校验转换完不等于能直接用我建议再跑一个校验脚本来检查生成的txt是否健康。重点查三类问题坐标越界、宽高为负、行格式异常。from pathlib import Path def check_yolo_labels(label_dir): bad_files [] for txt_path in Path(label_dir).glob(*.txt): content txt_path.read_text().strip() if not content: bad_files.append((txt_path.name, 空文件)) continue for line in content.splitlines(): parts line.split() if len(parts) ! 5: bad_files.append((txt_path.name, f列数错误: {line})) continue try: cls, x, y, w, h int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) except ValueError: bad_files.append((txt_path.name, f数字解析失败: {line})) continue if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): bad_files.append((txt_path.name, f坐标越界: {line})) if w 0 or h 0: bad_files.append((txt_path.name, f宽高非正: {line})) return bad_files issues check_yolo_labels(yolo_labels) for name, reason in issues: print(f{name}: {reason}) print(f共发现 {len(issues)} 个异常文件)这个脚本的思路很简单但很实用。空文件意味着这张图没有标注框如果数量多说明原始xml本身有问题。坐标越界主要发生在标注框紧贴图像边缘的场景有些标注工具在物体被裁切一半时会记录到图外坐标这类数据会导致训练时loss震荡。宽高非正基本就是xml里xmax小于xmin典型的坐标写反。提示正常的数据集经过这两步异常文件应该为0。如果发现几十个异常说明源数据质量不行建议直接人工复查对应的xml不要靠脚本自动修。4. 用YOLO训练异物检测模型yaml配置、训练命令与参数解读4.1 data.yaml怎么组织路径、类别数和names一一对应进入训练环节先搞定数据配置文件。YOLOv8的data.yaml是一个纯文本文件YOLOv5、YOLOv8、YOLOv11通用的写法如下# 数据集根路径建议填绝对路径避免相对路径在各种命令下失效 path: D:/datasets/line_foreign_objects train: images/train val: images/val test: images/test # 类别数量必须和下面names列表长度一致 nc: 4 # 类别名顺序就是txt里第一列的id。0对应names[0]以此类推 names: 0: kite 1: plastic_wrap 2: bird_nest 3: construction_machinery写这个yaml有三个容易错的地方。第一path是根目录train和val是相对路径拼接出来的如果你把images直接放在根目录下那train应该写images/train而不是train。第二names的顺序必须和txt里的类别id严格一致很多数据集txt里的0号是风筝你的yaml里0号却写成塑料薄膜训练出来模型的预测框全会偏一个类别而且是那种很难发现的错误——loss看起来正常每个类别的标签也都有但精确率就是上不去。第三nc和names的长度不匹配启动训练时YOLO会直接报错这个反而好排查。4.2 训练命令与超参不是越大越好环境用YOLOv8的话先确认版本和依赖。如果还没有环境建议用Anaconda新建一个Python 3.10的环境conda create -n yolo python3.10然后pip install ultralytics。GPU版本需要单独装torchCPU也能跑就是1300张图迭代150轮会比较慢看你自己预算。基础训练命令yolo detect train \ dataline_dataset.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ patience30 \ cacheTrue \ pretrainedTrue \ cos_lrTrue \ close_mosaic10逐项说参数的选择逻辑。modelyolov8s.pt是s版本属于速度和精度的平衡点输电线异物检测目标通常不算极小比遥感小目标大s版本够用。想更快就yolov8n.pt想更高精度用yolov8m.pt但m版本在1300张这个小数据集上容易过拟合没有预训练权重的话效果反而不如s。epochs150不是越多越好因为数据集小300轮后期基本在过拟合配合patience30早停机制150轮足够。imgsz640是超参数里的重点如果你的原始图像分辨率超过1920建议先做切片再训练直接resize到640会丢失太多细节小目标框框可能只剩几个像素。cacheTrue把图片加载进内存省去每轮IO的时间。cos_lrTrue用余弦退火学习率调度配合close_mosaic10最后10轮关闭Mosaic增强是YOLOv8在小数据集上的标准配方。Mosaic增强虽然能大幅提升泛化但在训练后期会导致分布漂移提前关闭能让模型稳定收敛。4.3 小数据集训练策略预训练权重、冻结训练、增强1300张图、4个类别这是典型的小数据集场景训练策略和有1万张图的数据集完全不同。我一般按这个顺序来先加载预训练权重。yolov8s.pt是在COCO上预训练过的COCO里有80类目标虽然和输电线异物八竿子打不着但底层的边缘纹理特征提取能力是通用的。加载方式就是上面命令里的pretrainedTrue它会把最后一层的分类头替换成你的4类前几层的权重保留。这个操作在小数据集上是降维打击式的提升比从零训练的效果高出一大截。再考虑冻结浅层。手动指定前几层不参与训练做法是在命令里加yolo detect train \ dataline_dataset.yaml \ modelyolov8s.pt \ freeze10freeze10代表冻结前10层的参数加速训练的同时防止浅层特征被小数据集带偏。什么时候用我建议第一轮直接跑不冻结的版本看loss曲线如果剧烈震荡再冻结重新跑。输电线异物这类目标背景比较干净浅层特征其实变化不大冻结10层基本没有精度损失但显存占用和训练时间能降接近三分之一。数据增强方面YOLOv8默认开了hsv_h0.015、hsv_s0.7、hsv_v0.4色彩抖动对户外巡检图非常合适但注意fliplr0.5——输电线的异物分布没有左右对称性左右翻转反而让模型学到错误的先验建议关掉或调低到fliplr0.2。degrees0.0默认不旋转巡检图像没有旋转样本需求保持默认即可。5. 避坑输电线异物检测最常见的六个翻车现场5.1 标注框贴图像边缘归一化坐标大于1现象训练到几十轮时loss突然跳高验证集mAP在0.7附近徘徊不上去了。原因部分标注框贴着图像边界画的比如风筝一半在画面外xml里xmax大于图片宽度转换时中心点x算出来超过1。YOLO格式对这种越界数据不会报错但loss计算出来的偏移量不可理喻导致梯度更新异常。解决第3章的校验脚本跑一遍把越界的坐标数值直接clamp到0到1之间在代码里对x_center min(max(x_center, 0), 1)。严格的做法是把这类图片挑出来重新标注实际工程里直接截断也能训练但需要留意被截断后框的中心点和宽高比例是否发生明显偏移如果框被截了一半以上建议直接删除这条标注。5.2 类别id和names错位模型学会“张冠李戴”现象训练完跑推理塑料薄膜的检测框全部被预测成风筝每个框置信度还挺高一看数据分布——标签文件里第一个数字全乱了。原因数据集自带YOLO格式时txt里的id是基于classes.txt的顺序你自己写data.yaml时没有按同一个顺序排或者VOC转换时CLASS_NAMES列表顺序和txt顺序不一致导致同一个目标在两种格式里对应不同类别。解决解压后先读classes.txt这个文件就是权威顺序来源。写data.yaml的names时逐行对照0号对应第一行1号对应第二行。如果数据集自带的YOLO标签和VOC标签在类别映射上对不上手动改txt文件代价太大建议直接用第3章的脚本从VOC重新生成一份YOLO标签以VOC的类别名为唯一基准。5.3 图片EXIF旋转信息导致标注位移现象前10轮训练正常第20轮开始某些图片的loss异常高查看预测框发现框的位置整体偏移一段距离。原因户外无人机拍摄的照片经常带EXIF旋转标记jpeg文件里存的像素矩阵没有旋但在看图软件里是正的。标注工具读EXIF后校正了方向xml坐标按校正后的图像算但训练时回访的是原始旋转矩阵的像素数据两者对不上标注和实际目标错位。解决训练前批量做一次方向校正把所有图片统一转成无EXIF的JPEG标注坐标同步旋转。这里有个血泪经验不要在训练脚本里动态处理EXIFYOLO的dataloader读图用的cv2.imread它不读EXIF信息处理逻辑写了等于白写。批量校正用PIL.ImageOps.exif_transpose配合img.save(path, exifb)处理完再跑一遍校验脚本。5.4 数据划分重叠mAP虚高到0.95现象这个坑最隐蔽。训练集和验证集有大量重复图片验证mAP达到0.95以上心里正美滋滋跑了一组全新巡检图片mAP直接掉到0.6。这种就是测试集里泄题了。原因数据集的train.txt和val.txt划分不规范部分图片同时出现在两个列表里。双格式数据集在转换过程中为了凑数据量有的作者会故意这样做也可能只是划分脚本写错了。解决用文件名的MD5做去重把train和val的交集全挑出来只留在train里然后重新生成val.txt。代码只有十几行from pathlib import Path import hashlib def file_md5(path): return hashlib.md5(path.read_bytes()).hexdigest() train_imgs [p for p in Path(images/train).glob(*.jpg)] val_imgs [p for p in Path(images/val).glob(*.jpg)] train_hashes {file_md5(p) for p in train_imgs} dup_val [p for p in val_imgs if file_md5(p) in train_hashes] print(f发现 {len(dup_val)} 张泄露图片: {[p.name for p in dup_val]})做完这一步再重新划分验证mAP回到0.7到0.8水平这个数字才是可信的。5.5 小目标多默认anchors和640分辨率不够用现象输电线异物里的鸟巢、小塑料片往往只占整图的10%甚至5%以下训练完小目标几乎全都漏检大目标检测正常。原因YOLO默认anchors是在COCO数据上调出来的COCO大目标多。640的输入尺寸对1280以上的原图来说缩小了一半原本20像素的小目标缩到10像素以下特征图上的响应已经很微弱。解决两条路。一是提高输入分辨率imgsz1280如果显存足够直接用二是对原图做切片把1920×1080的图切成四个960×540的子图每个子图作为独立图片训练这样目标占比直接放大4倍。切片时要保证子图之间保留10%重叠避免目标正好被切在边界。输电线路巡检场景经常是一张图上多个杆塔、多个异物分散排布切片方案在这类场景里实测效果比单纯加分辨率稳定。5.6 训练中BN崩溃、loss突然NaN现象epoch在40到60轮之间loss曲线突然跌到NaN然后训练崩溃。重启训练跑到同样轮次又崩溃不是随机事件。原因BN层崩溃触发机制通常是某个batch的样本数太少batch4配大片图或者输入图像里出现纯色块区域batch normalization的方差计算变成0或负值。输电线巡检图像经常有大量天空背景蓝色天空区域在切割后可能出现整块同色触发这个概率不低。解决把batch提到8或16BN层的统计量更稳定训练命令里加workers0排除数据加载线程的问题如果还是崩溃换成modelyolov8n.pt看是否继续复现。最稳的兜底方案是关闭BN的自动统计yolo detect train ... # 正常命令然后在训练中期检查loss曲线的变化崩溃后不要续训直接用best.pt做微调继续训练别用last.ptlast.pt记录的是崩溃那一轮的权重BN参数大概率已经污染。这条建议是花钱买来的教训第一次遇到BN崩溃我也犹豫要不要把崩溃的last续训下去后来发现10轮loss基本不下降白烧了一下午。6. 结果验证mAP之外必看混淆矩阵和置信度阈值调整训练完成拿到best.pt不要只看results.png里的mAP就收工。每个类别的mAP平均数值会掩盖单类别的灾难。跑一遍验证集yolo detect val \ modelruns/detect/train/weights/best.pt \ dataline_dataset.yaml然后打开runs/detect/val目录下的confusion_matrix.png这张图里能看出模型在类别层面真实的混淆情况。注意一个细节混淆矩阵的每一行代表该类别所有标注样本行内部数值相加等于100%所以同类别在不同图里“总数不唯一”其实是正常的——因为你看到的是归一化比例。看的时候重点盯对角线塑料薄膜被预测成风筝或者鸟巢被当成施工异物这两种混淆必须干预。如果两个类别之间横跳严重回到第3章检查标注框的name是否本身就标串了很多数据集的鸟巢和塑料薄膜在视觉上确实容易混标注员标错一两百张很正常。最后一步是置信度阈值。YOLO默认的conf0.25适用于通用场景但输电线巡检的异物检测场景要按召回优先还是精确优先来定。如果你是用在大规模巡线回查宁可多框几个假目标也不能漏检那阈值可以放到conf0.1yolo detect predict \ modelbest.pt \ sourcetest_images/ \ conf0.1 \ saveTrue跑完看输出图里的误检数量如果10张图里误检了30个框再往上调conf0.2。这个调参过程没有捷径就是拿一组真实巡检图来回跑记录阈值和误检率的关系。从那以后我每次换数据集都会强制走一遍这个流程VOC转YOLO一次成型、校验脚本清异常、训练前核对划分重叠、训练后看混淆矩阵再调阈值四步走完再跟领导汇报效果。这套流程帮我少踩了不少坑希望帮到你。本文还有配套的精品资源点击获取
返回列表