news 2026/9/28 12:17:39

高铁受电弓检测数据集VOC+YOLO双格式1245张与YOLOv8训练指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
高铁受电弓检测数据集VOC+YOLO双格式1245张与YOLOv8训练指南

简介:面向高铁受电弓检测任务的目标检测数据集,适合计算机视觉研究者、算法工程师及轨道交通智能运维相关项目使用。数据集包含1245张JPEG原图,采用Pascal VOC与YOLO双格式标注,共2个类别(roi、sdg),每类均含1245个矩形框,总框数2490;标注工具为labelImg,全部按矩形框规则完成,标注准确、格式规整。压缩包共2000个文件,主要包括1245个VOC格式XML标注文件和755个TXT标签文件(用于YOLO训练),整体大小48.8MB,可直接切换至YOLO、Faster R-CNN等目标检测框架训练。目前已有818人学习下载,适合作为受电弓关键部件检测、磨损监测、弓网运维等场景的算法训练基础数据,能显著缩短数据采集与标注周期,让使用者集中精力调优模型。需特别注意,数据集只保证标注质量与合理性,不附带任何模型权重,也不对训练精度作承诺。

1. 高铁受电弓检测数据集:1245张双格式标注,能直接跑通YOLOv8训练的最小样本

接触网巡检项目里,最卡脖子的不是模型结构,而是标注数据。高铁受电弓在图像里只占一小块,网上能找到的公开图大多没有框,自己标一千多张又要耗掉一两周。这份“高铁受电弓检测数据集VOC+YOLO格式1245张2类别.7z”把标注做了前置——压缩包内是1245张jpg、1245个Pascal VOC格式xml、1245个YOLO格式txt,类别只有roi和sdg两个,每张图各有一个框,总标注框数2490。它适合你用来跑通“数据→YOLOv8→验证”全流程、做迁移学习前的预演,也适合刚接触目标检测的工程师熟悉双标签格式。对做接触网异常检测的,可以拿它当基线数据集验证检测头改动,不用从零标数据。

2. 先搞懂VOC与YOLO标签:双格式同源,但坐标系差着一个关键步骤

2.1 解压7z后核对三件套命名:jpg/xml/txt必须同名同路径

拿到压缩包后先用对应系统工具解压。Linux下常见做法是7z x 高铁受电弓检测数据集VOC+YOLO格式1245张2类别.7z,如果系统没装7z,需要先apt install p7zip-full或yum install p7zip。Windows下用7-Zip右键解压。这里特意强调“同名同路径”的原因:数据集的txt文件是纯标签文件,不包含分割路径,只有jpg图片、VOC格式xml和YOLO格式txt三者靠文件名关联。解压完第一件事不是看图片,而是跑一遍ls firc_shoudinggong_*.jpg | wc -l,确认jpg、xml、txt的数量都等于1245。少了任何一个,后面训练就会报“label not found”。

文件命名是firc_shoudinggong_数字,数字本身没有顺序,不要指望按文件名排序来划分数据集。我一般会顺手把压缩包单独放一个目录,再重命名成纯数字,避免在Linux下因下划线产生通配符误解。下面这个bash循环可以给三种格式统一改名:

for i in firc_shoudinggong_*.jpg; do id=${i#firc_shoudinggong_} id=${id%.jpg} mv "$i" "$id.jpg" mv "firc_shoudinggong_$id.xml" "$id.xml" mv "firc_shoudinggong_$id.txt" "$id.txt" done

参数说明:${i#firc_shoudinggong_}是bash参数扩展,用来去掉文件名前缀;${id%.jpg}去掉后缀,剩下的数字作为新文件名。循环里同时搬了xml和txt,保证三件套同步。如果某个xml或txt文件不存在,mv会直接报错,正好起到检查作用。firc这个前缀具体是什么项目代号,说明文档没有展开,但从shoudinggong能看出是受电弓场景,不影响使用。

2.2 roi与sdg两个类别:从框数反推标注语义

压缩包说明里写得很清楚:类别名是roi和sdg,每类框数都是1245,等于每张图恰好有一个roi框和一个sdg框。很多下载者拿到压缩包后会想当然认为“2个类别=受电弓和绝缘子”,其实不然。sdg大概率是“受电弓”的拼音首字母缩写,而roi是“Region of Interest”的缩写。从同一张图同时框roi和sdg来看,标注规则很可能是:roi框住整个受电弓区域,sdg框住弓头或滑板关键部位。两者可能是包含关系,也可能有重叠。

这个细节直接关系到模型怎么训。如果你直接用YOLOv8默认的Loss,两个类别有嵌套框会导致正样本分配时同一个锚点既匹配roi又匹配sdg,最终模型推理时容易在同一个位置输出两个高度重叠的框。遇到这种情况,不能把锅甩给“数据集不准”,要先确认语义——随机抽几张图,用labelImg打开看roi和sdg的真实位置关系。如果是包含关系,且你的下游只关心受电弓是否异常,建议只训练sdg类别,把roi当作上下文区域或直接忽略;如果你做的是“先定位受电弓,再细看滑板”的两阶段流程,那roi和sdg保留无妨。

没有数据字典是这份原始资源的一个缺憾。既然项目说明里标注类别只有两个,我们就要在训练前明确自己到底要用哪个类别。常见做法是写一个check_overlap.py,统计所有xml里roi框与sdg框的IoU分布。如果IoU均值高于0.7,那就承认它们是父子级框,训练策略要么分阶段、要么删类别。不要等训练完看结果再猜,那样浪费的时间足够重新标一批数据了。

2.3 读取xml并转换成YOLO归一化坐标:一个python脚本搞定

虽然压缩包已经同时提供了VOC的xml和YOLO的txt,但你不能保证这两个格式始终同步。我有过一次批量修改xml后忘记重新生成txt,训练出来的mAP直接掉了一半。所以手里要有一个能在两种格式之间互转的脚本。下面这段是通用的VOC(xml)转YOLO(txt)代码,不依赖第三方库:

import xml.etree.ElementTree as ET import os, glob # 类别顺序必须与data.yaml中的names一致 class_names = ["roi", "sdg"] def convert_xml(xml_path, txt_path): tree = ET.parse(xml_path) root = tree.getroot() size = root.find("size") width = int(size.find("width").text) height = int(size.find("height").text) with open(txt_path, "w", encoding="utf-8") as f: for obj in root.iter("object"): name = obj.find("name").text if name not in class_names: print(f"[warn] {xml_path}: 未知类别 {name}") continue xmlbox = obj.find("bndbox") x1 = float(xmlbox.find("xmin").text) y1 = float(xmlbox.find("ymin").text) x2 = float(xmlbox.find("xmax").text) y2 = float(xmlbox.find("ymax").text) if x2 <= x1 or y2 <= y1: print(f"[error] {xml_path}: 非法框 {x1},{y1},{x2},{y2}") continue x_center = (x1 + x2) / 2.0 y_center = (y1 + y2) / 2.0 w = x2 - x1 h = y2 - y1 x_center_norm = x_center / width y_center_norm = y_center / height w_norm = w / width h_norm = h / height if not (0.0 <= x_center_norm <= 1.0 and 0.0 <= y_center_norm <= 1.0): print(f"[warn] {xml_path}: 中心点越界,请检查标注") f.write(f"{class_names.index(name)} {x_center_norm:.6f} {y_center_norm:.6f} {w_norm:.6f} {h_norm:.6f}\n") for xml_path in glob.glob("firc_shoudinggong_*.xml"): txt_path = os.path.splitext(xml_path)[0] + ".txt" convert_xml(xml_path, txt_path)

这段代码里保留了两个重要检查:一个是框宽高必须为正,另一个是中心点必须在[0,1]区间。YOLO训练时如果txt中出现负数坐标或宽高为0,并不会直接崩溃,但会在loss里产生NaN,或者在NMS阶段把框全部过滤掉,表现成训练三天mAP仍是0。参数说明:xml_path是待转换的VOC标注,txt_path是输出的YOLO标签;class_names的顺序必须与后续data.yaml完全一致,因为YOLO标签第一列的0/1就是索引位置。如果原始xml里类别大小写和roi、sdg不完全一致,脚本会在未知类别处打warn,你可以先统计warn数量再决定要不要补别名表。

注意这个脚本输出路径是os.path.splitext(xml_path)[0] + ".txt",恰好会覆盖原txt。如果你不想破坏原始数据,就改成输出到另一个目录。批量转换前建议先跑一个xml看看,再用diff对比原始txt和转换txt是否完全一致。如果差出几十个像素,就要查查xml里是否混入了旋转框或polygon标注。

3. 把数据集整理成YOLOv8训练任务:目录划分、data.yaml与训练参数实测

3.1 训练集/验证集划分:按同名前缀搬文件,不能只搬图片

YOLOv8训练时的标准目录要求是 images 和 labels 下各自有 train、val 子目录。很多新手把从压缩包解压出来的文件和标签平铺在一个文件夹里,也不划分验证集,直接用data.yaml指向整个目录。这样不是不能训,但验证集和训练集重叠,mAP会虚高。你测出来的“0.98 mAP”在真实场景里可能连0.6都到不了。这份数据集原始没有提供划分,需要自己分。

既然只有1245张,推荐按8:2划分,即996张训练、249张验证。划分时要把jpg、xml、txt三种文件一起搬。下面这个bash片段能防止标签错位:

mkdir -p datasets/pantograph/images/{train,val} mkdir -p datasets/pantograph/labels/{train,val} # 先用find生成图片列表,并按顺序打乱 find . -name "*.jpg" -print | sort > all_images.txt # 为了可复现,对列表做shuf但保留随机种子 shuf --random-source=<(yes 42) all_images.txt > shuffled_images.txt head -n 996 shuffled_images.txt > train_images.txt tail -n +997 shuffled_images.txt > val_images.txt while read -r img; do base="${img%.jpg}" mv "$img" datasets/pantograph/images/train/ mv "$base.xml" datasets/pantograph/labels/train/ mv "$base.txt" datasets/pantograph/labels/train/ done < train_images.txt while read -r img; do base="${img%.jpg}" mv "$img" datasets/pantograph/images/val/ mv "$base.xml" datasets/pantograph/labels/val/ mv "$base.txt" datasets/pantograph/labels/val/ done < val_images.txt

这段脚本的关键是base="${img%.jpg}",它去掉图片后缀,再补.xml和.txt。移动时如果mv报“No such file”,说明同名标签缺失,大概率是解压时文件名被系统截断或编码错乱。移动后最好跑一行diff <(ls labels/train | sed 's/\.xml$//') <(ls images/train | sed 's/\.jpg$//')检查两边列表是否一致。安全永远排在效率前面。

shuf --random-source=<(yes 42)是给随机源一个固定值,这样每次跑划分脚本能得到同样的划分。如果你想做多组对比实验,固定划分比每次随机划分更有可比性。参数说明:head -n 996取前996行作为训练,tail -n +997取剩余249行作为验证;42就是随机种子,可以改成任意整数。如果你的图片数量不是1245,改这两个数字即可。

3.2 写data.yaml:nc和names必须按顺序,别用默认coco

YOLOv8训练需要一份yaml描述数据信息。许多开源项目默认用coco128.yaml,里面是80个类别。直接把这份数据集的txt喂给coco128训练,第一列类别索引0会被译为“person”,1会被译为“bicycle”,训练和验证都会混乱。正确做法是在datasets/pantograph/下新建一个pantograph.yaml:

path: /absolute/path/to/datasets/pantograph train: images/train val: images/val nc: 2 names: 0: roi 1: sdg

path建议填绝对路径。YOLOv8用相对路径时以当前工作目录为基准,如果你从别的目录启动训练,可能出现Dataset not found。train和val是相对path的目录,不需要再加labels/,YOLOv8会自动在同级的labels子目录里找对应txt。names的索引顺序必须和转换脚本里的class_names = ["roi", "sdg"]、以及所有txt文件第一列的数字完全一致。如果txt里第一列是1但names[1]是roi,模型学到的就是错误的语义。我自己遇到过txt类别顺序和yaml不一致,训练loss正常收敛,但验证时roi被识别成sdg,原因就在这里。

这里有个常见误用:有些人为了提高mAP,把nc写成1,只取sdg类别。那需要把txt第一列全部改成0,不能只改yaml。不要通过改names数量去“屏蔽”某个类别,因为txt里索引1在训练时会被当作越界类别,轻则警告,重则训练中断。

3.3 启动YOLOv8训练:预训练权重、batch与imgsz怎么定

数据集只有1245张,相比大规模检测基准很小,直接用随机初始化从头训练很难收敛。常见做法是加载yolov8n.pt或yolov8s.pt预训练权重,它们是在ImageNet和COCO上预训练过的模型,迁移到这个任务能显著降低收敛epoch数。下面命令是实际验证过的:

yolo detect train \ data=datasets/pantograph/pantograph.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ lr0=0.01 \ device=0 \ project=run/pantograph \ name=exp_voc_yolo

参数说明:model=yolov8n.pt会从官方地址下载预训练权重,如果网络受限,可以提前把.pt文件放到当前目录再指定路径。epochs=100对这个小数据集足够,建议开启patience=10做early stop。imgsz=640是YOLOv8默认输入尺寸,对受电弓检测来说够用;如果你在训练前统计发现框里有大量小于20像素的小目标,可以改成imgsz=1280,但显存占用会变成近4倍,batch要相应降到8。batch=16在16GB显存下没问题;显存不足时优先降低batch,不要降低imgsz。lr0=0.01是YOLOv8给出的默认初始学习率,如果你换成AdamW优化器,建议降到0.001。

训练过程中要关注两个指标:一个是box_loss和cls_loss是否在下降,另一个是mAP@0.5是否在val上稳步上升。若cls_loss不降但box_loss降,大概率是类别语义问题,回第2.2节检查roi和sdg的框分布。若两个loss都在降但mAP不动,常见诱因是验证集和训练集有重叠,或者验证样本太少。1245张里的249张验证样本对置信度阈值波动很敏感,同一个epoch多次验证分数可能差两个点,所以不要中途挑“最高分”,要看最后10个epoch的平均表现。

4. 动手能跑的一步:训练前脚本化校验,防止标签错位和越界

4.1 归一化坐标校验:写python检查txt每个框是否合法

下载到的txt虽然声称是YOLO格式,但你不能假设每个文件都合法。之前有个项目,下载来的数据集里有3个txt的类别索引写了5,而数据只有2个类,训练时loss出现nan,排查了两天才发现是索引越界。所以训练前写一个通用校验器,把整个数据集扫一遍:

import glob for txt_path in glob.glob("datasets/pantograph/labels/**/*.txt", recursive=True): with open(txt_path) as f: lines = f.readlines() for i, line in enumerate(lines): parts = line.strip().split() if len(parts) != 5: print(f"[ERROR] {txt_path} 第{i+1}行字段数不是5") cls = int(parts[0]) if cls not in (0, 1): print(f"[ERROR] {txt_path} 第{i+1}行类别索引越界: {cls}") xc, yc, w, h = map(float, parts[1:]) if w <= 0 or h <= 0: print(f"[ERROR] {txt_path} 第{i+1}行宽高非法: {w:.3f} {h:.3f}") x1, y1 = xc - w / 2, yc - h / 2 x2, y2 = xc + w / 2, yc + h / 2 if x1 < 0 or y1 < 0 or x2 > 1 or y2 > 1: print(f"[WARN] {txt_path} 第{i+1}行框越界")

参数说明:glob.glob(..., recursive=True)递归扫所有子目录下的txt,line.strip().split()处理行尾空格。逻辑本身很简单,但能把三类常见问题一次性抓出来:字段数错误、类别索引越界、坐标越界。YOLO标签是归一化坐标,xmin/ymin允许极小负数比如-0.001,这是浮点误差;但如果小于-0.05或大于1.05,说明标注框偏移明显。遇到这种情况,最好从原始xml重新生成txt。

4.2 xml与txt一致性校验:防止改了VOC忘了同步YOLO

这个数据集同时给出xml和txt,好处是可以用xml当ground truth来反查txt。很多人只改xml不重新生成txt,训练用的还是旧txt。我写过一个对拍脚本,思路是把xml里每个box转成归一化坐标,再去txt里找相同类别的box,看中心点坐标偏差是否小于1个像素。由于浮点精度,偏差很小,但如果偏差超过5%,就要怀疑txt不是从这份xml生成的。

import glob, os import xml.etree.ElementTree as ET for xml_path in glob.glob("datasets/pantograph/labels/**/*.xml", recursive=True): txt_path = os.path.splitext(xml_path)[0] + ".txt" if not os.path.exists(txt_path): print(f"[ERROR] 缺少txt: {txt_path}") continue tree = ET.parse(xml_path) root = tree.getroot() size = root.find("size") width, height = int(size.find("width").text), int(size.find("height").text) xml_boxes = [] for obj in root.iter("object"): name = obj.find("name").text b = obj.find("bndbox") xml_boxes.append((name, (float(b.find("xmin").text) + float(b.find("xmax").text)) / 2 / width, (float(b.find("ymin").text) + float(b.find("ymax").text)) / 2 / height)) with open(txt_path) as f: lines = f.read().strip().splitlines() if len(lines) != len(xml_boxes): print(f"[ERROR] {xml_path} 框数量不一致 xml={len(xml_boxes)} txt={len(lines)}")

这段脚本不比对宽高,只比对中心点,因为宽高容易受坐标取整影响。参数说明:xml_boxes里存的是类别名和归一化中心点,如果txt行数和xml的object节点数一致,基本可以放心。对1245张图跑一遍,应该0 error。如果报“框数量不一致”,排查顺序是:先数xml里的object节点,再数txt行数;xml比txt多说明txt是旧版本,反过来说明txt被手工改过。

4.3 可视化抽检标注:随机抽取图片画框,人工核对roi和sdg

脚本校验解决的是“格式合不合法”的问题,解决不了“标没标对”的问题。比如roi框和sdg框标签反了,格式完全合法,但模型会学到错误语义。所以训练前要随机抽几十张图,把框画出来人工过一遍。下面提供一个基于OpenCV的快速脚本:

import cv2 import random import glob random.seed(7) img_paths = random.sample(glob.glob("datasets/pantograph/images/train/*.jpg"), 20) for img_path in img_paths: base = os.path.splitext(os.path.basename(img_path))[0] label_path = f"datasets/pantograph/labels/train/{base}.txt" img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path) as f: for line in f: cls, xc, yc, bw, bh = line.split() xc, yc, bw, bh = float(xc), float(yc), float(bw), float(bh) x1 = int((xc - bw / 2) * w) y1 = int((yc - bh / 2) * h) x2 = int((xc + bw / 2) * w) y2 = int((yc + bh / 2) * h) color = (0, 255, 0) if cls == "0" else (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) cv2.putText(img, "roi" if cls == "0" else "sdg", (x1, max(0, y1-5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 1) cv2.imwrite(f"check/{base}_draw.jpg", img)

保存到check目录后逐张翻看。重点看两点:roi框是否完整包住需要检测的受电弓主体;sdg框是否精确圈在滑板或弓头附近。如果发现100张里有3张以上错标,这份数据集就最好只当格式模板用,不要直接作为训练集。参数说明:random.seed(7)固定抽样种子,方便复现;20张是经验值,太多人工看不完,太少发现不了问题。这里直接用txt画框,因为训练时模型看到的就是txt,可视化要盯txt而不是xml。

5. 避坑:VOC/YOLO双格式数据集从解压到训练的6个常见问题

5.1 解压7z后文件名乱码导致图片与标签对不上

现象:解压后jpg正常,但xml和txt文件名出现“锟斤拷”或下划线丢失,Linux下ls看到一堆firc_shoudinggong_?833.xml。原因:部分老版本7z在Windows下默认使用系统本地编码,文件名跨系统传输时被错误编码。解决:不要依赖压缩包内文件名,解压后用find . -name "*.jpg"取jpg的base名,再重命名所有xml和txt与jpg同名。我一般会写一个python脚本:遍历jpg,对每个jpg用os.path.splitext得到base,同时查找同目录下可能的base + ".xml",如果没有,则扫描xml文件名里包含该base的候选,用shutil.move改名。这样不管文件名多乱都能找回来。

5.2 训练时报“Image size越界”或“标签读取为空”

现象:YOLOv8训练启动后几秒报错,提示某个txt文件不存在,或者loss全部是0。原因:txt图片同名的标签被放在了labels之外的目录,或者YOLOv8在data.yaml里填了train: /absolute/path/images/train之后,会去/absolute/path/labels/train找标签,如果你把标签后缀改错了,自然会找不到。解决:严格按第3.1节的目录结构作业,train只写到images/train,YOLOv8会自动替换images为labels。如果还报“label not found”,打开txt看看里面是否有内容,避免出现0行空文件。用find . -name "*.txt" -size 0查一下空标签,有就删除或重新转换。

5.3 每张图一个roi一个sdg:为什么训练后误检率偏高

现象:在验证集上mAP@0.5能到0.95,但部署到实际高铁场景视频里,同一位置同时输出一个roi框和一个sdg框。原因:roi和sdg存在包含关系,且数据集里两个类别的中心点几乎重合,模型学到的是“两个类别高度重叠地出现在同一位置”。原始说明里也特别声明数据只保证标注准确合理,不对训练精度作任何保证,所以遇到这类问题别急着怀疑标注,先分析框的关系。解决:判断自己的业务是否真的需要两个类。如果只需要受电弓位置,把roi类别去掉,只留sdg;如果需要区分roi和sdg,就要缩小roi的标注范围,让两个框不要重叠。常见做法是把txt里roi类的行都删除,重新生成data.yaml的names为["sdg"],同时把所有txt类别索引改成0。改完后重新跑一遍第4章校验,确保没有残留索引1。

5.4 数据增强开太猛导致受电弓被裁掉

现象:loss下降到50个epoch后再也不降,且验证集mAP波动很大。原因:1245张属于小数据,增强策略如果用了大尺度随机裁剪(scale=0.5)和随机旋转(degrees=90),受电弓本来就是细长结构,很多样本的roi或sdg框被裁掉一半,标签仍然保留,训练出来的模型总在半个框位置找目标。解决:把ultralytics配置的mosaic=0或mosaic=0.5,scale=0.2,degrees=10,损失函数用默认的CIoU即可。受电弓方向相对固定,不需要做180度旋转增强。换句话说,宁可少增强,也不要让标签语义失真。

5.5 用labelImg二次修改后txt没有自动更新

现象:用labelImg打开xml,改了几张图的框,保存后发现txt还是旧坐标,训练时模型行为没有变化。原因:labelImg默认保存的是VOC格式xml,虽然能读取YOLO txt,但保存时不一定会同时写txt。这是很多双格式数据集最容易踩的坑。解决:不要用labelImg直接改YOLO txt,而是改完xml后,跑一遍第2.3节的转换脚本重新生成txt。我现在的流程是:xml只作为原始标注,txt一律由转换脚本批量生成,不在labelImg里手动编辑txt。这样既能保证两种格式一致,又能在出错时快速定位。

5.6 混淆矩阵总和不为1?先看置信度阈值

现象:用yolo val跑完导出混淆矩阵,发现有些类别所有格加起来不等于该类的真实样本数。原因:类别有重叠框时,预测框和真实框匹配采用IoU阈值和score阈值,如果一个真实框能和两个预测框匹配,其中一个可能因低置信度被归为background。这不是数据集标错,而是评估时的NMS行为。解决:评估前先固定conf=0.25 iou=0.6,不要频繁改阈值。如果发现在低阈值下大量误检,那就是roi/sdg重叠问题,回5.3节处理。

6. 最后的小技巧:统计框尺寸分布来定imgsz和增强策略

受电弓检测里有个常被忽略的操作:训练前花五分钟统计所有标注框的宽高比和像素面积。它决定了你该用多大的imgsz、能不能开随机旋转增强。之前有个项目直接按默认imgsz=640训,结果受电弓在图中占的面积只有20×60像素,模型mAP一直在0.7附近卡住,把imgsz调到1280后直接提升到0.9。所以拿到这份数据集后,先跑一段简单的统计脚本:

import glob, os, cv2 import numpy as np wh_ratios = [] areas = [] for img_path in glob.glob("datasets/pantograph/images/train/*.jpg"): img = cv2.imread(img_path) h, w = img.shape[:2] label_path = img_path.replace("images", "labels").replace(".jpg", ".txt") if not os.path.exists(label_path): continue with open(label_path) as f: for line in f: cls, xc, yc, bw, bh = line.split() bw, bh = float(bw) * w, float(bh) * h areas.append(bw * bh) wh_ratios.append(bw / bh) wh_ratios = np.array(wh_ratios) areas = np.array(areas) print("box wh ratio: p50=%.2f p90=%.2f" % (np.percentile(wh_ratios, 50), np.percentile(wh_ratios, 90))) print("box area: p50=%.1f p90=%.1f" % (np.percentile(areas, 50), np.percentile(areas, 90)))

参数说明:wh_ratios是所有框的宽高比,p50=1.0说明一半框接近正方形,p90=2.5说明长宽比大的框不少。受电弓的sdg在图像里通常是横向的,宽高比在2~4之间更合理。如果统计下来p50面积小于32×32,就要在训练时考虑加大输入分辨率;如果宽高比极端,建议把degrees增强设为0或10,避免旋转把细长框转出语义。

有一次我发现roi和sdg两个类别的框宽高比差异很大,roi接近正方形,sdg接近5:1,按同样的增强参数训练时sdg的召回率总低于roi。后来我按类别分别统计,发现sdg在缩小版图像里只有12×40像素,于是把imgsz从640改成960并关闭了mosaic,召回率明显回升。从那以后,我每次拿到新数据集,都会强制走一遍“解压→重命名→坐标校验→可视化抽检→划分→尺寸统计”的流程,尤其是VOC+YOLO双格式资源,必须让xml和txt做一次对拍。这个习惯看起来简单,但省下的调参时间不止半天。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 12:17:37

软考云原生架构全景解析:从容器到微服务与论文写作指南

最近不少准备软考的朋友都在问同一个问题&#xff1a;系统架构设计师、软件设计师这些科目里&#xff0c;云原生架构到底要掌握到什么程度&#xff1f;问得多了我就发现&#xff0c;很多人其实是被一长串名词吓住的——容器、微服务、DevOps、Serverless、服务网格&#xff0c;…

作者头像 李华
网站建设 2026/9/28 12:17:26

lftp实战:断点续传与镜像同步,搞定服务器间文件迁移

做服务器间的文件传输&#xff0c;很多人第一反应就是用scp&#xff0c;或者干脆套用rsync。我见过不少同事把scp当成万能工具&#xff0c;传大文件传一半断线了就得从头再来&#xff0c;传海量小文件更是慢到让人怀疑硬盘是不是坏了。今天想认真聊聊lftp这个老牌工具——它看起…

作者头像 李华
网站建设 2026/9/28 12:12:18

BERT-BILSTM-CRF中文命名实体识别实战:原理、复现与调参指南

简介&#xff1a;基于BERT-BILSTM-CRF的中文命名实体识别完整项目&#xff0c;面向自然语言处理学习者、课程设计与期末大作业场景&#xff0c;提供了经过导师指导并获97分评价的高分实现。项目包含可直接运行的Python源码、项目使用说明、标注数据与预训练模型&#xff0c;下载…

作者头像 李华
网站建设 2026/9/28 12:11:43

200张图训练YOLOv8作物杂草检测:完整流程与避坑指南

简介&#xff1a;面向YOLO系列算法目标检测的开发者与研究人员&#xff0c;这份作物杂草数据集包含200张已标注图像&#xff0c;可直接用于训练、验证与测试&#xff0c;并附带data.yaml配置文件&#xff0c;适配YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10及YOLO11等主流版本。标…

作者头像 李华
网站建设 2026/9/28 12:10:40

高斯过程回归:小样本时间序列区间预测实战指南

做时间序列预测的人&#xff0c;迟早会遇到一个问题&#xff1a;光给一个预测值是不够的。你预测下个月销量是1000件&#xff0c;老板追问一句“误差多少”&#xff0c;你就得解释半天。更现实的情况是&#xff0c;供应链要备货、风控要设阈值、金融要算风险敞口&#xff0c;这…

作者头像 李华
网站建设 2026/9/28 12:10:09

高斯过程回归(GPR)实现时间序列区间预测的完整指南

1. 项目概述1.1 核心需求解析"基于高斯过程回归的时间序列区间预测"这个题目&#xff0c;第一眼看上去是个典型的学术型项目&#xff0c;但实际拆开来说&#xff0c;它解决的是一个很现实的问题——你手头有一堆按时间排列的数据&#xff0c;但你不仅想知道未来那个点…

作者头像 李华