无人机识别数据集实战:YOLOv8训练与小目标检测优化指南
简介面向无人机识别与目标检测任务的数据集资源专为YOLO系列v5至v10、Faster RCNN、SSD等深度学习模型训练设计适合目标检测方向的算法研究者、竞赛团队及学生实战练习无论是入门YOLO框架还是进行算法对比实验都能快速上手。压缩包约814MB内含1999个txt标签与1个yaml配置等2000个标注文件并提供XML标签及对应图片满足VOC与YOLO双格式使用需求txt标签采用归一化坐标yaml文件指定类别信息方便主流框架直接读取。数据集对应9229张无人机图片已按训练集、验证集、测试集划分完毕可无缝接入YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10等算法省去数据预处理与格式转换的繁琐步骤直接聚焦模型调优与结果分析。资源目录结构清晰便于按需取用目前已有339人学习下载是无人机检测相关项目与实验的高效起点。1. 无人机识别数据集小目标检测绕不开的“第一块砖”无人机目标的物理尺度通常只有几十个像素加上云层、树木、建筑背景的干扰直接拿 COCO 预训练模型去跑误检率会高到没法看。这也是为什么无人机识别不能只靠模型结构数据集的标注质量、类别定义和训练/验证/测试划分是否合理直接影响最终 mAP。这套 9229 张图片的无人机识别数据集同时提供 YOLO txt 和 VOC xml 两种标注内置类别 yaml 文件并且已经按 8:1:1 左右的比例切分好下载解压后不需要再写划分脚本适合想快速上手 YOLOv5 到 YOLOv10 系列、或者想对比 Faster RCNN 与 SSD 效果的从业者。对于做小目标方向的同学这份数据的价值不只在“能训练”更在于你可以从标签组织方式里反推数据制作规范。2. 数据组织方式txt 标签如何对应到 YOLO 训练管线2.1 目录结构与文件命名规则数据集根目录下通常是images和labels两个主体目录其中labels里同时存在*.txt和*.xml。txt 文件是 YOLO 格式的标注xml 文件是 VOC 格式的标注二者描述的是同一批目标。图片命名类似Drone_4235.jpg与标签文件Drone_4235.txt保持同名这套命名规则能直接被 YOLO 系列的检测器读取不需要额外做文件名映射。dataset/ ├── images/ │ ├── train/ │ │ ├── Drone_0001.jpg │ │ └── ... │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ │ ├── Drone_0001.txt │ │ └── ... │ ├── val/ │ └── test/ ├── drone.yaml └── annotations/ └── Drone_0001.xmlimages和labels同级且 train/val/test 子目录保持一致这是 YOLOv5 之后推荐的布局方式。如果你用的是旧版 YOLOv3需要自己写一个train.txt路径列表文件而 YOLOv8 及以上直接读drone.yaml里的路径配置就行。2.2 YOLO txt 标签的五个字段含义打开任意一个Drone_xxxx.txt每一行代表一个目标框格式为class_id x_center y_center width height其中x_center、y_center、width、height都是相对图片宽高的归一化数值取值范围是 0~1。比如一行0 0.5123 0.4789 0.0456 0.0521表示类别为 0目标中心点位于图片横向 51.23%、纵向 47.89% 的位置前景框的宽和高分别占图片宽度的 4.56% 和 5.21%。归一化的好处是无论输入图片是 640x640 还是 1280x720模型都能以相对坐标计算损失。不过这里有个容易踩的坑如果从 VOC 的 xml 转换时直接用了整数像素坐标而没有除以宽高训练时会出现 loss 异常或者检测框偏向图像边缘。检查方式很简单写个脚本看标签值是否有大于 1 的import os label_dir labels/train for f in os.listdir(label_dir): if not f.endswith(.txt): continue with open(os.path.join(label_dir, f)) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: print(f格式错误: {f} - {line}) else: vals list(map(float, parts[1:])) if any(v 0 or v 1 for v in vals): print(f归一化超界: {f} - {line})这个脚本遍历训练集标签检查每一行是否恰好 5 个字段以及边框坐标是否在 0~1 范围内。第二个any()判断特别重要很多数据集在手工标注后容易出现某个框的width大于 1导致训练时 anchor 匹配失败。2.3 VOC xml 与类别 yaml 的对应关系VOC 格式用 xml 保存目标信息结构里每个object节点包含name和bndbox。这套数据集的 xml 是为兼容 Faster RCNN、SSD 这类需要 Pascal VOC 格式的框架准备的。如果要用 Detectron2通常还需要把 xml 转成 COCO json转换时注意name要和 yaml 里的类别顺序一致。drone.yaml是 YOLO 系列的配置入口关键内容如下path: /your/absolute/path/dataset # 数据集根目录 train: images/train # 训练图片相对路径 val: images/val # 验证图片相对路径 test: images/test # 测试图片相对路径可选 nc: 1 # 类别数量这里是单类 names: 0: dronepath最好写成绝对路径否则训练时容易出现Dataset not found。train和val指向的路径是相对于path的目录YOLO 会自动去labels目录中寻找与图片同名同名的 txt。如果你的标签文件没有放在labels子目录而是和图片混在一起训练前一定要改回来。以下表格总结了三种标注文件的适用场景格式典型框架标注内容使用要点YOLO txtYOLOv5~v10类别id、归一化cxcywh每行一个目标直接供训练VOC xmlFaster RCNN、SSD类别名、像素坐标 xmin/ymin/xmax/ymax需要转换工具才能用于 YOLOyamlYOLO 系列路径、类别数、类别名训练时通过data参数指定3. 用 YOLOv8 在无人机数据集上训练从配置到命令行3.1 环境准备与数据校验训练 YOLOv8 需要ultralytics包建议使用 Python 3.9 或 3.10PyTorch 2.0 以上。安装命令pip install ultralytics安装完成后先执行一次数据校验确认图片和标签配对正常yolo detect train datadrone.yaml modelyolov8s.pt epochs1这里故意只跑一个 epoch不是为了训练结果而是为了触发数据集加载流程。如果标签路径配置有误YOLO 会在加载阶段直接报错并告诉你缺了哪些文件。正常情况会在统计信息里显示train: images/... (xxx images)和val: images/... (xxx images)同时输出各类别目标数量。看到类别0: drone计数非零说明标签匹配成功。3.2 训练参数选择与释义无人机检测场景里输入分辨率设置比模型大小更敏感。我一般先把imgsz设为 1280因为无人机在整幅图中占比太小640 分辨率下目标区域可能只有十几个像素特征图上的响应弱到无法回传梯度。但注意分辨率的提高会成倍增加显存占用如果显卡只有 8GB可以先用 640 跑通流程再用 1280 微调。基准训练命令如下yolo detect train \ datadrone.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ lrf0.01 \ mosaic1.0 \ scale0.5 \ fliplr0.5 \ device0modelyolov8s.pt加载 COCO 预训练权重迁移学习对小目标数据集的收敛速度有明显帮助。imgsz640训练尺寸后文进阶部分会说明如何调大。mosaic1.0启用马赛克增强把 4 张图拼成 1 张增加目标周围背景的多样性。但注意无人机目标普遍小mosaic 拼图后目标会被进一步缩小可能导致标注小于 3 像素而被过滤。如果后续发现小目标检测效果不佳可以尝试mosaic0.5或者关闭。scale0.5随机缩放的幅度。这个值不宜太大否则部分无人机缩成几个像素模型只能当作噪点学。训练完成后权重保存在runs/detect/train/weights/下best.pt是在验证集上 mAP 最高的权重last.pt是最后一轮的权重。调参时建议用best.pt继续训练而不是重新从头开始。3.3 验证与测试阶段的使用验证集上的结果能直观反映模型真实水平命令如下yolo detect val \ datadrone.yaml \ modelruns/detect/train/weights/best.pt \ imgsz1280这里我把imgsz改成 1280是为了对比训练和推理分辨率不一致时的性能差距。如果训练是 640直接拿 1280 去验证结果会略微下降因为模型看到的尺度分布变了。正确的做法是训练和验证使用相同分辨率或者分别在 640 和 1280 上验证取较优者作为最终推理配置。4. 训练中的典型坑标签过滤、类别不均衡与增强策略4.1 目标尺寸过小被过滤在 YOLOv8 的增强管线里有一个按像素过滤小目标的逻辑。如果标注框的宽或高小于 2 像素会被当成噪点直接丢弃。无人机数据集里如果包含大量远距离小目标这些目标的标签可能只有 1~3 像素一旦被过滤模型相当于从未见过这部分样本最终推理时漏检率会很高。排查方法是在训练日志里观察Github那一行输出的目标数量或者自定义数据集类统计每个框的像素大小。常见做法是写一个分析脚本from pathlib import Path import cv2 img_dir Path(images/train) label_dir Path(labels/train) pixel_areas [] for img_path in img_dir.glob(*.jpg): img cv2.imread(str(img_path)) h, w img.shape[:2] label_path label_dir / (img_path.stem .txt) if not label_path.exists(): continue with open(label_path) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: continue _, cx, cy, bw, bh map(float, parts) box_w int(bw * w) box_h int(bh * h) pixel_areas.append(box_w * box_h) pixel_areas.sort() print(最小面积, pixel_areas[0], 中位数, pixel_areas[len(pixel_areas)//2])如果中位数面积小于 100 像素说明小目标占主流训练时需要增大输入分辨率或者关闭那些会缩小目标的增强项。4.2 单类数据集上的类别不均衡问题这个数据集只有drone一个类别所以不存在多类别数量悬殊的问题但存在单类内部的“尺寸不均衡”。比如近景无人机面积大、数量少远景无人机面积小、数量多模型会偏向学习容易拟合的远景样本近景大目标反而识别不准。我处理这种问题时会使用copy_paste增强把大目标样本粘到小目标样本图上人为增加大目标出现概率。YOLOv8 设置方式是在训练参数里加yolo detect train datadrone.yaml modelyolov8s.pt copy_paste0.3copy_paste0.3表示有 30% 的概率执行复制粘贴操作。这个增强对小目标数据集是有风险的因为粘贴的大目标可能遮挡原有的小目标训练时目标之间的遮挡会影响损失计算。所以如果用它建议同时把mosaic降到 0.7避免多种强增强叠加导致过度扰动。4.3 增强参数调整的边界yaml 中有一类增强参数比如hsv_h、hsv_s、hsv_v分别控制色调、饱和度和明度的随机变化。对无人机这种天空背景颜色扰动太大反而会把目标颜色改得不像真实物体。我一般会限制hsv_h: 0.015 hsv_s: 0.4 hsv_v: 0.4上面hsv_h表示色调偏移范围是 0.015 的倍数如果改成 0.1无人机可能从白色变成蓝色训练时模型会努力去拟合一个不真实的目标“变色”规律。同理scale和translate参数也尽量保守因为无人机检测的场景中目标通常静止或缓动过大的位置偏移会让模型丧失空间先验。4.4 验证集 mAP 与真实场景差距YOLO 在验证时默认使用 640 推理尺寸并且会做多尺度测试之外的 NMS。实际使用中监控视频里的无人机可能出现在全图任意位置且没有像训练集那样经过中心对齐。验证指标 mAP 高不代表现场好用。建议在测试集上单独计算F1-score并统计不同距离区间近中小目标对应的大于/小于特定像素的漏检率。命令可以加上verboseTrue导出每张图的结果yolo detect val datadrone.yaml modelbest.pt conf0.25 iou0.5conf0.25是置信度阈值低于 0.25 的检测框会被丢弃iou0.5是 NMS 的 IoU 阈值。无人机检测场景中置信度阈值建议从 0.25 往下降比如 0.15这样能多召回一些模糊的远距离目标代价是误报增加。调阈值时要在误报与漏报之间找平衡点而不是只看 mAP。5. 小目标优化路线SAHI 切片推理与输入分辨率的选择5.1 为什么要对无人机使用切片推理即使是 YOLOv8在 640 分辨率下对一张 1920x1080 画面做推理远处的无人机可能只占 8x8 像素下采样 8 倍后只剩 1 个像素特征层基本没有响应。直接放大输入到 1920 又会超出显存限制。SAHISlicing Aided Hyper Inference是常用的解决方案把大图切成多个重叠的小块分别推理后再把检测框映射回原图坐标。SAHI 配合 YOLO 的用法pip install sahifrom sahi.model import Yolov8DetectionModel from sahi.predict import get_sliced_prediction model Yolov8DetectionModel( model_pathbest.pt, confidence_threshold0.2, devicecuda:0, ) result get_sliced_prediction( image_pathtest_frame.jpg, detection_modelmodel, slice_height320, slice_width320, overlap_height_ratio0.2, overlap_width_ratio0.2, )slice_height和slice_width设置切片尺寸320 意味着每个切片只有原来图像的三十分之一左右目标在切片里相对尺寸变大。overlap_height_ratio和overlap_width_ratio是切片重叠比例设 0.2 是为了避免目标恰好在切片边缘被切断。切片尺寸不是越小越好太小的切片会丢失上下文信息比如无法区分远处无人机和飞鸟一般取原图短边的 1/4~1/3。5.2 训练分辨率到底该调多大SAHI 是推理阶段的补救措施但对训练阶段提高imgsz是从源头改善小目标特征的最直接路径。我在 8GB 显存环境下通常这样分阶段训练先用imgsz640、batch16训练 50 轮让模型学习基本特征。加载best.pt改为imgsz1280、batch4继续训练 30 轮。第二步相当于微调学习率要调低例如lr00.001。原因是 1280 分辨率的特征图尺寸是 640 的 4 倍模型需要重新调整对目标尺度的敏感度但基础特征提取层已经很熟学习率太高会出现 loss 震荡。yolo detect train \ datadrone.yaml \ modelruns/detect/train/weights/best.pt \ epochs30 \ imgsz1280 \ batch4 \ lr00.001 \ mosaic0.5有人会直接把imgsz拉到 1536但收益会递减且显存占用急剧上升。无人机识别更需要的其实是保持目标宽高比不变因为无人机形状比较固定过度拉伸输入没有任何好处。5.3 用混淆矩阵判断下一步优化方向训练结束后在runs/detect/train/目录下会生成confusion_matrix.png。对于单类检测器只看两类真实正样本被分成背景的比例和背景被分成无人机的比例。如果后者偏高说明你采样的负样本不够有代表性比如训练集里没有云层、电线这类容易误判的背景。这时可以额外收集一些背景图加入训练集并给它们生成空标签。空标签文件是一个 0 字节的 txt。YOLO 允许图片没有标注训练时该图只会提取背景特征不会参与目标损失计算。补充背景后模型对误检区域的抑制能力会明显提升。最后再提一个验证技巧用导出为 ONNX 或 TensorRT 的模型做批量推理时要注意模型预处理的归一化方式。YOLOv8 默认除以 255但 ONNX 模型可能保留像素值 0~255直接推理会导致置信度全部变成 1。检查方法是输入一张纯黑图看输出框是否有异常或者用model.predict(..., verboseTrue)观察预处理参数。先跑通单张再上批量能省掉不少排障时间。本文还有配套的精品资源点击获取