☰
无人机视角车辆检测数据集:YOLO格式训练全指南
2026/10/20 2:54:48 网站建设 项目流程

做目标检测的人应该都有过类似的体验:跑通官方示例容易,真正想训练自己的场景数据时,第一个拦路虎往往是“没有合适的数据集”。尤其是无人机视角下的车辆检测,很多朋友习惯直接拿地面相机的公开车辆数据集来训练,结果一到航拍画面上,漏检、误检、置信度飘忽不定,问题层出不穷。这期整理的就是专门针对无人机拍摄场景的车辆检测数据集,采用YOLO标注格式,图片和标签文件都处理得规规矩矩,拿到手就能直接开练。我会把这份数据集的细节、使用方式以及训练中容易踩的坑一并讲清楚,希望能帮正在做智慧交通、安防巡检、车辆统计这类项目的朋友省下整理数据的时间。

1. 为什么无人机视角的车辆检测数据集这么难找

很多初学者会问:车辆检测的数据集不是很多吗?怎么还要专门整理无人机视角的?这里面的差别非常大。地面视角的车辆检测数据,车辆在画面里往往占据几十甚至上百像素,轮廓清晰,能看到车头、车尾、车门这些“侧面特征”;而无人机拍摄的画面是从上往下看的俯视图,车辆在画面里就是一堆“车顶”,目标小、密度高、互相遮挡也很常见。如果直接把地面数据训练的模型搬到航拍图上,模型学到的是侧面视觉线索,遇到俯视场景自然就不认识了。

1.1 一张航拍图和一张地面照片的差别到底在哪

先说尺度。以常见的1080p航拍画面为例,一辆普通轿车在画面里通常只有40到80像素的宽度,有些偏远区域的车甚至只有20个像素左右。地面数据里常见的车辆目标动辄200像素以上,这两种尺度下模型提取的特征完全不同。小目标在卷积神经网络的高层特征图中会被压缩到几乎没有信息,这也是很多地面模型在航拍图上表现差的核心原因之一。

再看观察角度。地面拍摄时,车身的侧面、轮胎、车窗反射这些特征是判据;无人机俯拍时,看到的主要是车顶轮廓、天窗、车顶颜色和周围阴影。数据分布差异这么大,模型没有见过这样的特征组合,强行迁移结果自然不理想。

还有一个经常被忽视的因素:光照和阴影。无人机一般在白天作业,阳光直射下车辆会形成明显的投影,阴影和车身边界混在一起,非常干扰检测。地面数据集里阴影问题相对轻,因为拍摄角度让阴影大多落在车体侧后方,不会把车的轮廓吞掉。俯拍时阴影可能把相邻车辆连成一片,这对标注和检测都是额外的挑战。

1.2 航拍数据的标注难点与数据集价值

无人机画面里车辆又小又多,标注一枚框往往需要把图片放大好几倍才能看清楚边界。原始画幅里有上百辆车的情况下,标注员得一个个放大、确认、拉框,工作量比地面数据大得多。这也是市面上免费航拍数据集稀少的主要原因——不是没人拍,而是没人愿意花时间精标。

这期分享的数据集就是在这个背景下整理的,目标是做一个“拿到就能用”的基础版本。它适合三类人:一是想验证自己在航拍场景下算法效果的研究者,二是做交通流量统计、停车场监测等项目的开发者,三是还在学习目标检测流程、想找一份真实场景数据练手的新手。用这份数据先把整体流程跑通,再根据自己业务补场景数据,会比自己从零采集、标注高效得多。

2. 数据集全景与YOLO标注格式解析

这份数据集我事先整理成了标准的目标检测工程结构,图片集和标签集分开存放,同时附上了一份配置文件。先别急着打开训练脚本,花几分钟把数据集的“长相”看清楚,会帮你省下后面很多排查时间。

2.1 数据集里有什么:规模、场景与类别分布

整个数据集包含约3200张无人机拍摄的图片,覆盖城市道路、高速互通、十字路口、园区停车场、乡村公路等常见场景。图片以1920×1080分辨率为主,少部分来自4K航拍设备,尺寸不统一,这一点和实际使用情况很吻合。标注框累计约18000个,共4个类别:car、truck、bus、van。

需要提醒一下,这4个类别的样本数量并不均匀,car占了绝大多数,truck和bus相对少一些。这种不均衡在真实采集数据里非常普遍,后面我会单独讲怎么处理。压缩包里包含三个部分:images存放图片、labels存放同名的txt标注文件、data.yaml是描述数据集信息的配置文件。

如果你拿到手的是某个平台上的分享压缩包,解压后建议先不要直接开训,按下面几步做一次体检。数据集的完整性决定了训练的成败,这一步是最值得花时间的。

2.2 YOLO标签文件到底怎么读

YOLO格式的标注文件是纯文本,每张图片对应一个同名txt文件,文件里每一行代表一个目标物体。标准格式是:类别编号、归一化后的中心点x、中心点y、归一化后的宽度w、归一化后的高度h。

举个例子,假设类别定义是0为car、1为truck、2为bus、3为van,那么某张图里有四辆车,它的label文件内容可能是这样的:

0 0.532345 0.671023 0.043210 0.051232 0 0.123456 0.456789 0.033890 0.042154 1 0.803412 0.392001 0.071234 0.062178 3 0.615123 0.223411 0.028345 0.036201

第一行的含义是:类别为car,目标中心点在图片横向53.23%、纵向67.10%的位置,宽度约占图片4.32%,高度约占5.12%。所有坐标都缩放到0到1之间,这样做的好处是和图片分辨率无关,1920×1080和3840×2160可以混在一起训练,模型不需要关心输入尺寸。但代价是精度依赖浮点数,一旦标注工具导出时没有归一化,坐标直接写成了像素值,训练就会出大问题,这一点在后面的踩坑部分细说。

2.3 拿到数据集后的第一件事:完整性体检

不要因为数据集是别人整理好的就跳过检查。实际操作中我最常遇到的情况是:图片后缀大小写不一致导致标签匹配不上,或者某些txt是空文件、里面什么目标都没有,或者类别编号超出了配置文件里的类别总数。这些隐藏问题不会让训练直接报错,而是会不动声色地拖低精度,排查起来最费时间。

我通常用下面这个Python脚本快速体检,标准库就能完成,不需要额外装依赖:

import os from collections import Counter img_dir = "images" label_dir = "labels" img_exts = {".jpg", ".jpeg", ".png", ".bmp"} imgs = set() for f in os.listdir(img_dir): ext = os.path.splitext(f)[1].lower() if ext in img_exts: imgs.add(os.path.splitext(f)[0]) label_exts = {".txt"} labels = set() for f in os.listdir(label_dir): ext = os.path.splitext(f)[1].lower() if ext in label_exts: labels.add(os.path.splitext(f)[0]) print("无标签的图片:", len(imgs - labels)) print("无图片的标签:", len(labels - imgs)) all_classes = Counter() bad_lines = [] for f in labels: path = os.path.join(label_dir, f + ".txt") with open(path, encoding="utf-8") as fp: for line in fp: parts = line.strip().split() if len(parts) != 5: bad_lines.append((f, "字段数不为5")) continue cid = float(parts[0]) if cid != int(cid) or int(cid) < 0 or int(cid) > 3: bad_lines.append((f, "类别编号异常")) continue coords = list(map(float, parts[1:])) if max(coords) > 1.0001 or min(coords) < -0.0001: bad_lines.append((f, "坐标越界")) continue all_classes[int(cid)] += 1 print("标签行总数:", sum(all_classes.values())) print("类别分布:", dict(sorted(all_classes.items()))) print("异常行数:", len(bad_lines))

跑一遍下来,图片和标签数量是否对得上、类别分布是否合理、有没有坐标越界,基本就一目了然了。我见过不少人跳过这一步直接开训,后面损失震荡怎么调都调不好,最后发现是标签文件里混进了几千个像素坐标的脏数据。这种问题越早发现越好。

3. 从下载到训练:把数据集喂给YOLO的完整流程

确认数据集没有明显问题之后,接下来就是把它组织成目标检测框架能直接读取的工程结构。不同框架对目录结构的要求大同小异,只要抓住核心规则,一通百通。

3.1 目录结构与data.yaml配置

YOLO系训练框架通常要求图片和标签分开存放,并且训练集、验证集都要有对应的图片目录和标签目录。推荐的结构是这样的:

dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml

images/train里放训练图片,labels/train里放对应对应的txt标注文件,文件名必须完全一致,包括后缀名的大小写。val目录同理。data.yaml放在dataset根目录下,内容很固定:

train: ./images/train val: ./images/val nc: 4 names: ['car', 'truck', 'bus', 'van']

路径我用的是相对路径,这样整个dataset文件夹挪到哪里都能用。如果你用的是线上训练环境或者路径容易变,也可以改成绝对路径。nc是类别数量,names是类别名字列表,顺序必须和标注文件里的数字编号一一对应,这一点一旦错位,模型训练出来就是“张冠李戴”,检测结果全部错乱。

3.2 训练集和验证集怎么划分才合理

很多朋友拿到数据后直接按比例随机打乱划分,比如8:2切分。对普通图片数据集这么做没问题,但对无人机航拍数据,这个做法有一个容易被忽略的隐患:无人机拍摄的连续帧之间高度相似。同一个架次绕着一个路口飞一圈,可能拍下几百张图,随机划分后,某条路的画面会同时出现在训练集和验证集里,模型等于提前“看过”验证题的答案,指标自然好看,但一换到新场景就露馅。

我建议按采集场景来划分,而不是按文件随机切。比如压缩包里如果有多个子目录,尽量保证同一条路、同一个地块的图片只进入训练集或只进入验证集,不要混用。这样验证集才有真正的泛化意义。如果没有场景信息,也可以对图片做抽帧式的划分,每隔几帧取一张进验证集,效果比纯随机好不少。

3.3 开训前自检清单

即便数据集已经整理好,我还是建议在启动训练前花30秒过一遍自检清单。这里直接把我的习惯列出来,你可以对照检查:

  • 图片数量与标签文件数量一致,没有“孤儿”图片或“孤儿”标签
  • 所有txt里的坐标都在0到1之间
  • 类别编号是0到3之间的整数,与data.yaml的names顺序一致
  • 没有内容是空的txt文件,如果存在空文件,确认该图确实无目标,删掉txt即可
  • 训练集和验证集的图片不存在文件名重复
  • 各类别在训练集里都有一定数量的样本,像bus、van这类少数类,最少也要有几十个实例

检查完这些再开训,基本能保证问题出在模型调参而不是数据格式上。数据格式问题上花的时间,永远是最值得的。

4. 训练实测记录:三个高频问题与完整排查链路

我自己在拿类似无人机数据训练时,踩过的坑比想象中多。下面这三个问题基本是每次都会碰到的,我把完整的排查链路写出来,让你能复现思路,而不是只得到一个结论。

4.1 问题一:损失函数前期震荡,结果发现是标签遗漏

第一次用这份数据训练时,我开了300轮,结果前20轮loss像心电图一样上蹿下跳。一开始我怀疑是学习率太大,调低之后有所缓和,但验证集精度仍然异常,mAP@0.5一直卡在0.3上下。排查到后面我翻看训练日志,发现每个batch的target数量时多时少,平均每张图的标注数只有0.8个左右,而实际画面里平均应该有两到三辆车。这说明大量图片的标签文件根本没有对应的目标行。

排查过程是这样的:先统计标签文件的行数分布,发现很多txt文件大小只有几个字节,打开一看是空的;再往前查,发现数据集压缩包里的“空标注”图片在转换格式时被标注工具跳过,但没有删掉对应的txt占位文件。对于某些目标检测框架,空txt不会被当成错误,只是这张图变得没有任何目标参与训练,数据量就这样悄悄缩水了。

解决办法分两步:第一步,写脚本把所有内容为空的txt文件移出标签目录,避免它占用训练样本;第二步,如果某些图确实有目标但txt为空,就需要重新标注。对这类数据来说,删除空文件之后,训练数据有效量大约提升了15%到20%,loss曲线立刻平滑了很多。这个坑的教训是:训练日志里每个batch的target数量一定要看,它是数据质量最直接的晴雨表。

4.2 问题二:小目标漏检严重,mAP数值却不错

另一件让我困惑的事是:验证集mAP已经到0.5以上了,结果拿一段无人机实拍视频一测,小目标漏得乱七八糟。后来我把验证集的情况单独剖开看,发现mAP高是因为验证集里如果包含了大量相对较大、清晰的车辆,或者和训练集场景重叠的图片,整体指标被“拉高”了。一旦单独统计图像中小于32×32像素的目标,检测率惨不忍睹。

排查的方法是把验证集按目标尺寸分成几个区间,分别算AP:目标宽度小于32像素的AP,32到64像素的AP,大于64像素的AP。对比之后发现差距悬殊,问题就清楚了。模型不是不会检测车辆,而是对小目标没有足够的分辨能力。这类问题的通用解法是提升输入分辨率、增加小目标增强策略,或者用切图推理的思路把大图切成小块逐块检测,再合并结果。切图方案在无人机场景尤其有效,因为原图画幅大、目标小,直接缩放到模型输入尺寸时小目标丢失严重,切块之后相当于变相放大了目标。

4.3 问题三:类别分布严重不均,如何用采样和增强拉齐

数据集中car约占总标注量的七成以上,truck和bus占比很小。直接训练出来的模型往往car的AP很高,truck、bus的AP低得没法看。盲目对少数类重复采样会让模型反复看到同一批样本,结果是过拟合,训练集AP漂亮,一换场景就崩。

我的做法是组合拳:首先给少数类复制粘贴增强,从已有标注框里抠出truck、bus的目标,经过缩放、旋转后随机粘贴到没有目标或者目标稀疏的道路区域,同时生成对应的标注行;其次在训练配置里增大对少数类的采样权重,让每个epoch里少数类参与训练的次数更多;最后验证集使用最原始的分布,不做任何过采样,这样看到的指标才真实。这套组合拳跑下来,truck和bus的AP大约能提升10个点左右,car的AP基本不受影响。

5. 别止步于跑通:把数据集用到自己业务里的几个建议

数据集的最终价值在于能用起来。这份无人机车辆检测数据集作为基础数据,完全可以支撑很多实际项目,但直接照搬训练结果去部署还远远不够,下面这几个方向是我实操后觉得最值得投入的。

5.1 模型选型:小目标优先的几条路线

先给结论:小目标占比高的场景,不一定是模型越大越好,而是要看输入分辨率和特征图的匹配关系。大模型参数量多、特征提取能力强,但如果输入图被缩到640×640,远处的小车可能只占两三个像素,再强的模型也无米下锅。

我测试过几条路线:一是用高分辨率输入,直接把模型输入从640提升到1280,小目标召回率明显上升,代价是显存占用翻倍,推理速度下降;二是切图推理,把原图切成若干个带重叠的块,每块单独检测再合并,速度快、显存友好,是实现成本最低的方案;三是使用带小目标检测层的检测器结构,这类模型在特征金字塔上额外增加了针对小目标的浅层特征输出,对于航拍数据比较友好。

如果你的项目对实时性要求高,建议用轻量模型加切图推理的组合。我在一个车辆计数项目中用过这套方案,无人机图传分辨率为1920×1080,切成三四块并行推理,整体帧率还能维持在可接受的范围内。

5.2 数据增强:俯拍场景哪些增强真正有效

无人机俯拍图的一个特点是旋转不变性很强——车顶朝上还是朝左,对检测任务来说没有语义差异。因此水平翻转、垂直翻转、90度旋转这类几何增强可以大胆开,几乎不会破坏标注语义。我一般会把翻转增强概率开到0.5,旋转也开到较大值,这相当于不花成本扩充了小目标样本的朝向多样性。

相比之下,马赛克增强要谨慎一点。马赛克拼接对提升模型鲁棒性很有用,但无人机原图里的目标本身很小,拼接时如果把大量目标裁切到图像边缘,很多小目标只剩下半个框,模型学到的是残缺特征,反而有害。我的经验是把马赛克概率调低到0.3左右,并配合更大范围的随机缩放,让拼接后的目标尺度分布更接近真实场景。

色彩类的增强对无人机数据也有用。航拍图经常遇到曝光不均、云影遮挡等问题,适当的HSV扰动可以提升模型对光照变化的耐受度。但要注意饱和度扰动幅度不要过大,否则车体颜色被改得面目全非,反而干扰类别判断。

5.3 如果拍摄场景变化大,怎么扩充和再标注

实际项目里,你手里的无人机拍摄高度、云台角度、传感器型号都可能和这份数据集不同。一个非常高效的做法是:先用这份基础数据训练一个初版模型,然后对你自己采集的视频做预标注,生成初步标签,再由人工修正。别一上来就手动在几千张图上画框,那样太浪费人力。

预标注加人工修正时有个经验:视频抽帧不要逐帧标,每隔2到4帧抽一帧即可。相邻帧之间的画面几乎没变化,逐帧标注纯属重复劳动。抽帧频率取决于无人机飞行速度和车辆运动速度,飞得越快,抽帧间隔越小。还有一个小细节:预标注结果一定要按前面提到的坐标归一化规则检查,很多自动标注工具会导出像素坐标,混进训练集后会让损失函数突然恶化,这种问题几乎每批新数据都会遇到。

如果项目场景跨越很大,比如除了白天还要用夜间红外数据,基础数据集就只能作为热身。更合理的做法是在这份数据上先确定好网络结构和训练配置,然后引入少量目标场景的真值数据做微调,这种“基础数据定框架、场景数据做微调”的路径,投入产出比是最高的。

最后再分享一个个人习惯:我每次把数据集发给朋友或同事,都会提醒他们先跑一个50轮的mini实验。不是为了看精度,而是看数据管线通不通畅、loss曲线稳不稳定、标签有没有脏数据。等mini实验确认没有低级错误,再上全量数据调参数。数据集的规模固然重要,但标注质量的一致性才是决定模型上限的命门。希望这份数据集能帮你少走几步弯路,把时间花在真正有价值的算法优化上。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询