
简介这份资源面向智慧交通与城市管理场景下的计算机视觉开发者提供城市道路打场晒粮行为的检测数据集可用于目标检测模型的训练与验证。数据集共1065张jpg图片每张均配有对应的Pascal VOC格式xml标注和YOLO格式txt标注标注类别为shailiang共1245个矩形框使用labelImg完成画框标注适合直接接入YOLO系列或VOC兼容框架进行实验。资源包为1个docx文件大小约2.32MB文档内整理并说明了数据集的结构、格式与标注信息便于快速了解数据组织方式。目前已有63人浏览学习可作为道路异常行为识别、智慧交通巡检等方向的数据补充帮助读者省去自行采集与标注的成本快速搭建训练流程并验证检测效果。1. 城市道路打场晒粮检测1065 张 VOCYOLO 双格式数据集能解决什么夏收和秋收那几周很多跑县道、乡道的司机都会遇到同一个场景柏油路被占了一半玉米或小麦铺成一条黄带边上摆着石块、木棍甚至钉板。对智慧交通里的路侧感知来说这不是普通的障碍物而是一类有季节规律、形态松散、边界模糊的侵占行为。用通用 COCO 预训练模型去测要么把晒粮堆当成路面纹理忽略掉要么把成片黄色误判成车辆或路障。这个数据集就是冲着这个细分场景来的1065 张 jpg 图片全部用 labelImg 画了矩形框同时给出 Pascal VOC 的 xml 和 YOLO 的 txt只有一个类别shailiang总框数 1245。它适合做路侧视频抽帧后的目标检测微调、做小样本类别的验证集也适合拿来做数据增强和标注格式转换的练手素材。下面按「拿到手怎么用 → 怎么训 → 坑在哪」的顺序拆开讲。2. 数据集结构与 VOC/YOLO 双格式的取舍2.1 1065 张图、1245 个框意味着什么先把数字摊开看。1065 张图对应 1065 个 xml 和 1065 个 txt说明每张图都有标注没有空图混在里面。1245 个框除以 1065 张图平均每张 1.17 个框说明绝大多数图片里只有一处晒粮区域少数图片有两处或以上。这个分布对训练有两个直接影响一是正样本密度低如果按常规 YOLO 的 anchor 匹配策略一张图里只有一个目标时正样本数量偏少容易欠拟合二是类别极度不平衡不存在因为只有一类但「背景 vs 前景」的区分会很敏感路面、阴影、黄色标线都可能被误检。我一般拿到这种单类别、低框密度的数据集会先做两件事统计框的宽高分布确认有没有极端长宽比再抽 30 张图肉眼过一遍看标注是否把晒粮边缘的散落颗粒也框进去了。这个数据集标注规则写的是「对类别进行画矩形框」没有更细的边界约定所以不同图片之间框的松紧程度可能有差异训练前统一看一眼能省掉后面调参的玄学时间。2.2 VOC 和 YOLO 到底该用哪套两套格式同时给不是让你都用而是让你按框架选。VOC 的 xml 是绝对坐标xmin/ymin/xmax/ymax适合 torchvision 的VOCDetection、MMDetection 的 VOC 后端或者你自己写解析脚本。YOLO 的 txt 是归一化的class cx cy w h直接喂给 Ultralytics 系列、YOLOv5/v8 的 dataloader。格式坐标类型典型框架注意点Pascal VOC xml绝对像素torchvision、MMDetection图片尺寸变化时要重新算YOLO txt归一化 0~1Ultralytics、YOLOv5/v8类别从 0 开始这里是 0类别名——只有shailiang映射为 0需要提醒的是项目正文里明确写了「不包含分割路径的 txt 文件」也就是说没有 train/val 划分清单。你得自己切分常见做法是按 8:1:1 或 7:2:1 随机分并且固定随机种子否则每次训练验证集都在变指标没法比。2.3 目录该怎么摆Ultralytics 对目录结构有约定最省事的摆法是这样dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml图片放images对应的 txt 放labels文件名保持一致只换扩展名。xml 可以单独放一个annotations目录留档训练时不用。下面这段脚本做三件事读所有 jpg、按比例切分、把文件复制到对应目录。import os import random import shutil random.seed(42) # 固定种子保证划分可复现 src_img raw/images src_lbl raw/labels dst dataset ratio (0.8, 0.1, 0.1) # train/val/test files [f for f in os.listdir(src_img) if f.endswith(.jpg)] random.shuffle(files) n len(files) n_train int(n * ratio[0]) n_val int(n * ratio[1]) splits { train: files[:n_train], val: files[n_train:n_train n_val], test: files[n_train n_val:] } for split, names in splits.items(): os.makedirs(f{dst}/images/{split}, exist_okTrue) os.makedirs(f{dst}/labels/{split}, exist_okTrue) for name in names: shutil.copy(os.path.join(src_img, name), f{dst}/images/{split}/{name}) txt name.replace(.jpg, .txt) shutil.copy(os.path.join(src_lbl, txt), f{dst}/labels/{split}/{txt}) print({k: len(v) for k, v in splits.items()})逻辑说明random.seed(42)是后悔药没有它你复现不了划分结果。ratio按 8:1:11065 张大约得到 852/106/107。复制而不是移动是为了保留原始文件后面做增强或重新划分不用重新解压。跑完打印三个数字确认加起来等于 1065少一张都说明有文件扩展名大小写不一致。2.4 data.yaml 怎么写path: ./dataset train: images/train val: images/val test: images/test nc: 1 names: 0: shailiangnc是类别数这里必须是 1。names的键从 0 开始和 txt 里的类别索引对应。如果写成1: shailiang训练时会出现索引越界或者全部预测成背景这是新手最常见的翻车点之一。3. 用 YOLO 跑通训练从环境到第一组指标3.1 环境与依赖Ultralytics 现在装起来很直接Python 3.8 以上都行。我一般用虚拟环境隔离避免和系统里的 torch 版本打架。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install ultralytics yolo checks # 确认 torch、cuda 是否可用yolo checks会打印环境摘要重点看 CUDA 那一行。如果显示 CPU训练会慢到让你怀疑人生1065 张图在 CPU 上跑 100 epoch 可能要几个小时。有显卡的话确认驱动和 torch 版本匹配这一步省不得。3.2 训练命令与参数yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/shailiang \ nameexp1参数逐个说modelyolov8n.pt用 nano 版预训练权重1065 张图的数据量不适合从零训微调收敛快。imgsz640是默认输入尺寸如果原图分辨率远大于 640晒粮区域又小可以提到 960 或 1280但显存占用会涨。batch16按显存调8G 显存跑 640 一般能到 16。lr00.01是初始学习率微调场景可以降到 0.001 更稳。patience20是早停20 轮验证指标不涨就停省时间。3.3 训练过程看什么训练日志里重点盯三个数box_loss、cls_loss、mAP50。单类别任务cls_loss会降得很快如果它一直不降八成是 data.yaml 的类别索引写错了。mAP50在前 10 轮通常涨得猛后面趋缓。如果mAP50卡在 0.3 以下不动先别急着调模型回去看标注框是不是把整条路都框进去了——框太大模型学到的就是「路面晒粮」。验证集指标出来后用yolo detect val单独跑一次加上save_jsonTrue可以把预测结果导出方便和 VOC 的 xml 做逐图对比。yolo detect val \ modelruns/shailiang/exp1/weights/best.pt \ datadataset/data.yaml \ splitval \ save_jsonTruesplitval指定验证集save_json导出的 json 里每张图有预测框和置信度可以写脚本算漏检和误检的具体分布。3.4 推理与可视化yolo detect predict \ modelruns/shailiang/exp1/weights/best.pt \ sourcedataset/images/test \ conf0.25 \ saveTrueconf0.25是置信度阈值晒粮这种边界模糊的目标阈值太高会漏检太低会误检。我一般先在验证集上画一条 conf-recall 曲线找召回率开始明显下降的拐点再定阈值。结果图默认存到runs/detect/predict抽几张和原图并排看重点看阴影、黄色标线、路面修补这些干扰项有没有被误框。4. 避坑与排查标注、格式、训练里最容易翻车的几处4.1 现象训练报「Label class x exceeds nc」原因txt 里的类别索引大于等于nc。这个数据集只有一类txt 里应该是 0如果出现 1 或更大说明标注时类别名映射错了或者混入了别的数据集的标注。解决写个脚本扫一遍所有 txt 的第一列找出最大值。import os bad [] for f in os.listdir(dataset/labels/train): with open(fdataset/labels/train/{f}) as fp: for line in fp: cls int(line.split()[0]) if cls 1: bad.append((f, cls)) print(bad[:20], len(bad))把bad里的文件挑出来用 labelImg 重新确认类别或者直接改 txt 第一列为 0。4.2 现象mAP 一直很低预测框全是大框原因标注时把整片路面或整张图框进去了模型学到的是背景而非目标。这个数据集标注规则只写了「画矩形框」没有约束框的紧致度不同人标出来的松紧可能差很多。解决统计框面积占整图面积的比例超过 0.8 的挑出来人工复核。import os from PIL import Image for f in os.listdir(dataset/labels/train): img Image.open(fdataset/images/train/{f.replace(.txt, .jpg)}) w, h img.size with open(fdataset/labels/train/{f}) as fp: for line in fp: _, _, _, bw, bh map(float, line.split()) if bw * bh 0.8: print(f, bw * bh)比例过大的框要么重标要么在训练时过滤掉。4.3 现象验证集指标波动大每次跑都不一样原因没有固定随机种子或者 train/val 划分每次重新生成。Ultralytics 默认会做随机增强验证集本身不变的话指标不该大幅波动。解决划分脚本里固定random.seed训练命令里加deterministicTrue并且把划分好的目录固定下来不要每次训练前重新切。4.4 现象推理时把黄色标线、路面阴影误检成晒粮原因单类别数据集里负样本没有晒粮的路面没有被显式标注模型没见过足够的「类似但不该检」的样本。解决从原图里挑一批没有晒粮的路面图作为背景图加入训练集txt 留空。Ultralytics 支持空标签文件这些图会贡献负样本损失。一般加 10%~20% 的背景图误检会明显下降。4.5 现象xml 和 txt 对不上同一张图框位置不一致原因两套格式是分别生成的转换过程中可能因为图片尺寸读取错误或坐标取整方式不同产生偏移。解决写个校验脚本随机抽 50 张把 xml 的绝对坐标转成归一化和 txt 逐框比对差值超过 0.01 的记下来。import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path): tree ET.parse(xml_path) root tree.getroot() w, h Image.open(img_path).size boxes [] for obj in root.findall(object): b obj.find(bndbox) xmin float(b.find(xmin).text) ymin float(b.find(ymin).text) xmax float(b.find(xmax).text) ymax float(b.find(ymax).text) cx (xmin xmax) / 2 / w cy (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h boxes.append((cx, cy, bw, bh)) return boxes比对结果不一致的以 xml 为准重新生成 txt因为 xml 是 labelImg 直接产出的txt 是转换来的前者更可信。5. 进阶把 1065 张图用出 3000 张的效果数据量不大单类别想提升泛化增强策略比换模型更划算。Ultralytics 内置的增强参数里对这个场景最有用的是这几个hsv_h、hsv_s、hsv_v控制色调、饱和度、亮度扰动晒粮的颜色在不同光照下差异大适当调高饱和度扰动有帮助mosaic做四图拼接能增加小目标和多目标场景flipud和fliplr做上下、左右翻转路侧视角一般左右翻转安全上下翻转要谨慎因为天空和路面的位置关系被破坏了。我一般会跑两组对比一组默认增强一组把hsv_s0.7、mosaic1.0、fliplr0.5其他不变看验证集 mAP 差多少。如果提升不明显说明数据本身的多样性已经够或者标注噪声盖过了增强收益。另一个技巧是用训练好的模型去跑未标注的路侧视频抽帧把高置信度的预测框导出来人工修正后加入训练集。这是半自动标注的路子1065 张起步迭代两三轮能到两三千张的有效样本。导出预测框可以用save_txtTrue格式和 YOLO 标注一致直接改改就能用。yolo detect predict \ modelruns/shailiang/exp1/weights/best.pt \ sourceunlabeled_frames \ conf0.5 \ save_txtTrue \ save_confTrueconf0.5比推理时高是为了只保留比较确定的框减少人工修正量。save_confTrue会在 txt 每行末尾多一个置信度方便按分数排序优先看低分的那些。最后说个验证习惯每次改完数据或增强参数我都会固定跑一次yolo detect val把mAP50、mAP50-95、每类 precision/recall 记在一个表格里和上一版对比。没有这个对照调参就是凭感觉。从那以后我每次动数据集之前都强制走一遍划分校验和格式比对宁可多花十分钟也不想训到一半发现标签是错的。希望帮到你。本文还有配套的精品资源点击获取