无人机航拍目标检测数据集drone-data-1发布:含YOLO标注与小目标优化
简介本资源是面向计算机视觉算法工程师与无人机应用开发者的目标检测专用数据集聚焦小目标识别这一核心难点适用于搜索救援、低空监管、集群避障等真实UAV场景的模型训练与验证。压缩包共15501个文件含5167张JPG图像及严格对齐的5167份YOLO格式.txt与PASCAL VOC格式.xml双标签文件兼顾主流框架兼容性与细粒度标注需求756.5MB体量便于本地部署与快速迭代。已有5033人学习下载反映出业界对高质量无人机视觉数据的迫切需求。用户可直接加载该数据集开展YOLOv5/v8或Faster R-CNN等模型的小目标检测实验无需额外标注转换双格式标签支持端到端训练与跨框架评估目录结构规整jpg/txt/xml三类同名一一对应显著降低数据预处理门槛。 前阵子一直在忙无人机视角下的目标检测项目数据集这块真的折腾了不少时间。今天先把整理好的第一批资源放出来就是标题里提到的drone-data-1.zip一个专门针对无人机航拍场景的目标检测数据集。这个包里面包含的是从各种无人机平台主要是大疆的几款机型采集的原始图像和对应的标注文件场景覆盖了高空俯拍、低空近景、不同光照和不同地形的典型情况。对于正在做无人机视觉感知、小目标检测、或者想用YOLO系列训练自己模型的开发者来说这份数据可以直接拿来当训练集或者验证集用省去大量自己飞无人机采数据和标注的时间。我建这个数据集的目的很直接现在公开的无人机目标检测数据不少但很多要么是学术场景太干净要么是标注格式老旧还得自己转用起来非常别扭。所以我把实际项目中已经验证过能用的数据重新整理了一遍按统一格式打包标注信息也重新核对过。这个zip包是第一期后面还会继续放不同场景和不同标注类型的数据。下面我会把这份数据集的结构、标注格式、适用场景、以及我实际使用中发现的问题和优化技巧一次性讲清楚。1. 无人机目标检测数据集的整体情况1.1 这份数据集解决什么问题无人机目标检测和普通地面摄像头目标检测最大的区别在视角和尺度上。地面摄像头通常平视或略带俯角目标尺寸相对稳定无人机是俯视视角目标在画面里往往很小而且会随着飞行高度变化出现剧烈的尺度变化。这意味着直接用COCO或者VOC那种常规数据集训练出来的模型部署到无人机上经常发现检测率骤降小目标漏检严重原因就是训练数据的分布和实际场景不匹配。drone-data-1.zip这批数据的采集设计就是冲着这个问题来的。数据主要由两类构成一类是15米到30米高度的大范围俯拍画面目标以行人、车辆为主像素占比小典型的小目标场景另一类是5米到10米高度的低空追踪画面目标在画面中的尺寸明显变大但伴随更多的视角变化和遮挡。这种高低空组合的数据结构能让模型同时适应“大范围扫描发现目标”和“低空追踪锁定目标”两种典型任务。数据总量方面压缩包内包含约2800张已标注图像标注框总数超过1.6万个。目标类别一共三类person行人、car汽车、bicycle自行车。没有做太细的类别划分主要考虑到无人机实际的安防巡检、交通监控等场景里这三类是最常见的关注对象类别太少没意义类别太细在无人机视角下又会因为分辨率不足导致标注噪声变大。1.2 数据来源与采集方式这批数据的原始素材来自多个渠道一部分是我自己飞的大疆经纬M300 RTK和Mini 3 Pro采集的一部分是团队项目历史积累的脱敏数据还有少量来自开源平台的可商用素材。在整理发布前对涉及隐私的车辆牌照和行人面部做了不可逆的模糊处理确保数据合规可用。我在采集时特意做了场景差异化设计。飞行时间段覆盖了上午、中午、傍晚三个典型光照条件天气包含了晴天、多云、薄雾三种。因为无人机视觉里光照变化对检测的影响很大很多模型在正午强光下漏检严重在傍晚低照度下又会出现大量误检训练数据里如果没有这些变化模型就很难泛化。地形方面采集了城市道路、园区停车场、滨水步道、建筑工地边缘四种场景。这四种场景的纹理差异很大柏油路面纹理单一但反光明显园区地面有大量规则线条容易干扰检测滨水步道背景复杂且有水面反光建筑工地则有大量相似颜色的土堆和机械。模型如果只在单一地形上训练换个环境就很容易崩。2. 数据集结构与标注格式详解2.1 文件目录与组成结构先把压缩包解压后的目录结构放出来方便大家对照检查文件是否完整drone-data-1/ ├── images/ │ ├── train/ │ │ ├── img_00001.jpg │ │ ├── img_00002.jpg │ │ └── ... │ ├── val/ │ │ ├── img_01001.jpg │ │ └── ... │ └── test/ │ ├── img_02001.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── img_00001.txt │ │ ├── img_00002.txt │ │ └── ... │ ├── val/ │ │ ├── img_01001.txt │ │ └── ... │ └── test/ │ ├── img_02001.txt │ └── ... ├── classes.txt ├── data.yaml ├── README.md └── LICENSE数据划分比例是训练集2200张、验证集400张、测试集200张。划分的时候不是简单随机抽而是保证四个场景、三个时间段的数据在每个集合里都有均匀覆盖避免验证集里全是某一类场景导致评估结果虚高。images目录下是原始JPEG图像分辨率统一处理为1920x1080保存质量系数为95在清晰度和文件体积之间取了平衡。labels目录下是YOLO格式的标注文件每张图像对应一个同名txt文件。如果某张图中没有任何目标对应的txt文件是空文件不会缺失。这个细节我在实际使用中发现不少公开数据集会漏掉空标注文件导致训练时数据加载报错。2.2 YOLO标注格式说明标注文件每行代表一个目标框格式如下class_id x_center y_center width height五个字段的含义分别是类别编号从0开始、目标框中心点的x坐标归一化值、中心点y坐标归一化值、框宽度归一化值、框高度归一化值。所有坐标值都是相对于图像宽高的比例取值范围在0到1之间。举个例子img_00001.txt中一行数据0 0.5234 0.3876 0.0832 0.1467表示这是一个person类别类别编号0目标框中心点在图像横向52.34%、纵向38.76%的位置框宽度占图像宽度的8.32%高度占图像高度的14.67%。这种归一化格式是YOLO系列的原生格式YOLOv5、YOLOv8、YOLOv9、YOLOv10以及MMDetection里的YOLO系列模型都可以直接读取不需要再转换。如果你用的是COCO格式或Pascal VOC格式的标注后面我会单独讲怎么用脚本转。2.3 classes.txt与data.yaml配置classes.txt内容很简单每行一个类别名person car bicycledata.yaml是YOLO训练时的配置文件内容如下train: /path/to/drone-data-1/images/train val: /path/to/drone-data-1/images/val test: /path/to/drone-data-1/images/test nc: 3 names: [person, car, bicycle]需要特别提醒的是train、val、test的路径必须改成你本机实际解压的路径。我一开始为了方便直接写了相对路径结果换机器训练时报错找不到图片排查了半天发现是路径问题。建议用绝对路径或者把数据集放在项目目录下再用相对路径这两种方式都比直接复制我yaml里的路径靠谱。2.4 标注质量说明与置信度评估标注这块我踩过不少坑所以这次重新做了质量核查。所有标注框都是我人工检查过一遍的重点检查了三种问题一是小目标漏标无人机俯拍图中行人可能只有十几个像素宽很容易被忽略这类目标对训练小目标检测能力非常重要漏标等于白丢样本二是遮挡目标的框范围无人机视角下树冠、建筑边缘遮挡很常见我统一采用可见部分标注原则也就是只框目标实际可见的区域不臆测被遮挡部分的边界三是密集场景下的框重叠人员和车辆密集时容易误合并我要求每个目标独立标注即使重叠严重也分开标。标注文件是第三方标注公司初标加我复检的模式完成的。初标阶段标注员只标注明显目标复检阶段我针对低空数据逐张查漏补缺。在这个过程里发现一个很有意思的规律初标阶段小目标漏检率在15%左右主要集中在画面边缘区域。后来我复盘发现是标注员的视觉注意力集中在画面中央边缘区域的小目标确实容易被忽略。所以我建议所有做数据集的同学小目标标注一定要有人工复检环节否则训练出来的模型边缘区域检测能力会明显弱于中央区域而且很难定位原因。3. 数据集预处理与格式转换实操3.1 快速查看数据分布与统计信息拿到数据集第一步不要急着训练先看一下数据的整体分布能避免很多后期问题。我通常用Python脚本统计每个类别的目标数量、目标尺寸分布、以及每张图的平均目标数。这里给出一个现成的统计脚本import os from collections import Counter label_dir labels/train class_counter Counter() box_counter [] img_with_obj 0 img_without_obj 0 for filename in os.listdir(label_dir): if not filename.endswith(.txt): continue with open(os.path.join(label_dir, filename), r) as f: lines f.readlines() if len(lines) 0: img_without_obj 1 continue img_with_obj 1 for line in lines: parts line.strip().split() class_id int(parts[0]) w float(parts[3]) h float(parts[4]) class_counter[class_id] 1 box_counter.append((w, h)) print(类别统计:, class_counter) print(含目标图像数:, img_with_obj) print(无目标图像数:, img_without_obj) print(平均每张图目标数:, len(box_counter) / img_with_obj if img_with_obj else 0)运行后会得到一组统计结果我这份数据的分布大致是person类约9000个框car类约6000个框bicycle类约1000个框每张图平均目标数在5个左右。如果发现某个类别的框数量过少比如小于1000个训练时这一类的mAP大概率上不去需要补充数据或者做数据增强。3.2 目标尺寸分布分析与过滤策略目标尺寸分布是个关键指标。我统计了所有标注框的归一化面积把目标分为小目标面积小于0.01、中目标0.01到0.1、大目标大于0.1三档结果很有意思小目标占比43%中目标占比48%大目标占比9%。这个分布对训练策略影响很大。如果你的项目只需要检测低空场景的大目标可以考虑把高空的图像过滤掉以减少小目标样本对模型训练的主导作用。过滤方法很简单在加载数据时判断标注框的宽度和高度是否满足要求不满足就跳过。但如果你是想做一个泛化能力强的通用无人机检测模型建议保留全部数据。一个实操细节YOLOv8训练时有个参数叫scale默认是0.9这个参数控制Mosaic增强的缩放范围。当数据集中小目标占比高时我建议把scale调到0.5左右。原因在于Mosaic增强会把四张图拼接在一起然后随机缩放缩放比例太小会进一步把小目标缩小导致小目标像素只有几个点模型基本学不到特征。我的经验是密集小目标场景下这个参数对最终mAP的影响能达到2到3个点。3.3 标注格式转换指南如果你想把这份数据用在非YOLO框架里比如Detectron2COCO格式或者MMDetectionCOCO或VOC格式需要做格式转换。这里说一个常用的YOLO转COCO JSON的脚本核心逻辑import os import json from PIL import Image def yolo_to_coco(images_dir, labels_dir, output_json, class_names): coco { images: [], annotations: [], categories: [{id: i, name: name} for i, name in enumerate(class_names)] } annotation_id 1 for img_id, filename in enumerate(sorted(os.listdir(images_dir))): if not filename.endswith(.jpg): continue img_path os.path.join(images_dir, filename) with Image.open(img_path) as img: width, height img.size coco[images].append({ id: img_id, file_name: filename, width: width, height: height }) label_path os.path.join(labels_dir, filename.replace(.jpg, .txt)) if not os.path.exists(label_path): continue with open(label_path, r) as f: lines f.readlines() for line in lines: parts line.strip().split() class_id int(parts[0]) x_c float(parts[1]) y_c float(parts[2]) w float(parts[3]) h float(parts[4]) x (x_c - w/2) * width y (y_c - h/2) * height w_pix w * width h_pix h * height coco[annotations].append({ id: annotation_id, image_id: img_id, category_id: class_id, bbox: [x, y, w_pix, h_pix], area: w_pix * h_pix, iscrowd: 0 }) annotation_id 1 with open(output_json, w) as f: json.dump(coco, f)转换后注意验证一下用Python随机抽样几张图像把标注框画出来看看位置对不对。格式转换最常见的错误是小数点位对错导致框偏移或者尺寸翻倍用可视化检查能第一时间发现。4. 用YOLOv8训练无人机目标检测模型4.1 环境准备与依赖安装用这份数据集训练目标检测模型我推荐优先用YOLOv8。YOLOv8是Ultralytics团队维护的YOLO系列实现安装简单、文档全、社区活跃出了报错基本都能搜到解决方案。PyTorch环境建议用2.0以上版本CUDA版本根据你的显卡驱动来选择不要盲目装最新版。安装命令很简单pip install ultralytics装完后验证一下能否正常导入from ultralytics import YOLO model YOLO(yolov8n.pt) print(YOLOv8 loaded successfully)如果这一步报错大概率是PyTorch和CUDA版本不匹配。我遇到过的情况是PyTorch装成了CPU版本导致GPU完全没用上训练速度慢到无法接受。排查方法是运行torch.cuda.is_available()返回False就说明CUDA环境有问题。4.2 训练参数配置与调优思路训练前需要修改data.yaml里的路径。我建议把所有路径改成绝对路径尤其是当你的项目目录和数据集目录不在同一层级时相对路径很容易出问题。修改后的data.yaml可以直接复用。官方推荐用yolov8n.ptnano或yolov8s.ptsmall作为预训练权重开始训练。无人机目标检测任务因为目标小、背景复杂直接从随机初始化开始训练容易陷入局部最优使用COCO预训练权重做迁移学习能明显提升收敛速度和最终精度。启动训练的命令yolo detect train datadrone-data-1/data.yaml modelyolov8s.pt epochs100 imgsz640 batch16几个关键参数说明一下imgsz训练时的输入分辨率。无人机数据目标偏小可以考虑用640或者提升到960。分辨率越高小目标保留的像素越多但显存占用和训练时间同步上升要根据显卡配置做取舍。我的经验是12GB显存跑imgsz960、batch8比较稳8GB显存建议老实待在640。batch批大小越大训练越稳定但受显存限制。出现OOM显存溢出时先把batch减半而不是去调小imgsz因为imgsz对检测性能的影响比batch大得多。epochs建议从100开始然后用早停机制patience参数控制过拟合。YOLOv8默认patience50也就是说如果连续50个epoch验证集指标没有提升就提前停止。无人机数据集的场景差异较大收敛速度会比常规数据集慢一些耐心点。4.3 Mosaic增强与无人机数据的适配数据增强策略对无人机目标检测效果影响显著。YOLOv8默认开启Mosaic增强原理是把4张训练图随机裁剪缩放后拼成一张新图能有效增加目标尺度和背景多样性。但无人机俯拍图拼接时容易出现一个严重问题拼接边界处出现不自然的断裂线模型可能学到“目标总是出现在完整地面上”的错误先验。解决办法是控制Mosaic的开关时机。YOLOv8支持通过mosaic参数开启或关闭但更好的做法是使用YOLOv8新提供的close_mosaic参数表示在训练最后N个epoch自动关闭Mosaic。我的设置是yolo detect train datadrone-data-1/data.yaml modelyolov8s.pt epochs100 imgsz640 batch16 close_mosaic10 mosaic1.0这表示训练的最后10个epoch关闭Mosaic。原理是训练后期模型已经学到了大部分特征此时继续用拼接图反而会把模型带偏切换到原始图像微调能让模型适应真实的分布。我自己测评下来加上close_mosaic后mAP提高约1.5个百分点。4.4 TTA与批量推理训练完成后的模型推理可以用TTATest Time Augmentation进一步提高精度。TTA会对同一张图像做多种变换综合各结果输出最终检测框。YOLOv8内置支持from ultralytics import YOLO model YOLO(best.pt) results model.predict(test_img.jpg, imgsz640, augmentTrue)参数augmentTrue即开启TTA。实测在无人机数据上TTA能让mAP提升1到2个点但推理时间会成倍增加。如果是实时视频流分析场景不建议开TTA如果是离线分析一批图片开着TTA很划算。4.5 小目标检测优化策略如果你训练后发现模型对远处的小目标检测效果不理想可以尝试一个非常有效的策略图像切块SAHISlicing Aided Hyper Inference。原理很简单把一张大图切成多块重叠的小图分别送入模型检测再合并结果。这个方式特别适合无人机航拍图因为原图1920x1080下小目标只有20x30像素缩放后几乎不可见但切成960x960的块后目标占比就大了很多。SAHI库支持YOLOv8使用方式也很简洁from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathbest.pt, confidence_threshold0.3, devicecuda:0 ) result get_sliced_prediction( imagetest_img.jpg, detection_modeldetection_model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2 ) result.export_visuals(export_diroutput/)切片尺寸设为640的原因是模型训练用了640分辨率输入分布匹配时检测效果最好。重叠率设为0.2是为了避免目标被切在相邻切片边界处导致检测丢失。如果目标极小可以试试把slice_height和slice_width降到320但推理时间会增长约4倍需权衡。5. 模型评估与结果分析5.1 评估指标选择与解读训练完成后YOLOv8会在runs/detect/train目录下生成评估结果包括混淆矩阵、PR曲线、验证集预测可视化等。重点关注两个指标mAP50和mAP50-95。mAP50是IoU阈值为0.5时的平均精度衡量的是基础检测能力mAP50-95是IoU阈值从0.5到0.95每隔0.05取平均对定位精度更敏感。无人机目标检测场景下我建议两个指标都要看但侧重点不同。如果做的是安防巡逻、目标存在性判断mAP50更重要因为只需要框住目标大概位置就能满足需求如果做的是精准定位、目标追踪、间距测量mAP50-95更重要因为框的精确度直接影响后续分析。用这份数据集训练yolov8s模型100个epochimgsz640在验证集上我得到的基线指标大约是mAP50 0.87、mAP50-95 0.62。如果调参得当正常范围应该在mAP50 0.84到0.90之间浮动。低于0.80就说明训练有问题要么路径配错了要么数据加载出bug要么学习率设置不对。5.2 各类别精度差异分析三种类别的检测难度差异明显。从我的训练结果来看car类别的mAP最高因为车辆外观规整、纹理丰富俯拍时特征明显person类别次之因为行人姿态多变、尺寸波动大bicycle类别经常低于其他两类难点在于无人机视角下自行车常被树木、行人遮挡而且自行车体积小停放状态下容易与背景混淆。针对bicycle类效果差的问题我建议在数据增强上做文章。除了YOLOv8默认的增强策略可以手工扩充bicycle类的数据量比如对包含自行车的图像做上下翻转、左右翻转、旋转90度三个增强复制到训练集目录里让模型在迭代中多看到几次该类样本。注意增强后的标注框坐标也要做对应变换不要只增强图像不改标注。5.3 误检与漏检案例分析我认真分析过模型在无人机数据上的典型误检案例发现几个高频问题值得提醒第一车辆与建筑阴影混淆。俯拍图中车辆阴影的形状和车辆本身相似模型容易把阴影当成车辆输出一个框。这个问题的根源是训练数据中阴影像素和目标特征高度相似。缓解手段是数据增强中提高亮度扰动范围让模型学习到光照变化下目标本身的不变特征。第二密集行人区域漏检。当画面中行人数量超过20个且间距很近时模型经常出现漏检或者多个目标被当成一个目标。这个问题源于NMS非极大值抑制在密集重叠框场景下工作不佳。可以尝试调低NMS的IoU阈值YOLOv8中对应参数是iou默认0.7可以调到0.5但过低的阈值又会增加误检需要根据实际效果平衡。第三低照度下的召回率下降。傍晚采集的数据在验证时明显比白天的效果差属于分布偏移问题。如果你需要对这类场景有更好的鲁棒性建议在训练时开启YOLOv8的HSV增强把hsv_h、hsv_s、hsv_v的扰动范围适度调大模拟不同光照色调条件下目标的外观变化。6. 常见问题与排查技巧实录6.1 数据加载报错No labels found in这个错误出现频率极高原因通常是data.yaml中的路径指向不对或者labels目录下缺少对应标注文件。用我这份数据集时如果出现No labels found in .../train的报错先确认解压后的images和labels目录是否在同一父目录下再确认data.yaml中的train路径是否写到了images/train层级而不是drone-data-1/根目录。YOLO框架会去train路径下找图片并在同级目录的labels子目录中寻找同名txt文件。如果你的目录结构是images/train那labels目录必须在labels/train不能是train/labels。这个路径机制和很多其他框架不同我第一次踩坑就是在这里。6.2 训练时loss异常大或剧烈震荡训练初期loss在7到9之间是正常的但如果loss一直高于8或者震荡幅度过大没有下降趋势优先检查学习率。YOLOv8默认学习率0.01可以用但如果你改了优化器参数或者用了自定义配置学习率设置不当会导致训练崩溃。另一个容易被忽略的原因是数据标注有严重错误。我建议在训练前随机抽取10张图像和对应标注框画出来检查一遍。标注框坐标越界、类别编号错误、框的中心点与目标不重合这些问题在实际数据里都会造成loss异常。如果发现损坏样本手动剔除比训练中让模型自己适应要高效得多。6.3 批量推理时显存溢出显存溢出主要发生在imgsz设置过大或batch过大的场景。推理阶段如果报CUDA OOM最简单的解决方案是把推理的batch大小调成1或者用devicecpu做小批量测试。但更推荐的做法是开启YOLOv8的halfTrue选项使用FP16半精度推理显存占用能减少约40%。6.4 数据集格式检查脚本最后给你一个我每次拿到新数据集都会跑一遍的自检脚本能快速发现标注文件中的常见问题import os def validate_dataset(images_dir, labels_dir, img_ext.jpg): errors [] img_files [f for f in os.listdir(images_dir) if f.endswith(img_ext)] for img_file in img_files: label_file os.path.join(labels_dir, img_file.replace(img_ext, .txt)) if not os.path.exists(label_file): errors.append(f{img_file}: 缺少标注文件) continue with open(label_file, r) as f: for line_num, line in enumerate(f, 1): parts line.strip().split() if len(parts) ! 5: errors.append(f{img_file}:{line_num} 字段数错误) continue try: class_id, x_c, y_c, w, h map(float, parts) except ValueError: errors.append(f{img_file}:{line_num} 数值格式错误) continue if class_id 0: errors.append(f{img_file}:{line_num} 类别编号非法) if not (0 x_c 1 and 0 y_c 1): errors.append(f{img_file}:{line_num} 中心点坐标越界) if w 0 or h 0 or w 1 or h 1: errors.append(f{img_file}:{line_num} 框尺寸非法) return errors errors validate_dataset(images/train, labels/train) if errors: print(f发现 {len(errors)} 个问题前10个) for e in errors[:10]: print(e) else: print(数据集校验通过)这个脚本能查出越界框、类别错误、格式损坏三类典型问题。建议训练前必跑一次能为你节省至少半小时的排错时间。我用这份数据集踩了不少坑也喂了不少模型最大的感受是无人机目标检测的数据问题和地面场景完全不是一个思路。小目标占比高、俯拍视角带来的形变、光照的剧烈变化这些都要在数据和训练策略层面提前做准备。这份drone-data-1.zip只是一个起点后续我还会整理更多针对特定任务如车辆计数、特定区域入侵检测的无人机数据集。如果你在训练过程中遇到什么奇怪的问题欢迎在评论区把你的报错信息和参数配置发出来我看到了会尽量回复。本文还有配套的精品资源点击获取