☰
旋翼无人机检测数据集:5000张已标注图,VOC与YOLO双格式,YOLOv8训练避坑指南
2026/10/11 22:34:37 网站建设 项目流程

简介:本资源为面向旋翼无人机目标检测任务的YOLO系列算法训练数据集,适合计算机视觉方向的学生、算法工程师及科研人员使用,可解决无人机场景下目标检测模型训练样本不足、标注成本高的问题。数据集已完成标注,同时提供VOC与YOLO两种标签格式,可直接接入主流检测框架进行训练与验证。压缩包共含19264个文件,其中6421张jpg原始图像、6421个xml标注文件与6422个txt标签文件,整体约672.99MB,图像与双格式标注一一对应,便于格式转换与交叉校验。类别统一为drone,本部分part1包含5000余张图像,是完整数据集的组成部分之一。目前已有1154人学习下载,读者可据此快速搭建无人机检测实验流程,用于模型训练、精度对比与算法改进,省去自行采集与标注的时间成本。

1. 旋翼无人机检测数据集:5000 张已标注图能省掉多少返工

上周帮一个做电力巡检的朋友看模型,他拿无人机航拍图训 YOLOv8,mAP 卡在 0.6 上不去,排查半天发现是标注框把整片天空都框进去了。这种返工最耗人——标 5000 张图,外包按框收费,改一轮就是一周。所以当我拿到drone-part1.zip这个包时,第一反应不是看它有多少张,而是看它的标注质量能不能直接进训练管线。

这个数据集就是冲着「旋翼无人机目标检测」这个具体任务来的:单类别drone,5000 多张图,VOC 和 YOLO 两种标签格式都给了,解压就能挂到 YOLO 系列算法上跑。它适合三类人:刚入门目标检测想找个干净数据集练手的、做低空安防或巡检需要无人机正样本的、以及拿它当负样本补充去抑制误检的。下面我按「格式怎么选 → 怎么接进训练 → 坑在哪 → 怎么验证」的顺序拆一遍,都是能直接抄的步骤。

2. 两种标签格式怎么选:VOC 与 YOLO 的转换逻辑

2.1 先搞清楚两种格式到底差在哪

VOC 格式每张图对应一个同名.xml,里面是<object>节点,坐标存的是绝对像素值xmin/ymin/xmax/ymax。YOLO 格式每张图对应一个.txt,每行class_id cx cy w h,坐标是归一化到 0~1 的相对值,且是框中心点加宽高。这个数据集两种都给了,意味着你不需要自己写转换脚本,但得知道选哪个。

我一般这么判断:如果你用 Ultralytics 系的 YOLOv5/v8/v11,直接上 YOLO 格式,省一步转换;如果你要接 MMDetection、Detectron2 或者做数据增强时想用albumentations的 VOC 解析,那就用 VOC 格式。注意一点,VOC 的xmax/ymax是包含边界的,转 YOLO 时宽高算的是xmax - xmin,别手滑写成xmax - xmin + 1,那 1 个像素的偏差在 5000 张规模上会让框整体偏大一圈。

2.2 目录结构怎么摆才能被框架认出来

YOLO 训练对目录结构有硬要求,很多人卡在「图片和标签对不上」这一步。标准摆法是这样:

# 数据集根目录结构(YOLO 格式) drone_dataset/ ├── images/ │ ├── train/ # 训练集图片,如 drone_5_3566.jpg │ └── val/ # 验证集图片 ├── labels/ │ ├── train/ # 对应 .txt 标签,文件名必须与图片同名 │ └── val/ └── data.yaml # 数据集描述文件

关键点是images/train/drone_5_3566.jpg必须对应labels/train/drone_5_3566.txt,文件名(不含扩展名)严格一致。我见过有人把标签全塞一个文件夹,训练时 loss 直接 NaN,排查两小时才发现是路径没对上。

2.3 data.yaml 的字段含义与常见写错

data.yaml是 Ultralytics 读取数据集的入口,字段不多但每个都别写错:

# data.yaml path: /home/user/drone_dataset # 数据集根目录,绝对路径最稳 train: images/train # 相对 path 的训练图路径 val: images/val # 相对 path 的验证图路径 nc: 1 # 类别数,本数据集只有 drone 一类 names: # 类别名列表,顺序即 class_id 0: drone

nc和names必须对齐,names的键从 0 开始。单类别场景下nc: 1、names: {0: drone},如果你写成names: ['drone']列表形式,新版 Ultralytics 也认,但老版本会报 key 错误。path建议写绝对路径,相对路径在不同工作目录下启动训练时容易找不到文件,这个坑我踩过不止一次。

3. 接进 YOLO 训练管线:从环境到首轮跑通

3.1 环境准备与依赖版本

数据集本身不挑框架,但 YOLO 版本和 PyTorch/CUDA 的匹配是玄学重灾区。我一般用 conda 隔离环境,避免和系统里的包打架:

# 创建并激活环境 conda create -n drone_yolo python=3.10 -y conda activate drone_yolo # 安装 PyTorch(以 CUDA 11.8 为例,按自己显卡驱动选) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 Ultralytics pip install ultralytics # 验证环境 yolo checks

yolo checks会打印 PyTorch 版本、CUDA 是否可用、GPU 型号。如果这里显示 CUDA 不可用,别急着往下跑,先解决驱动和 torch 版本匹配问题,否则训练会退回 CPU,5000 张图一个 epoch 能跑到你怀疑人生。Python 选 3.10 是因为它在 3.8~3.12 之间兼容性最稳,3.12 有些依赖轮子还没跟上。

3.2 划分训练集与验证集

数据集给的是整包,没预先分 train/val,得自己切。常见做法是 8:2 或 9:1,无人机检测这种单类别任务,我倾向 8:2,验证集留够才能看出过拟合。用脚本切比手动拖靠谱:

import os import random import shutil # 源图片和标签目录(假设解压后图片和标签分开存放) img_src = "drone_raw/images" lbl_src = "drone_raw/labels" # 目标根目录 dst_root = "drone_dataset" random.seed(42) # 固定随机种子,保证可复现 imgs = [f for f in os.listdir(img_src) if f.endswith(".jpg")] random.shuffle(imgs) split = int(len(imgs) * 0.8) # 80% 训练 train_imgs, val_imgs = imgs[:split], imgs[split:] for subset, files in [("train", train_imgs), ("val", val_imgs)]: os.makedirs(f"{dst_root}/images/{subset}", exist_ok=True) os.makedirs(f"{dst_root}/labels/{subset}", exist_ok=True) for f in files: shutil.copy(os.path.join(img_src, f), f"{dst_root}/images/{subset}/{f}") # 标签同名,扩展名换成 .txt lbl = os.path.splitext(f)[0] + ".txt" shutil.copy(os.path.join(lbl_src, lbl), f"{dst_root}/labels/{subset}/{lbl}") print(f"train: {len(train_imgs)}, val: {len(val_imgs)}")

random.seed(42)是为了让每次划分结果一致,方便复现实验。split控制比例,想改成 9:1 就把0.8换成0.9。脚本假设图片和标签已经分目录存放,如果你的压缩包是图片标签混在一起,先按扩展名筛一遍再跑。跑完打印数量,确认加起来等于总数,少一张都可能是文件名大小写或扩展名不一致导致的漏拷。

3.3 启动首轮训练与关键参数

环境好了、数据摆好了,先用小 epoch 跑通流程,别一上来就 300 epoch:

# 首轮冒烟测试,10 epoch 看 loss 是否正常下降 yolo detect train \ data=drone_dataset/data.yaml \ model=yolov8n.pt \ epochs=10 \ imgsz=640 \ batch=16 \ device=0 \ project=runs/drone \ name=smoke_test

model=yolov8n.pt用 nano 版先验证流程,权重小、跑得快。imgsz=640是 YOLO 默认输入尺寸,无人机目标通常不大,640 够用,如果小目标漏检多再上 1280。batch=16按显存调,8G 显存跑 640 大概能到 16,爆显存就降到 8。device=0指定第一块 GPU,多卡用device=0,1。跑完看runs/drone/smoke_test下的results.csv,box_loss和cls_loss应该稳步下降,如果震荡或 NaN,先回去查标签格式。

3.4 训练结果怎么读

首轮跑完重点看三个指标:metrics/mAP50、metrics/mAP50-95、val/box_loss。mAP50 是 IoU 阈值 0.5 下的平均精度,单类别无人机检测,干净数据上 10 epoch 能到 0.7 以上算正常。如果 mAP50 一直上不去但 loss 在降,多半是验证集标注有问题;如果 loss 不降,检查学习率和数据加载。confusion_matrix.png也值得看,能直观看出漏检和误检的比例。

4. 避坑与排查:标注、路径、显存三类高频翻车

4.1 标签坐标越界导致训练报错

现象:训练启动后报Label class x is invalid或normalized coordinates out of range。原因:YOLO 格式要求cx cy w h都在 0~1 之间,VOC 转 YOLO 时如果框超出图片边界,归一化后会出现负值或大于 1 的值。解决:写个校验脚本扫一遍所有标签,把越界的框裁到边界内或直接丢弃。

import os lbl_dir = "drone_dataset/labels/train" bad = [] for f in os.listdir(lbl_dir): with open(os.path.join(lbl_dir, f)) as fp: for i, line in enumerate(fp): parts = line.strip().split() if len(parts) != 5: bad.append((f, i, "字段数不对")) continue cx, cy, w, h = map(float, parts[1:]) if not all(0 <= v <= 1 for v in (cx, cy, w, h)): bad.append((f, i, f"越界: {cx},{cy},{w},{h}")) print(f"问题标签数: {len(bad)}") for b in bad[:10]: print(b)

这个脚本逐行读标签,检查字段数和坐标范围。len(parts) != 5能抓出多空格或漏字段的行。越界的框要么是标注时手抖,要么是转换脚本没做 clip,发现后回源头修,别在训练时硬扛。

4.2 图片与标签文件名不匹配

现象:训练日志显示No labels found或某张图被跳过。原因:图片是.jpg,标签可能是.JPG.txt或文件名多了空格。解决:用脚本比对两个目录的文件名集合,找出差集。

import os img_dir = "drone_dataset/images/train" lbl_dir = "drone_dataset/labels/train" imgs = {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lbls = {os.path.splitext(f)[0] for f in os.listdir(lbl_dir)} print("有图无标签:", imgs - lbls) print("有标签无图:", lbls - imgs)

差集为空才说明配对完整。有图无标签的图会被当负样本,有标签无图的标签会被忽略,两种情况都会悄悄拉低指标,不报错但结果不对,属于黑匣子式翻车。

4.3 显存溢出与 batch 设置

现象:训练中途报CUDA out of memory。原因:batch或imgsz超过显存容量。解决:优先降batch,从 16 降到 8 再到 4;还不行就降imgsz,640 降到 512。也可以用yolo detect train ... amp=True开混合精度,省显存但可能影响精度。别一上来就上大模型,yolov8n跑通再换yolov8m/l,显存不够时模型越大越容易崩。

4.4 验证集指标虚高

现象:mAP50 很高但实际推理漏检严重。原因:训练集和验证集划分时没打乱,或者验证集里同一场景的图太多,导致指标虚高。解决:划分时务必random.shuffle,并且检查验证集是否覆盖了不同光照、角度、背景。如果数据集本身场景单一,指标好看不代表泛化好,得拿真实航拍图另测。

4.5 类别 id 从 0 还是 1 开始

现象:训练不报错但检测结果全是背景。原因:VOC 的类别从 1 开始,YOLO 从 0 开始,转换时没减 1。解决:确认 YOLO 标签里class_id是 0。本数据集单类别,所有标签第一列应该都是 0,如果看到 1,说明转换脚本漏了减一操作,得批量改。

5. 进阶:用这份数据做迁移与负样本增强

5.1 拿它当预训练权重再微调

5000 张单类别数据,直接训一个通用检测器有点浪费。更划算的做法是先在这份数据上训一个无人机专用检测头,再迁移到你的具体场景(比如电力巡检、农业植保)。操作上就是正常训完yolov8n.pt,得到best.pt,然后拿它当预训练权重去训你的新数据:

yolo detect train \ data=your_dataset/data.yaml \ model=runs/drone/smoke_test/weights/best.pt \ epochs=100 \ imgsz=640 \ batch=16

这样做的价值在于:模型已经学会了「旋翼无人机」的纹理和轮廓特征,你的新场景哪怕只有几百张图,也能更快收敛。我一般会冻结 backbone 前几层先训 head,再解冻全量微调,效果比从头训稳。

5.2 当负样本抑制误检

反过来用也成立。如果你的场景里经常把鸟、风筝、远处飞机误检成无人机,可以把这份数据里的无人机图当正样本,再混入你的误检图当负样本(空标签),一起训。YOLO 对空标签图的处理是只算背景 loss,能有效压低误检。比例上正负样本 3:1 到 5:1 比较稳,负样本太多会让模型过于保守。

5.3 验证方法:别只看 mAP

训完别只盯 mAP。我习惯做三件事:一是拿val_batch0_pred.jpg看预测框和真值的贴合度,肉眼比指标诚实;二是用yolo detect predict跑一批没参与训练的图,看漏检;三是统计不同置信度阈值下的精确率和召回率,选一个适合业务的阈值。无人机检测里,漏检往往比误检代价高,所以阈值可以适当调低,宁可多框几个也别漏。

# 用训好的权重推理单张图 yolo detect predict \ model=runs/drone/smoke_test/weights/best.pt \ source=test_images/ \ conf=0.25 \ save=True

conf=0.25是默认置信度阈值,漏检多就降到 0.15,误检多就升到 0.4。source可以是单张图、目录或视频。跑完看runs/detect/predict下的结果,重点看小目标和遮挡目标。

从那以后我每次拿到新数据集,都强制先跑一遍标签校验脚本再进训练,宁可花十分钟查标签,也不花三小时等一个注定失败的 epoch。这份drone-part1.zip的标注质量在单类别数据集里算干净的,VOC 和 YOLO 双格式省了转换的麻烦,5000 张规模够训一个可用的基线。希望帮到你。

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

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

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

立即咨询