
简介俯拍视角下的道路车辆与行人目标检测数据集面向算法工程师与计算机视觉学习者适用于智能交通和辅助驾驶项目可直接用于主流YOLO系列网络训练。数据集包含超过三千张图片及对应标签划分为训练集与验证集提供类别文件整体采用YOLO标注格式并已进行旋转、缩放、裁剪等数据增强处理可增强模型鲁棒性。类别共有十个覆盖汽车、摩托车、行人、卡车等常见城市交通目标可用于交通监控与辅助驾驶研究。压缩包内共两千个文件其中一千九百九十九个为文本标签文件另有一个辅助脚本整体大小四百六十三点一一兆字节。已有超过一千六百人学习对需要高质量标注数据的开发者来说可有效节省采集与标注时间也可直接作为算法验证模板与项目素材帮助快速完成目标检测任务。1. 俯拍道路目标检测数据集为什么 3000 张图比三万张平视图更考验模型无人机巡检、高架路口、智慧园区安防这些场景里摄像头视野是俯拍的车辆是一个个倾斜的小矩形行人往往只有十几个像素道路标线比车身更容易被模型记住。3000 张俯拍道路图带车辆和行人标签真正的价值不是“又多了一份数据集”而是把目标检测在小目标、密集、遮挡条件下的极限摆到桌面上。平视场景里跑得飞快的 YOLO换到俯拍图往往 mAP 掉十几个点差距不在数量在视角与尺度。这篇文章按“数据 → 训练 → 评估 → 清洗”的顺序把这套数据落地成可复现流程适合交通感知工程师和用 YOLOv8 训练自己数据集的算法同学。2. 数据集结构与标注格式从目录布局看清一张俯拍图被标注成了什么拿到目标检测数据集第一个动作不是看图片而是摸清目录结构和标签口径。俯拍道路数据最常见的组织方式是图片与标签文件同名同层级分布训练、验证、测试三个子集分开。标签格式决定了后续接训练脚本时要不要写转换器也决定了类别顺序会不会在某个环节悄悄错位。2.1 俯拍道路数据集的目录与命名约定标准布局通常是这样data/ ├── images/ │ ├── train/ # 约 2100 张 │ ├── val/ # 600 张 │ └── test/ # 400 张 └── labels/ ├── train/ ├── val/ └── test/图片img_0042.jpg对应的标签就是同目录级别下的img_0042.txt。这种一一对应的命名约束是所有后续流程的基石如果原始数据集给你的是 JSON 或 XML第一步先转成同名文件再谈训练。俯拍道路场景里同一条路段往往有大量连续帧划分 train/val/test 时不能随机洗牌否则同一地点的图片会同时出现在训练集和验证集评估指标虚高。按拍摄批次或路段 ID 划分也就是让同一个场景只出现在一个子集里是这类数据集首先要遵守的纪律。有一个前提必须确认3000 张图片里是不是存在“连拍重复”。俯拍无人机录像抽帧出来的数据相邻帧车辆位置只差几个像素如果直接全量进训练模型会把背景纹理当特征。检查方法很简单对图片算感知哈希把相似度超过 0.95 的帧做去重或分到同一个批次。2.2 标签格式怎么选VOC xml、YOLO txt 还是 COCO json常见的目标检测标注格式有三种俯拍道路数据集里概率最高的是前两种。格式坐标口径适合链路常见坑Pascal VOC xml绝对像素 xmin/ymin/xmax/ymax老训练库、mmdet 系列解析慢需自己改造读入YOLO txt归一化 cx/cy/w/hYOLOv5/v8、SAHI类别 id 漂移、宽高为 0COCO json绝对像素 x/y/w/hDetectron2、mmdet大 json 文件难增量修改容易漏类别如果这份数据同时带了 xml 和 txt优先以 txt 为主做训练同时保留 xml 作为可读源。拿 YOLOv8 训练的话标签文件每一行就是class_id cx cy w h四个坐标值全部除以图片宽高是 0 到 1 之间的小数。俯拍图里一辆车的框可能只有 0.05 宽写错成像素值会导致 loss 直接发散。2.3 读懂一条车辆标注边界框坐标的两种口径以一张 3840×2160 的俯拍路口图为例VOC 里一条车辆标注长这样annotation foldertrain/folder filenameimg_0042.jpg/filename size width3840/width height2160/height depth3/depth /size object namecar/name difficult0/difficult bndbox xmin1204/xmin ymin860/ymin xmax1390/xmax ymax968/ymax /bndbox /object /annotation对应到 YOLO txt同样是这个框0 0.3378 0.4231 0.0484 0.0500先从 xml 读出目标框坐标然后按公式换算中心点cx(xminxmax)/2/wcy(yminymax)/2/hw(xmax-xmin)/wh(ymax-ymin)/h。这里最容易错的是把中心点当成了角点坐标或者忘了归一化直接写像素这两种错误在俯拍小目标上表现得尤其隐蔽因为数值很小loss 未必爆炸但精度会非常差。遇到像这类垂直视角的采集一个框里出现半截车身的概率很大。建议核对标签里有没有大量与图像边缘相交的框如果标注时没有把边缘截断的部分标进去训练时模型会学到“车身不完整也可以算正样本”的错误规律。2.4 用脚本统计标签分布与小目标占比拿到标签后先跑一轮统计比直接训练重要得多。以下脚本扫描 YOLO 格式标签输出每类目标数量、小目标占比并检查类别 id 是否越界from pathlib import Path import random label_dirs [Path(data/labels/train)] class_names [car, person] stats {c: {count: 0, small: 0} for c in class_names} image_width 3840 # 改成实际图的宽 for d in label_dirs: for txt in sorted(d.glob(*.txt)): for line in txt.read_text().strip().splitlines(): parts line.split() if len(parts) ! 5: print(异常行:, txt, line) continue cid int(parts[0]) if cid len(class_names): print(类别 id 越界:, txt, cid) continue w_norm float(parts[3]) area w_norm * image_width stats[class_names[cid]][count] 1 if area 48: stats[class_names[cid]][small] 1 for c in class_names: s stats[c] ratio s[small] / max(s[count], 1) print(f{c}: 总数 {s[count]}, 小目标占比 {ratio:.2%})这段脚本用 width 判断的是归一化宽度小于 48 像素的目标也就是 MS COCO 定义里 small object 的横向尺寸口径阈值可以根据俯拍高度调整到 32 或 64。如果小目标占比超过一半直接喂给默认的模型配置几乎必然在 mAP-small 上惨败后续训练、切片推理都要按这个统计结果做决策。同时输出异常行也保护了后面 YOLO 训练脚本不会因为一个脏标签中途崩掉。这个统计结果会成为第 4 章切片方案的输入参数。3. 用 YOLOv8 在俯拍道路数据集上跑通训练从数据划分到第一个 mAPYOLO 目标检测流程走到自定义数据这一步卡住人的地方往往不是模型结构而是数据文件的对齐。YOLOv8 训练自己的数据集本质上只做三件事把图片和标签放到对应目录写一个 dataset.yaml 描述类别然后跑训练命令。每一步都有容易踩空的地方下面拆开说。3.1 先按路段划分数据别用随机洗牌俯拍道路数据里同一路段的光照、地面纹理、车道线高度相似。如果随机划分验证集里可能藏着与训练集几乎相同的背景mAP 虚高到 0.8部署到新路段直接掉到 0.3。按采集批次或路段前缀划分是最稳妥的方案假设文件名里有路段标识可以这样切python - PY from pathlib import Path import random imgs sorted(Path(data/images).glob(*_*.jpg)) site_groups {} for p in imgs: site p.name.split(_)[0] site_groups.setdefault(site, []).append(p) sites sorted(site_groups) random.Random(42).shuffle(sites) # 假设有 20 个路段按 15:3:2 切分 train_sites set(sites[:15]) val_sites set(sites[15:18]) test_sites set(sites[18:]) for site in train_sites: for p in site_groups[site]: p.rename(Path(data/images/train) / p.name) PY这段脚本的关键在设计逻辑里以路段为最小单位洗牌而不是以图片为最小单位。代码里的站点拆分方式要根据文件名规则调整但原则不变——验证集和测试集必须包含训练集没见过的路段才能测出模型在真实场景里的泛化能力。俯拍数据里时间因素也很重要白天和夜晚尽量同时出现在三个子集里避免模型没见过夜间灯光下的车辆轮廓。3.2 写 dataset.yaml 时的类别顺序陷阱YOLOv8 训练自己的数据集离不开一个 yaml 配置文件。下面的写法兼容官方训练流程path: /path/to/data # 数据根目录的绝对路径 train: images/train # 相对 path val: images/val test: images/test nc: 2 names: 0: car 1: person训练时报错说 “found 2 classes with same name” 或者 mAP 一直为 0十有八九是这里类别顺序和标签 txt 里的 class_id 对不上。标签里1代表行人yaml 里却写成了0: person模型训练出来会把行人当车。如果数据集自带 class_list 说明文件以它为唯一事实来源如果没有按第 2 章的统计脚本输出 order 列表作为 names 顺序。宁可在 yaml 里多写注释也不要凭文件名猜顺序。还有一种情况是 names 数量比标签里实际类别多导致某些类别完全没有正样本训练日志会看到某一类 AP 为 0。检查方法是在训练前跑一条验证命令看类别 id 是否在合法范围内。3.3 训练命令与必调参数数据就绪后跑训练的命令如下yolo detect train \ datadataset.yaml \ modelyolov8s.pt \ imgsz960 \ batch16 \ epochs100 \ optimizerAdamW \ cos_lrTrue \ patience15 \ projectruns/detect \ namebirdview_960先说 imgsz俯拍图如果原始是 3840 宽直接缩到 640 会让车辆框变得只有 8×8 像素特征提取器根本分不清车和人。建议先尝试 960显存不够再降 800而不是一上来就 640。batch 按显存调单卡 24G 用 16 就差不多多卡可以翻倍。epochs 配 patience15 做早停俯拍数据集 3000 张的情况下通常第 60 到 80 轮就收敛了没必要硬跑满。optimizer 很多人默认用 SGD但俯拍小目标场景 AdamW 收敛更稳特别是标签里少量脏样本存在时AdamW 对梯度噪声的容忍度更高。cos_lrTrue 会让学习率按余弦曲线衰减减少后期在小目标框上反复震荡。几个关键参数的作用和适用场景汇总如下参数推荐值说明imgsz960 或 800比原始分辨率小 3 到 4 倍即可过小会丢小目标batch1624G 单卡显存不足时优先降 imgsz其次降 batchepochs100 patience15小数据集早停收益大没必要追求固定轮数optimizerAdamW对噪声标签和有遮挡的小目标更友好lr00.001AdamWSGD 场景用 0.01混用会震荡warmup_epochs3前几轮先稳定梯度适合新数据集冷启动命令跑完后看runs/detect/birdview_960/下的results.csv和weights/best.pt。这里说的几个参数不是定死的如果你的图本身只有 1080p那 imgsz800 就够了960 反而浪费显存。训练结束后先别急着测 test 集先跑一轮yolo detect val看验证集 mAP-50 是否明显高于 0.5如果 mAP 很低回到第 2 章检查小目标占比和脏标签模型结构的问题排在数据问题之后。4. 俯拍小目标检测的两个狠招切片推理与针对性数据增强模型在验证集上 mAP 到 0.6 不算完俯拍道路上真正让人头疼的是小目标漏检。车辆只有二三十像素时直接推理很容易漏此时常规增强手段帮不上忙切片推理才是立竿见影的方案。这一章讲怎么判断要不要切片以及切片参数怎么给。4.1 先看评估指标再决定要不要切图mAP-small 和 mAP-50 的差别训练结束后跑一次带详细指标的验证yolo detect val \ modelruns/detect/birdview_960/weights/best.pt \ datadataset.yaml \ imgsz960输出里除了 mAP50 和 mAP50-95还有按目标面积分组的指标small、medium、large。COCO 口径下小于 32×32 像素的框算 small对俯拍道路图来说这几乎就是最常见的车辆尺寸。如果 mAP50 有 0.7但 mAP50 small 只有 0.3说明模型在大目标上工作正常、小目标上漏检严重切片推理立刻安排。如果 small 和 medium 差距不大那问题出在类别不平衡或标签噪声切片解决不了先回第 2 章做数据清洗。有一个习惯值得保留把每次评估的 small/medium 指标和 imgsz、增强参数一起记录。红外小目标检测里讨论的那些面积阈值和评价参数在可见光俯拍道路上同样适用唯一区别是阈值要按你的图片宽度等比放大。4.2 SAHI 式切片把一张大图切成 640 子图再拼回框SAHI 是切片推理的常用开源方案做法是把大图切成若干个重叠子图分别推理后再把重叠区域的框用 NMS 合并避免同一个目标被重复计数。安装 sahi 后用训练好的模型做切片预测from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathruns/detect/birdview_960/weights/best.pt, confidence_threshold0.25, image_size960, devicecuda:0, ) result get_sliced_prediction( image_pathdata/images/test/site03_018.jpg, detection_modeldetection_model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2, ) result.export_visuals(export_dirruns/sliced_vis/)模型推理时会把每个 640×640 子图缩放到模型输入尺寸小目标在子图里被放大了好几倍原本只有 20 像素的车轿在子图里变成 60 像素以上特征提取自然更准确。切片尺寸和重叠比例的设置逻辑如下参数建议值效果与注意点slice_width/height640 或 512子图越大切块越少、速度越快但如果目标太小还是要小切片overlap_width_ratio0.20.4目标恰好被切片边界切断时需要重叠来兜底overlap_height_ratio与宽度一致非方形输入可分开设置俯拍一般对称即可confidence_threshold0.250.3切片推理因为目标更清晰阈值可以比整图推理略高切片推理最大的注意点是速度一张 4K 图切成 48 个子图推理耗时可能比整图贵 10 倍。如果项目只有离线分析需求代价可接受如果要做实时视频流就得换思路比如只在检测到小目标候选区切片或者用滑窗加缩放采样。另外切片推理结束后拼接回原图时会遇到 NMS 合并阈值sahi 内部已处理不需要额外写。4.3 YOLOv8 的数据增强参数怎么调得不把行人切碎默认的 mosaic 增强会把四张图拼成一张对于平视大目标非常有效但俯拍小目标场景里mosaic 缩放后行人和车辆会被压缩到只有几个像素反而成了噪声。这里建议保留但“降量”在训练命令里加上augment: true hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 30.0 translate: 0.1 scale: 0.5 fliplr: 0.5 flipud: 0.5 mosaic: 0.5 mixup: 0.1degrees30 是俯拍场景下比较关键的参数因为车辆朝向在画面里是任意角度的默认 0 度旋转会限制模型对旋转车辆的适应能力俯拍下左右翻转和上下翻转同样安全但平视数据里 flipud 不该开。mosaic 和 mixup 调低到 0.5 和 0.1 左右小目标就不会被拼图操作稀释成噪声。scale 保持 0.5 而不是默认的更大值避免把小目标缩得完全不可见。如果数据集本身已经很大每张图都做这么多变换会拖慢训练速度可以用cacheTrue把图片缓存进内存加速读取。增强策略没有绝对答案判断标准是验证集 mAP 变化趋势稳定、训练 Loss 和验证 Loss 同降不背离。一旦发现训练 Loss 持续下降而验证 Loss 开始回升先把 mosaic 关掉再试。4.4 错误的做法把 imgsz 直接拉到 1920有人觉得小目标检测差最简单的办法就是把推理分辨率调大从 960 一路涨到 1920。这样做训练显存暴涨而收益递减很快——小目标确实变清晰了但模型在小图训练时见过的尺度分布和 1920 输入不一致推理时反而产生大量误检。常见可用方案是保持训练 960推理时做一个二阶段策略整图粗检对高密度区域裁块细检或者把第 2.1 节里的路段去重做得更狠集中批次去补齐低置信度的困难样本。如果你的数据里目标框本身是任意朝向的窄长条水平框会把大量背景也框进去此时可以考虑 mmrotate 这类旋转框检测方案把 DOTA 风格的 OBB 标注转成旋转框格式再训练。5. 训练后别急着部署用可视化校验把脏标签和漏检一起挑出来模型训练结束后最常见的心态是直接看 test 集 mAP 数字。俯拍道路场景里mAP 高不等于能上线因为 3000 张图片里只要存在个别标签错位或漏标评估结果就会被污染。收货前至少做一遍可视化校验把预测框和真实标签叠在同一张图上人工扫一遍胜过任何曲线分析。5.1 用 YOLOv8 自带的预测可视化快速建立第一印象把验证集图片跑一遍预测保存输出yolo detect predict \ modelruns/detect/birdview_960/weights/best.pt \ sourcedata/images/val \ imgsz960 \ conf0.25 \ saveTrue \ projectruns/val_vis跑完打开runs/val_vis里的图片重点看两类现象一是同一辆车上有两个重叠框说明 NMS 阈值需要调低二是行人被反复漏检说明增强或切片参数不合适回第 4 章调整。预测可视化需要和标签叠加对比可以在代码里读取 YOLO txt 并画矩形也可以用 LabelImg 打开原图加载标签做法哪个顺手用哪个。5.2 低置信度样本里藏着真问题把置信度阈值从 0.25 降到 0.1重新预测专门保存置信度在 0.1 到 0.25 之间的预测框。这些“犹豫框”往往是标签漂移、遮挡严重、目标极小的三类样本。如果这批低置信度框里有大量真实车辆被标成 person问题不在模型而在标签如果一半以上都落在非机动车道上的人身上模型可能把路面纹理或阴影学成了特征。这类样本直接补进数据集比反复调参更有效。5.3 用硬负样本回填数据集继续下一轮迭代人工看过几百张可视化结果之后把最常被漏检的场景截图回填到训练集中建议按“候选池”方式管理先攒 200 到 500 张困难样本重新训练一轮对比 mAP-small 的变化。硬负样本不只是“错图”还包括大量正确的空背景图模型需要学会在无人无车的路面上输出零检测。俯拍道路的背景变化很大阴影、匝道护栏、路面积水反光都可能被误检成汽车空背景图能有效压低误检率。把这一步并入迭代流程切一批新路段图做一轮可视化审查补一批候选框再训一轮直到 mAP-small 的变化不再明显为止。验证集评估时保持同一批图片不变这样前后指标才可比。本文还有配套的精品资源点击获取