ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

几百张固定翼无人机检测数据集:YOLOv8小样本训练与避坑指南

几百张固定翼无人机检测数据集:YOLOv8小样本训练与避坑指南 简介这份资源面向无人机视觉检测方向的开发者与研究者提供一套可直接用于YOLO系列算法训练的大型固定翼无人机目标检测数据集标签类别为mq-20-drone适合开展单类目标检测的模型训练、算法对比与课程实验。压缩包共624个文件包含362张jpg图像、260个txt标注文件以及2个yaml配置文件整体约14.56MB图像与标签一一对应yaml文件用于声明类别数与类别名称。数据集已完成train、val、test划分目录结构配置齐全yolov5、yolov7、yolov8等主流框架无需额外整理即可直接投入训练。目前已有1098人学习下载配套博文提供了数据集与检测结果的参考展示便于读者快速判断数据分布与检测效果。对于需要快速搭建固定翼无人机检测基线、验证模型改进思路或补充实验数据的读者这份资源能省去数据采集与标注环节直接进入训练与调参阶段。1. 几百张固定翼无人机检测数据集小样本高价值场景的真实门槛固定翼无人机检测这个方向最近一年问的人明显变多了。原因不复杂机场净空区、电力巡线、边境巡查、大型活动安保都需要在远距离、小目标、复杂天空背景下把固定翼无人机从云层、飞鸟、塔吊里区分出来。但真正动手的人很快会撞上同一堵墙——公开数据集里固定翼样本少得可怜自己采几百张已经是极限而 YOLO 系列模型动辄要几千上万张才肯收敛。我手上这份「几百张固定翼无人机检测数据集」就是在这种背景下攒出来的。它不追求规模追求的是场景纯度固定翼、天空背景、多尺度、多光照标注框紧贴机身。它适合两类人一类是想验证 YOLO 在小样本下到底能不能用的算法工程师另一类是有实际巡检需求、准备自己补数据的落地团队。几百张不是终点而是起点——关键在于你怎么用它把模型推到可用线以上。2. 固定翼无人机数据集为什么难做从目标特性到标注口径2.1 固定翼与多旋翼在检测任务上的本质差异很多人把无人机检测当成一个统一任务这是第一个认知偏差。多旋翼在画面里通常是悬停或低速移动形态稳定、背景变化慢固定翼则是高速巡航姿态角变化剧烈俯仰、滚转、侧飞都会让轮廓在连续帧里完全不同。更麻烦的是尺度固定翼作业高度普遍在 100 米以上1080P 画面里目标可能只有 20×15 像素属于典型小目标检测。这带来两个直接后果。第一通用 COCO 预训练权重的迁移效果会打折因为 COCO 里几乎没有这种「天空背景 极小目标」的组合。第二数据增强不能照搬随机裁剪、马赛克增强在小目标上很容易把目标裁没或糊成一团。我一般会先把原图缩放到 1280 或 1536 长边再训练而不是默认 640这一步对召回率的影响比换模型结构还大。2.2 几百张数据集的标注口径与类别设计几百张的规模标注质量比数量重要得多。固定翼检测我建议只设一个类fixed_wing_uav。不要按机型、颜色、军民用去细分样本量撑不住类别一多每类只剩几十张模型直接学废。标注框要贴紧机身包括机翼和尾翼但不要框住尾迹或螺旋桨虚影。遇到目标被云层部分遮挡的情况按可见部分标注并在训练时把这类样本单独统计。下面是我整理标注时用的一个校验脚本用来快速筛掉异常框import os import cv2 # 校验 YOLO 格式标注类别 0坐标归一化宽高不能为 0 def check_labels(img_dir, lbl_dir, min_size4): bad [] for name in os.listdir(lbl_dir): if not name.endswith(.txt): continue img_path os.path.join(img_dir, name.replace(.txt, .jpg)) img cv2.imread(img_path) if img is None: bad.append((name, missing_image)) continue h, w img.shape[:2] with open(os.path.join(lbl_dir, name)) as f: for i, line in enumerate(f): cls, cx, cy, bw, bh map(float, line.split()) # 还原到像素尺度检查是否过小 pw, ph bw * w, bh * h if pw min_size or ph min_size: bad.append((name, fline{i}_too_small)) if not (0 cx 1 and 0 cy 1): bad.append((name, fline{i}_out_of_range)) return bad if __name__ __main__: issues check_labels(images, labels) for item in issues[:20]: print(item) print(total issues:, len(issues))这段脚本做三件事确认图片存在、把归一化坐标还原成像素、筛掉小于 4 像素的框。参数min_size按你的实际分辨率调1280 长边下我一般设 4 到 6。跑完如果异常比例超过 5%说明标注流程有问题先返工再谈训练。2.3 采集端要控制的四个变量几百张的预算下每一张都要有信息量。我采集时会刻意控制四个变量光照顺光、逆光、阴天、黄昏、背景纯天空、云层、远山、城市天际线、尺度远中近三档、姿态平飞、转弯、爬升。每个组合至少留 5 到 10 张这样几百张覆盖的工况比随机拍两千张还全。采集设备用 1080P 25 帧就够重点是焦距和稳定性长焦端抖动会让标注框漂移。3. 用 YOLOv8 在几百张固定翼数据上跑通训练3.1 环境与数据目录的最小配置训练环境我一般用 PyTorch Ultralytics 的组合显卡 8G 显存起步。数据目录按 YOLO 标准组织fixed_wing_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yamldata.yaml内容如下path: ./fixed_wing_dataset train: images/train val: images/val nc: 1 names: [fixed_wing_uav]划分比例我建议 8:2几百张的规模下验证集留 60 到 100 张。注意验证集要覆盖所有光照和背景组合不能随机切否则指标虚高。3.2 训练命令与关键参数怎么设启动训练的命令不复杂难的是参数。下面是我在几百张固定翼数据上验证过的一组配置yolo detect train \ modelyolov8s.pt \ datafixed_wing_dataset/data.yaml \ imgsz1280 \ epochs300 \ batch8 \ lr00.001 \ lrf0.01 \ warmup_epochs5 \ mosaic0.5 \ scale0.3 \ degrees10 \ patience50 \ projectruns/fixed_wing \ nameexp01逐个说imgsz1280是小目标召回的关键别省显存降到 640batch8是 8G 显存下的稳妥值显存够可以上 16lr00.001比默认的 0.01 小一个量级小样本下大学习率容易震荡mosaic0.5而不是默认的 1.0因为四图拼接会让本就小的目标更小degrees10给一点旋转增强模拟固定翼的姿态变化patience50配合 300 epoch让模型有足够时间收敛。3.3 训练过程要看哪几条曲线跑起来之后别只盯 mAP。我重点看三条train/box_loss是否平稳下降、metrics/mAP50-95是否在 150 epoch 后还在涨、val/box_loss有没有明显反弹。如果 val loss 在 100 epoch 左右开始上升而 train loss 继续降说明过拟合这时候要么加增强要么减模型容量。几百张数据上YOLOv8s 通常比 YOLOv8m 更稳别一上来就上大模型。4. 小样本固定翼检测的避坑与排查清单4.1 坑一mAP 看着高实际漏检严重现象验证集 mAP50 到 0.9但拿真实视频一跑远距离目标十有八九漏掉。原因验证集和训练集同分布且验证集里中近距离目标占比偏高模型学到了「大目标优先」的捷径。解决单独切一个「远距离子集」做评估把目标像素小于 32×32 的样本挑出来算召回。如果远距离召回低于 0.6回到 3.2 节把imgsz提到 1536并把mosaic降到 0.3。4.2 坑二把飞鸟标成了无人机现象模型在天空场景里对飞鸟频繁误报。原因标注时把形态相似的飞鸟框进了正样本或者负样本里根本没有飞鸟。解决专门收集 50 到 100 张纯飞鸟、无无人机的天空图作为背景负样本放进训练集标注为空 txt。这一步对降低误报率的效果立竿见影。4.3 坑三增强过猛导致目标消失现象训练中期 loss 突然飙升之后再也降不下来。原因mosaic1.0加上scale0.5的组合把 20 像素的目标缩到了 5 像素以下标注框还在但目标已经不可辨。解决小目标任务里scale不要超过 0.3mosaic控制在 0.5 以内。如果要用 MixUp先确认目标在混合后仍然清晰。4.4 坑四验证集指标波动大无法判断收敛现象相邻两个 epoch 的 mAP 差 0.1 以上。原因验证集只有几十张单张难例就能拉动整体指标。解决把验证集扩到 100 张以上或者用 K 折交叉验证。几百张数据下5 折是性价比最高的做法每折验证 60 到 80 张取平均指标。4.5 坑五导出部署后精度掉一截现象PyTorch 下 mAP 0.85转成 ONNX 或 TensorRT 后掉到 0.75。原因预处理不一致最常见的是 letterbox 的填充值和归一化顺序对不上。解决导出时固定imgsz推理端严格复现 Ultralytics 的 letterbox 逻辑填充值用 114。转 TensorRT 时先用 FP32 验证一遍确认无损再上 FP16。5. 把几百张用到极致半自动标注与主动学习闭环几百张的天花板很明显真正的出路是让数据自己长起来。我现在的做法是搭一个半自动闭环用当前模型对未标注视频抽帧推理把置信度在 0.3 到 0.6 之间的「模糊样本」挑出来人工复核确认后加入训练集。这批样本信息量最大往往几十张就能带来明显提升。具体操作上先用训练好的权重跑推理并保存 txtyolo detect predict \ modelruns/fixed_wing/exp01/weights/best.pt \ sourceunlabeled_frames/ \ conf0.25 \ save_txtTrue \ save_confTrue \ imgsz1280然后写个小脚本按置信度分桶把 0.3 到 0.6 的挑出来import os # 按置信度筛选待复核样本 def pick_hard_samples(txt_dir, low0.3, high0.6): hard [] for name in os.listdir(txt_dir): path os.path.join(txt_dir, name) with open(path) as f: lines f.readlines() if not lines: continue confs [float(l.split()[5]) for l in lines] avg sum(confs) / len(confs) if low avg high: hard.append(name) return hard if __name__ __main__: samples pick_hard_samples(runs/predict/labels) print(hard samples:, len(samples))参数low和high是经验值0.3 以下基本是误报0.6 以上模型已经很有把握中间这段才是真正值得花人力的。每轮复核 50 到 100 张迭代三到五轮几百张的底子能撑起一个在特定场景可用的检测器。有个习惯我保持了两年每次训练前先花十分钟看一眼验证集里最难的十张图确认标注没问题再启动。这个动作帮我省下的返工时间比任何调参技巧都多。数据集不在大在于你知不知道自己喂进去的每一张在教模型什么。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进