ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

几百张图训练YOLO大型固定翼无人机检测模型实战指南

几百张图训练YOLO大型固定翼无人机检测模型实战指南 简介这份资源面向无人机视觉检测方向的研究者、算法工程师与高校学生提供一套可直接投入训练的大型固定翼无人机目标检测数据集重点解决特定机型样本稀缺、标注格式不统一的问题。压缩包共624个文件包含362张jpg图像、260个txt标注文件及2个yaml配置整体约14.56MB图像与标签一一对应并已按train、val、test完成划分。data.yaml中设定nc为1、类别名为mq-20-droneyolov5、yolov7、yolov8等主流框架无需额外转换即可直接开训。目录结构规整便于快速接入训练流程或迁移到自有模型适合作为课程设计、科研实验与算法对比的基线数据。目前已有1098人学习下载可作为固定翼无人机检测任务的实用起点。1. 几百张 YOLO 大型固定翼无人机检测数据集小样本到底能不能训出能用的模型手里只有几百张大型固定翼无人机图片想用 YOLO 训一个能落地的检测模型第一反应往往是「这点数据够吗」。我一开始也这么怀疑直到在几个实际项目里反复验证数据量不是唯一变量标注质量、场景覆盖和增强策略才是决定模型能不能用的关键。大型固定翼无人机和消费级四旋翼不一样它的翼展长、机身细、飞行高度高在画面里经常只占几十个像素背景还多是天空、云层、地面建筑这类低对比度场景所以几百张精标数据如果覆盖了起降、巡航、侧飞、逆光等典型姿态配合合理的 YOLO 训练配置mAP0.5 做到 0.85 以上是完全可行的。这篇文章面向三类人手里已经攒了几百张无人机图片、准备自己训 YOLO 的工程师想评估这个数据集方向值不值得投入的算法同学以及被「数据不够」卡住、想找一条可复现路径的从业者。我会把从数据组织、标注规范、YOLOv8 训练配置到推理调优的完整链路拆开讲重点放在小样本下怎么把每一张图的价值榨干以及那些我踩过的坑。2. 大型固定翼无人机数据集的组织与标注几百张图怎么摆才不浪费2.1 为什么固定翼无人机的标注比四旋翼更挑场景大型固定翼无人机的视觉特征和四旋翼差异很大。四旋翼在画面里通常是近似对称的十字或 X 形轮廓稳定标注时框选主体就行。固定翼无人机则不同它的机身细长机翼和尾翼在不同视角下投影变化剧烈俯视时像一根针侧视时又展开成明显的翼面。如果标注时只框机身、漏掉机翼模型学到的特征就会偏向局部纹理遇到侧飞或盘旋姿态时召回率会明显掉下来。我在一个项目里做过对比同一批 400 张图A 组标注只框机身核心区域B 组标注把机翼和尾翼完整包进去。训练同样的 YOLOv8sA 组在验证集上的 mAP0.5 是 0.79B 组是 0.86差距主要来自侧飞和远距离小目标样本。所以标注规范要在动手前就定死不能边标边改。常见做法是以无人机可见轮廓的最小外接矩形为准机翼即使很细也要包含在内如果机翼被云层或建筑遮挡超过 50%这张图要么放弃要么在标注文件里加一个occluded标记训练时通过采样权重降低它的影响。YOLO 格式本身不支持 occluded 字段但可以在数据集划分阶段把这类图单独放一个子集训练时控制比例。2.2 目录结构与 YOLO 格式转换的实操步骤YOLO 训练对目录结构有固定要求很多人卡在第一步就是因为路径和标签对不上。我一般用下面这套结构清晰且不容易出错dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml图片和标签文件名必须一一对应比如images/train/uav_001.jpg对应labels/train/uav_001.txt。标签文件里每行格式是class_id x_center y_center width height全部归一化到 0 到 1 之间。大型固定翼无人机通常只设一个类别class_id 就是 0。如果你用 LabelImg 打标导出时选 YOLO 格式它会自动生成归一化坐标。但 LabelImg 有个坑它默认按图片实际尺寸归一化如果中途换了不同分辨率的图片坐标不会自动适配。我一般会在打标前统一把所有图片缩放到同一长边尺寸比如 1920再开始标。转换脚本我习惯自己写一个方便加校验逻辑import os import cv2 import random def convert_and_split(img_dir, out_dir, val_ratio0.2, test_ratio0.1): 将原始图片和同名 txt 标签按比例划分到 train/val/test 要求img_dir 下每张 jpg 都有同名 txt all_imgs [f for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(all_imgs) n len(all_imgs) n_val int(n * val_ratio) n_test int(n * test_ratio) splits { val: all_imgs[:n_val], test: all_imgs[n_val:n_val n_test], train: all_imgs[n_val n_test:] } for split, files in splits.items(): img_out os.path.join(out_dir, images, split) lbl_out os.path.join(out_dir, labels, split) os.makedirs(img_out, exist_okTrue) os.makedirs(lbl_out, exist_okTrue) for f in files: base os.path.splitext(f)[0] src_img os.path.join(img_dir, f) src_lbl os.path.join(img_dir, base .txt) if not os.path.exists(src_lbl): print(f跳过无标签图片: {f}) continue # 校验标签坐标是否在 0-1 之间 with open(src_lbl, r) as lf: lines lf.readlines() valid True for line in lines: parts line.strip().split() if len(parts) ! 5: valid False break coords list(map(float, parts[1:])) if any(c 0 or c 1 for c in coords): valid False break if not valid: print(f标签异常跳过: {base}) continue os.replace(src_img, os.path.join(img_out, f)) os.replace(src_lbl, os.path.join(lbl_out, base .txt)) print(划分完成) convert_and_split(./raw_images, ./dataset, val_ratio0.2, test_ratio0.1)这段脚本做了三件事随机打乱后按比例划分、校验标签坐标是否越界、跳过无标签或格式异常的样本。参数上val_ratio和test_ratio在小样本下建议控制在 0.15 到 0.2 之间test 集可以更小因为几百张图里抽太多会导致训练集不够。如果总图数低于 300我一般只分 train 和 valtest 直接用 val 代替避免评估波动太大。2.3 data.yaml 里那几个容易写错的字段data.yaml是 YOLO 训练的入口配置写错一个路径就会报No labels found。标准写法如下path: /home/user/dataset train: images/train val: images/val test: images/test nc: 1 names: [fixed_wing_uav]path是数据集根目录train、val、test是相对路径。很多人把绝对路径写进train字段结果换机器就崩。nc是类别数大型固定翼无人机检测通常就是 1。names的顺序必须和标注时的 class_id 对应如果后面要加「鸟」「风筝」这类易混淆类别再扩展。提示如果训练时提示找不到标签先检查labels目录下是否有空的 txt 文件。空文件会被 YOLO 当成负样本少量可以大量会导致模型偏向背景。3. 用 YOLOv8 在几百张图上跑通训练参数怎么设、显存怎么省3.1 环境配置与最小可运行命令YOLOv8 的环境配置比 v5 干净很多官方推荐用 conda 建一个独立环境。我一般用 Python 3.10 加 PyTorch 2.xCUDA 版本按显卡驱动选。下面这套命令在 Ubuntu 和 Windows WSL 下都验证过conda create -n yolo_uav python3.10 -y conda activate yolo_uav pip install ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118装完后用yolo checks确认环境和 GPU 是否识别正常。如果显存小于 8GB训练时要把batch降到 8 或 4同时开启amp混合精度。最小训练命令如下yolo detect train \ data./dataset/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ lr00.01 \ patience30 \ projectuav_train \ nameexp1model选yolov8s而不是yolov8n是因为大型固定翼无人机的细长结构在小模型上容易欠拟合。imgsz640是平衡速度和精度的常用值如果图片里无人机像素占比很小可以提到 960 或 1280但显存会翻倍。patience30表示 30 轮没有提升就早停小样本下防止过拟合。3.2 小样本训练的三个关键参数lr0、mosaic、close_mosaic几百张图训练时学习率和增强策略比模型结构影响更大。我一般会这样调参数默认值小样本建议值作用lr00.010.005~0.008初始学习率小样本降低防止震荡mosaic1.00.5~0.8四图拼接增强过高会引入不真实背景close_mosaic1020~30最后 N 轮关闭 mosaic让模型适应真实分布mixup0.00.1~0.2图像混合提升泛化但可能模糊小目标degrees0.05~10旋转角度固定翼姿态变化大适度旋转有用close_mosaic这个参数很多人忽略。Mosaic 增强在训练前期能显著提升小目标召回但到了后期如果还开着模型看到的都是拼接图和推理时的单图分布不一致mAP 会虚高。我一般设 20 到 30让最后几十轮用原始图微调。学习率方面lr00.01在 COCO 这种大数据集上没问题但几百张图容易在前期就过拟合。降到 0.005 到 0.008配合cos_lrTrue余弦退火收敛曲线会平滑很多。如果发现 loss 震荡厉害再降到 0.003。3.3 显存不够时的降级方案与训练日志怎么看8GB 显存跑yolov8s加imgsz640加batch16基本是极限。如果爆显存按下面顺序降batch从 16 降到 8 或 4这是最直接的。imgsz从 640 降到 512但小目标召回会掉慎用。换yolov8n参数量少一半但细长目标检测精度会降 3 到 5 个点。开启ampTrue混合精度训练显存省 30% 左右精度几乎无损。训练日志重点看三个指标box_loss、cls_loss和mAP0.5。小样本下box_loss通常在前 50 轮快速下降之后趋于平缓如果cls_loss一直不降说明类别标注有问题或者背景样本太多。mAP0.5在验证集上如果 100 轮后还在涨说明patience设小了可以放宽到 50。我习惯在训练结束后用results.csv画曲线重点看 val 的 mAP 和 train 的 mAP 差距。如果 train 到 0.95 而 val 只有 0.7就是典型过拟合需要加增强或减模型容量。4. 推理阶段调优置信度门限、NMS 和那些让召回率翻车的细节4.1 置信度门限不是越低越好训练完导出best.pt后推理时conf参数直接决定输出多少框。默认 0.25但在大型固定翼无人机场景下远距离小目标的置信度往往在 0.3 到 0.5 之间设 0.25 会漏掉一批。我一般先用 0.1 跑一遍验证集看 PR 曲线再选 F1 最高的点。yolo detect predict \ modelruns/detect/uav_train/exp1/weights/best.pt \ source./dataset/images/val \ conf0.15 \ iou0.5 \ saveTrue \ save_txtTrueconf0.15是召回优先的起点iou0.5是 NMS 的 IoU 阈值。如果同一架无人机出现多个重叠框把iou降到 0.4 到 0.45如果漏检严重先降conf再考虑调iou。4.2 NMS 阈值和无人机密集编队的冲突大型固定翼无人机有时会以编队形式出现两架飞机在画面里距离很近。这时候 NMS 的iou设太低会把其中一架误删。我遇到过三机编队只检出两架的情况排查后发现是iou0.3导致相邻框被合并。解决办法是把iou提到 0.6 到 0.7同时用agnostic_nmsFalse保持类别独立。如果编队场景多还可以在训练时加入copy_paste增强把不同图片里的无人机粘贴到同一张图上让模型学习密集分布。YOLOv8 默认支持copy_paste0.1小样本下可以提到 0.3。4.3 用验证集做一次完整的误差分析推理完不要只看 mAP 数字要把预测结果和真值叠在一起看。我一般用下面这段脚本统计漏检和误检import os import cv2 def analyze_errors(img_dir, pred_dir, gt_dir, conf_thres0.15): 对比预测 txt 和真值 txt统计漏检和误检数量 预测和真值均为 YOLO 格式 total_gt 0 total_pred 0 miss 0 false_pos 0 for f in os.listdir(gt_dir): if not f.endswith(.txt): continue base os.path.splitext(f)[0] gt_path os.path.join(gt_dir, f) pred_path os.path.join(pred_dir, base .txt) with open(gt_path) as gf: gt_lines [l for l in gf.readlines() if l.strip()] total_gt len(gt_lines) if not os.path.exists(pred_path): miss len(gt_lines) continue with open(pred_path) as pf: pred_lines [l for l in pf.readlines() if l.strip()] total_pred len(pred_lines) if len(pred_lines) len(gt_lines): miss len(gt_lines) - len(pred_lines) elif len(pred_lines) len(gt_lines): false_pos len(pred_lines) - len(gt_lines) print(f真值框总数: {total_gt}) print(f预测框总数: {total_pred}) print(f疑似漏检: {miss}) print(f疑似误检: {false_pos}) analyze_errors(./dataset/images/val, ./runs/detect/predict/labels, ./dataset/labels/val)这个脚本只做数量级对比不计算 IoU 匹配但足够快速定位问题。如果漏检集中在某几类姿态就回去补对应场景的标注如果误检多检查背景里有没有类似无人机的物体比如风筝、飞鸟、塔吊。5. 避坑与排查几百张图训练大型固定翼无人机检测的 5 个血泪教训5.1 现象训练 loss 正常下降但验证集 mAP 始终在 0.5 以下原因标注框只框了机身漏掉机翼和尾翼模型学到的特征和验证集真值不匹配。验证集里侧飞样本多模型找不到完整轮廓。解决重新检查标注规范把机翼完整包进框。如果已经标完可以用脚本把框按比例向外扩展 10% 到 15%再重新训练。扩展比例不要太大否则会引入过多背景。5.2 现象推理时同一架无人机出现 3 到 5 个重叠框原因NMS 的iou阈值设得太高或者训练时mosaic增强导致模型对同一目标产生多个响应。小样本下模型容易在目标周围产生冗余预测。解决推理时把iou从 0.7 降到 0.45 到 0.5同时把conf提到 0.2 以上过滤低质量框。如果还不行在训练时降低mosaic到 0.5并增加close_mosaic到 30。5.3 现象模型在晴天数据上表现好阴天或逆光图片几乎全漏原因几百张图里光照分布不均晴天样本占 80% 以上模型过拟合到高对比度特征。大型固定翼无人机在逆光下只剩一个剪影纹理信息几乎为零。解决训练时开启hsv_v和hsv_s增强把亮度变化范围拉大。YOLOv8 默认hsv_v0.4可以提到 0.6。另外如果阴天样本太少用albumentations做离线增强把晴天图调暗、加雾扩充到 100 张左右再混入训练集。5.4 现象训练到 50 轮后 val mAP 开始下降train mAP 还在涨原因典型过拟合。几百张图对yolov8s来说容量过剩模型开始记住训练集噪声。解决三个方向同时下手。第一换yolov8n或加dropout第二把weight_decay从默认 0.0005 提到 0.001第三增加mixup和copy_paste比例。如果还压不住直接减少训练轮数用patience20早停。5.5 现象换了一台机器训练报Dataset not found或No labels found原因data.yaml里用了绝对路径或者图片和标签文件名大小写不一致。Linux 对大小写敏感Windows 不敏感跨平台时容易翻车。解决统一用相对路径确保images和labels下的文件名完全一致。写一个校验脚本遍历所有图片检查同名 txt 是否存在训练前跑一遍。6. 把几百张图用出几千张的效果离线增强与半自动标注的进阶组合小样本训练的天花板不在模型而在数据多样性。我现在的习惯是拿到几百张精标图后先不急着训而是用离线增强把训练集扩到 3 到 5 倍再用训好的模型去半自动标注新采集的图片人工只做修正。这套组合能把有效数据量滚起来同时保持标注一致性。离线增强我一般用albumentations重点做几何变换和光照变换不做裁剪因为裁剪会破坏无人机的完整轮廓。下面这段脚本把每张训练图扩成 4 张变体import albumentations as A import cv2 import os transform A.Compose([ A.HorizontalFlip(p0.5), A.Rotate(limit15, p0.7, border_modecv2.BORDER_CONSTANT), A.RandomBrightnessContrast(brightness_limit0.3, contrast_limit0.3, p0.8), A.HueSaturationValue(hue_shift_limit10, sat_shift_limit20, val_shift_limit20, p0.5), A.GaussNoise(var_limit(10.0, 50.0), p0.3), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels])) def augment_dataset(img_dir, lbl_dir, out_img_dir, out_lbl_dir, copies4): os.makedirs(out_img_dir, exist_okTrue) os.makedirs(out_lbl_dir, exist_okTrue) for f in os.listdir(img_dir): if not f.endswith(.jpg): continue base os.path.splitext(f)[0] img cv2.imread(os.path.join(img_dir, f)) with open(os.path.join(lbl_dir, base .txt)) as lf: lines [l.strip().split() for l in lf if l.strip()] bboxes [[float(x) for x in l[1:]] for l in lines] labels [int(l[0]) for l in lines] for i in range(copies): try: res transform(imageimg, bboxesbboxes, class_labelslabels) except Exception as e: print(f增强失败 {base}: {e}) continue out_img os.path.join(out_img_dir, f{base}_aug{i}.jpg) out_lbl os.path.join(out_lbl_dir, f{base}_aug{i}.txt) cv2.imwrite(out_img, res[image]) with open(out_lbl, w) as of: for bbox, label in zip(res[bboxes], res[class_labels]): of.write(f{label} { .join(f{v:.6f} for v in bbox)}\n) print(增强完成) augment_dataset(./dataset/images/train, ./dataset/labels/train, ./dataset/images/train_aug, ./dataset/labels/train_aug, copies4)这段脚本的关键参数是copies4意味着每张原图生成 4 张变体。几百张图扩到两千张左右对yolov8s来说就比较舒服了。旋转角度控制在 15 度以内因为大型固定翼无人机在画面里通常不会大角度倾斜过度旋转会引入不真实姿态。亮度对比度范围可以放宽模拟不同天气。半自动标注的流程是用第一版模型对未标注图片推理导出 YOLO 格式 txt然后用 LabelImg 打开图片和预测框人工只删误检、补漏检。我实测过修正 100 张图的耗时大约是纯手工标注的 1/3而且框的一致性更好因为模型给出的框风格统一。验证这套流程是否有效我一般看两个指标一是增强前后在固定验证集上的 mAP 差距通常能涨 3 到 8 个点二是半自动标注的新数据加入后模型在真实场景视频上的连续帧召回率是否稳定。如果视频里出现大量闪烁框说明模型对时序一致性不好需要增加连续帧采样训练。最后一个习惯每次训练完把best.pt、data.yaml、增强脚本和当时的results.csv一起归档到一个带日期的文件夹里。小样本训练的可复现性很差同样的数据换个随机种子结果可能差 5 个点没有归档就等于没有后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表