无人机视角飞机目标检测数据集实战:从检查到训练避坑指南

发布时间:2026/10/7 5:42:11
无人机视角飞机目标检测数据集实战:从检查到训练避坑指南 简介面向无人机视觉与高空目标检测场景的飞机目标检测数据集适用于航空器识别、机场空域监测、无人机交通管理以及小目标检测算法研究。压缩包共1054个文件包含526张jpg航拍图片、526个YOLO格式txt标注文件另附1个yaml文件与1个docx说明文档整体仅15.63MB。数据划分清晰训练集479张、验证集31张、测试集16张覆盖多种高度、角度、光照条件及云层、城市、旷野等不同背景单张图片最多标注20余个飞机实例适合密集目标检测训练。目前已有202人学习下载。资源即用性突出标注格式可直接适配YOLOv5/v7/v8等主流检测框架方便快速开展模型训练与效果验证对于需要高空视角小目标样本或密集标注数据的开发者和研究人员是一份轻量而实用的数据集。1. 无人机视角飞机目标检测数据集为什么通用检测模型会在这里集体失灵无人机视角飞机目标检测数据集听起来只是把普通飞机检测换成无人机拍摄但真正跑过一次就会发现在 COCO 上表现很好的通用检测模型放到无人机拍机场的画面里会漏检得厉害。原因很直接——无人机视角下的飞机往往只占几十个像素有俯冲、盘旋、停靠各种姿态跑道、车辆和建筑还在不停干扰。专门整理这类数据集意义就在于让目标检测模型适应这种远距离、小尺度、背景杂乱的真实分布。它适合做机场智慧巡检、低空安防、无人机航测复核的人。这里从拿到包开始重点聊检查、训练、避坑和验证。2. 数据集的真实构成从目录结构到标注格式的拆解拿到一个无人机视角飞机目标检测数据集.zip最忌讳的事是解压后直接丢进训练脚本。多数包内部其实是两种形态之一已经转好的 YOLO 格式images/与labels/同名 txt或者给你 VOC/COCO 原始标注xml/json。先花十分钟把目录和标注格式摸清楚能省后面两三个小时的排错。2.1 先跑一遍配对检查图片和标签缺一不可解压后第一步是用命令看目录再用脚本统计配对。这是每个数据集我都必跑的检查先摸清目录层级再确认图片与标注文件是否一一对应。unzip -q 无人机视角飞机目标检测数据集.zip -d aircraft_dataset find aircraft_dataset -maxdepth 2 -type d | sort如果解压后出现images和labels两个目录继续往下走如果每个样本是单独文件夹优先用find看层级。配对统计用 Pythonfrom pathlib import Path dataset Path(aircraft_dataset) images list(dataset.rglob(*.jpg)) list(dataset.rglob(*.png)) labels list(dataset.rglob(*.txt)) img_names {p.stem for p in images} lab_names {p.stem for p in labels} print(图片数:, len(img_names), 标签数:, len(lab_names)) print(有图无标签:, len(img_names - lab_names)) print(有标签无图:, len(lab_names - img_names))统计用的stem是去掉后缀后的文件名这样一张DJI_0001.jpg能对应DJI_0001.txt。labels只匹配 txt适合 YOLO 格式如果包内是 VOC/COCOtxt 为 0 是正常的需要用别的脚本检查 xml/json。配对检查的意义在于YOLO 训练时图片缺标签会静默丢样本标签缺图片则可能报错或产生空标签文件这两种情况都不报错但会让验证 mAP 悄悄失真。这里发现数量对不上优先回到数据分割来源找原因不要急着训练。2.2 三种标注格式对比YOLO 的 txt 为什么最省事不同数据集会按不同习惯整理标注最常遇到三种格式文件形式坐标表示典型工具是否适合直接训练YOLO每张图一个 .txt类别 id 归一化中心 (x, y, w, h)Ultralytics YOLO最省事VOC每张图一个 .xml像素左上/右下 (xmin, ymin, xmax, ymax)mmdetection、detectron2需转换COCO单个 annotations.json像素左上角 (x, y, w, h) mask学术实验、mmdetection需转换大多数无人机视角飞机检测数据集以 YOLO 或 VOC 形式发布。如果拿到的是 VOC我一般会先用脚本转成 YOLO 格式再开始训练。转换脚本的关键部分如下import xml.etree.ElementTree as ET from pathlib import Path xml_dir Path(annotations) out_dir Path(labels) out_dir.mkdir(exist_okTrue) class_map {airplane: 0, helicopter: 1} # 按实际类别调整 for xml_file in xml_dir.glob(*.xml): tree ET.parse(xml_file) root tree.getroot() size root.find(size) img_w, img_h float(size.find(width).text), float(size.find(height).text) lines [] for obj in root.iter(object): cls obj.find(name).text if cls not in class_map: continue box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) x (x1 x2) / 2.0 / img_w y (y1 y2) / 2.0 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{class_map[cls]} {x:.5f} {y:.5f} {w:.5f} {h:.5f}) out_path out_dir / (xml_file.stem .txt) if lines: out_path.write_text(\n.join(lines))这段脚本的核心是坐标归一化VOC 给的是像素坐标YOLO 给的是相对原图的比例。转换时重点检查两处第一class_map是否覆盖数据集内全部类别否则漏类会静默消失第二确保x2-x1和y2-y1为正很多标注软件导出时会把左上右下写反。脚本跑完别急着训练抽两张图把预测框画出来叠在原图上看看确认坐标正反再继续走。2.3 先看类别平衡再看目标尺度这决定训练分辨率数据集里每类有多少框、框在图片里一般多大这些信息比类别名还有用。用 Python 统计 YOLO 标签import numpy as np from glob import glob box_w, box_h [], [] for txt in glob(labels/**/*.txt, recursiveTrue): for line in open(txt): parts line.strip().split() if len(parts) ! 5: continue box_w.append(float(parts[3])) box_h.append(float(parts[4])) box_w np.array(box_w) box_h np.array(box_h) print(框宽占比 中位/90分位: {:.4f}/{:.4f}.format( np.median(box_w), np.percentile(box_w, 90))) print(框高占比 中位/90分位: {:.4f}/{:.4f}.format( np.median(box_h), np.percentile(box_h, 90)))如果中位数低于 0.03也就是目标宽度不足原图 3%按 1080p 算只有 30 像素左右属于典型的移动小目标检测场景。这时训练分辨率别再用 640优先用 1280 甚至原图直接训练。类别平衡则决定要不要做重采样如果airplane有 1 万框而某个稀有类别只有 50 框那后者在训练里会被淹没我一般会为稀有类别做复制增强或给大类降采样。遥感领域里常用 HRSC2016 做舰船检测但那是水平大目标分布无人机视角更接近移动小目标检测别把普通数据集的缩放策略照搬过来。统计脚本遇到空标签文件会在np.median上报错这正好提醒你先按第 5 章的清洗脚本把空标签清理或归类。3. 用 YOLO 训练飞机检测从解压到出模型的最小命令序列数据集检查完下一步是让训练跑起来。我习惯用 Ultralytics YOLO 系列v8、v11 共用同一套yolo命令环境配置和数据集 yaml 不用改。这节按“环境→数据划分→训练参数”三步走每一步都可以直接抄。3.1 环境配置v8/v11 共用的 Ultralytics 训练命令“目标检测yolov11(ultralytics) 环境配置”是很多人卡住的地方其实化成命令就三条conda create -n uav_aircraft python3.10 -y conda activate uav_aircraft pip install ultralyticsPyTorch 建议单独装。如果机器已有可用的 CUDA用 PyTorch 官方加速安装方式先装带 CUDA 的版本回头再装 ultralytics可以避免 ultralytics 装出一个只用 CPU 跑的 torch。装完后跑python -c import torch; print(torch.cuda.is_available())输出 True 再往下走。这里不写死版本号因为 Ultralytics 的 v8 和 v11 在检测任务上的命令几乎一致跑通训练后再考虑要不要升级。3.2 数据划分与 dataset.yaml让训练器认识你的目录数据集目录通常是images与labels同级。先把它们按约定拆成 train/val 两个子集。为了复现稳定我不用随机 seed而用文件名哈希划分import hashlib, shutil from pathlib import Path images Path(images) labels Path(labels) img_train Path(images/train); img_val Path(images/val) lbl_train Path(labels/train); lbl_val Path(labels/val) for img_dir, lbl_dir in [(img_train, lbl_train), (img_val, lbl_val)]: img_dir.mkdir(parentsTrue, exist_okTrue) lbl_dir.mkdir(parentsTrue, exist_okTrue) for img in list(images.glob(*.jpg)) list(images.glob(*.png)): lbl labels / (img.stem .txt) if not lbl.exists(): print(缺少标签:, img.name) continue h hashlib.md5(img.stem.encode()).hexdigest()[0] dest_img img_train if h 8 else img_val dest_lbl lbl_train if h 8 else lbl_val shutil.copy(img, dest_img) shutil.copy(lbl, dest_lbl)哈希划分的优点是只要文件名不变每次划分结果完全一致训练、复现、回头再查都方便。缺点在于它不能按视频片段隔离如果你知道哪些帧来自同一段视频优先用第 5 章的视频ID分组方案。写完划分脚本后在数据集根目录创建aircraft.yamlpath: /绝对路径/aircraft_dataset train: images/train val: images/val names: 0: airplane 1: helicopter如果数据集中只有一类飞机names只写一行。Ultralytics 优先读 yaml 里的 names不会去看 labels 里的 names 或 classes.txt所以这是唯一直接影响训练类别数的文件。写错类别数最常见的报错是“标签类别超过 names 长度”遇到就回这里查。3.3 训练命令与关键参数imgsz、batch、epochs、workers 怎么给最小训练命令长这样cd aircraft_dataset yolo taskdetect modetrain modelyolov8s.pt \ dataaircraft.yaml \ imgsz1280 batch16 epochs100 workers8 \ patience20 save_period10几个参数按项目调整imgsz1280对无人机飞机目标检测几乎是必选项。前面统计过尺度占比之后如果小目标多用 640 会把飞机缩成 5-8 像素模型根本学不到特征。显存不够时先保 imgsz把 batch 降到 8 或 4。batch16是 24G 显存左右的经验值OOM 表现是训练中断把 batch 和 imgsz 任选一个降下来即可。epochs100对几千张图片的数据级够用数据量小可以降到 60但别低于 50数据集很大可以跑到 200配合patience20早停。workers8是 Linux 常规值Windows 上建议改成 4 或 2否则经常遇到 dataloader 报错。如果想用 YOLOv11把modelyolov8s.pt换成modelyolo11s.pt其他参数位置不变。训练中断后用yolo resume可以继续训练。训练完成后会自动执行验证流程runs/detect/train/weights/best.pt是验证集上指标最好的权重除非你明确想用最后一次续跑结果否则部署和落地一律用best.pt。4. 无人机视角飞机检测的 5 个经典翻车点现象、原因与排查清单这一章是血泪经验集中地。无人机视角和普通行车记录仪视野有一个本质区别相机离目标远、角度高、目标小造成很多在常规目标检测里不是问题的问题。如果你训练时发现 loss 一路下降但验证效果很差或者推理视频时出现诡异误检按下面几个点逐一排查大多数情况能在半天内定位。4.1 漏检率高小目标被 imgsz640 抹掉了现象训练曲线正常但推理时距离稍远的飞机全部漏检验证集 recall 也很低。原因无人机视角下很多飞机的标注框占原图不到 3%而默认imgsz640会把原图缩到一半或更小目标变成只有十几个像素。网络下采样后目标特征直接消失。解决把训练和推理的 imgsz 提到 1280如果显卡不够先减小 batch推理端同样用imgsz1280不要只改训练不改验证。另一个常用做法是切片推理SAHI把大图切成 640 或 960 的子图让模型在子图尺度上检测后再拼回结果。yolo predict modelbest.pt sourcetest.jpg imgsz1280 conf0.25这条命令里的conf0.25先按默认走具体阈值看 4.6 的调法。4.2 斜着停的飞机框不准水平框的固有限制现象机头朝前的检测还可以但跑道上斜停的飞机预测框和真值 IOU 很低看起来框多了一大块背景。原因VOC/YOLO 默认用轴对齐水平框只能表达矩形区域不能表达朝向。斜停的飞机水平框自然的包含大量地面背景训练时模型学到的是“一个横向拉长的框”不能区分机头方向。解决如果数据集准备长期用先检查原始标注里有没有角度向量。如果原始标注是polygon或rotated_rect但转成 YOLO 时把角度丢了可以用 mmrotate 或 Ultralytics 的 OBB 模式把框定义成(cx, cy, w, h, angle)。如果原始只有水平框就不要硬上旋转框模型而是把评估指标从严格 IOU 放宽成中心点命中率预测框中心落入真值框内即算命中这种评估方式对地勤场景更实际。4.3 训练集和验证集永远是亲戚mAP 虚高现象训练时验证 mAP 到了 0.9但拿着模型去测一段全新无人机视频漏检和误检非常严重和验证结果完全不符。原因很多人把连续视频转帧后随机划分 train/val相邻帧画面一样模型在验证时看见的其实是“训练集邻居”。模型记忆背景纹理就能拿高分没有真正学习飞机特征。解决按视频片段划分数据。从文件名里抽出视频 ID比如DJI_20240101_001_001.jpg取前三个字段保证同一个视频的所有帧只出现在 train 或只出现在 val。第 5 章会给一个按视频前缀划分的脚本。如果数据集的文档没说怎么分至少要把“连续编号连续帧”的先挑出来放验证集再随机补全。4.4 误检一堆机场车辆和建筑模型把特征学成了轮廓现象验证集 precision 低输出结果里经常出现机场大巴、塔台、地面标志线被框成飞机。原因飞机在俯视画面中的特征是矩形轮廓和纹理而地面车辆、建筑也有类似边缘结构。如果训练负样本不足模型用一个粗轮廓区分正负类自然会把大型轮廓当作飞机。解决收集一批不含飞机的无人机机场场景图做负样本放到 train 目录里给空标签文件或者作为背景图像。在训练时把scale和translate增强打开让模型见过飞机在不同尺寸和位置的情况弱化对固定位置的依赖。如果误检还是集中在车辆可以在后处理逻辑中按目标长宽比过滤比如飞机宽度与高度比例通常不会超过 3长条目标直接丢弃。4.5 白天训练完逆光傍晚视频全挂现象白天验证效果很好一到傍晚或逆光场景recall 直接掉一半。通常数据集拍摄时段集中在上午 9 点到下午 3 点。原因无人机视角的光照变化比地面更大。太阳位置低时飞机背光面与地面颜色接近模型没有见过这种光照目标边缘特征大幅减弱。解决在训练增强里加入光照扰动命令行末尾追加yolo taskdetect modetrain modelyolov8s.pt dataaircraft.yaml \ imgsz1280 batch16 epochs100 workers8 \ hsv_h0.015 hsv_s0.4 hsv_v0.4hsv_v调高一点相当于模拟不同亮度hsv_s模拟色彩饱和度下降。也可以在数据集里补 5%~10% 的阴天、黄昏、逆光样本不要只依赖增强。如果项目上线时段明确是清晨傍晚建议训练时就用混合光照而不是等模型上线后才发现没覆盖。4.6 排查顺序先看失败图再跑 PR 曲线遇到验证分数和直觉不符我一般按“先数据后模型”的顺序排查第一确认 train/val 没有视频帧串4.3第二在验证集上用best.pt跑一次把置信度在 0.3 以下但仍命中的框、以及置信度高于 0.9 却框错的目标导出来看图第三按 4.1~4.5 归类现象。看失败图这一步最花时间但最值得它往往比调一次学习率更能说明问题。如果你换一套数据后指标崩了优先怀疑 4.2 和 4.3而不是模型结构。5. 数据清洗与增强把样本少、框不准的短板补上无人机视角数据集不像 COCO 那样经过严格清洗尤其从视频转帧的包常常带着越界框、空标签和因抖动产生的错误标注。这些脏数据不清理训练再久都在不干净的地基上跑。我习惯在每次训练前做一遍自动筛查再决定增强策略。5.1 自动筛查标注异常越界、空标签、类别错配写一个能扫全量标签的脚本放在数据集根目录直接跑。假设标签是 YOLO 格式from pathlib import Path for label_dir in [Path(labels/train), Path(labels/val)]: if not label_dir.exists(): continue for txt in sorted(label_dir.glob(*.txt)): lines txt.read_text().strip().splitlines() if not lines: print(f空标签: {txt}) continue for idx, line in enumerate(lines): parts line.split() if len(parts) ! 5: print(f列数错误 {txt} 第{idx1}行: {line}) continue cls int(parts[0]) cx, cy, w, h map(float, parts[1:]) if w 0 or h 0: print(f尺寸异常 {txt} 第{idx1}行: {line}) if cx - w/2 0 or cx w/2 1 or cy - h/2 0 or cy h/2 1: print(f越界 {txt} 第{idx1}行: {line})这段脚本只做告警不做自动删除。越界框可能是标注时手动加了外扩直接删会丢目标正确做法是先看告警数量。如果只有几十个手工检查如果有几百个多半是标注工具导出时坐标系写错回头检查 VOC 转 YOLO 脚本的系数。空标签对应的图片如果是纯地面背景建议保留作为负样本如果是漏标需要补标。一张图完全没有飞机但带空标签文件在 YOLO 训练里是合法负样本我一般不会删。5.2 按视频片段划分数据避免相邻帧串组4.3 提过的问题这里直接给脚本。假设文件名风格是DJI_20240101_001_001.jpg前三个字段代表“机型日期片段号”from collections import defaultdict from pathlib import Path img_dir Path(images) groups defaultdict(list) for img in list(img_dir.glob(*.jpg)) list(img_dir.glob(*.png)): prefix _.join(img.stem.split(_)[:3]) # DJI_20240101_001 groups[prefix].append(img) items sorted(groups.items()) cut int(len(items) * 0.8) train_groups {k for k, _ in items[:cut]} val_groups {k for k, _ in items[cut:]} print(片段数:, len(items), 训练片段:, len(train_groups), 验证片段:, len(val_groups))得到片段前缀后把每张图连同标签按前缀搬进 train/val 目录即可。关键点在于哪怕有些片段只有几十帧也要整段划分而不是把片段内部分帧放训练、部分留验证。因为无人机视频相邻帧之间目标位置变化很小模型只要记住上一帧就赢了。如果文件名没有统一前缀可以按帧的秒数或者拍摄时间戳聚类如果都没有只能用第 3 章的 MD5 哈希划分但不要指望它消除视频帧泄漏。5.3 增强策略不是所有增强都适合小目标Ultralytics 的增强默认在超参里已有基础值但针对无人机小目标几个参数值得单独调。常见做法是训练命令覆盖yolo taskdetect modetrain modelyolov8s.pt dataaircraft.yaml \ imgsz1280 batch16 epochs100 workers8 \ mosaic0.6 hsv_v0.3 flipud0.2 scale0.5 translate0.1参数说明mosaic0.6对中大型目标明显但对小于 20 像素的目标拼接后可能被裁剪掉一半。如果目标是极小建议把 mosaic 降到 0.5 或 0.6给模型看到完整小目标的机会更多。flipud0.2允许上下翻转对无人机视角有意义同一架飞机在画面上可能机头朝上或朝下翻转可以模拟不同航向。但如果你数据里飞机带阴影上下翻转后阴影方向改变需要观察是否引入混淆。hsv_v0.3模拟不同亮度是应对 4.5 逆光问题的关键。scale0.5让目标缩放范围更大防止模型只见过固定尺寸的飞机。除了这些内置增强如果样本量特别小可以试试复制粘贴增强把不同图片中的飞机实例抠出来以随机位置贴到背景图上同时自动生成 YOLO 标签。这对无人机俯视图效果好因为飞机实例相对独立、旋转角度自由但要注意不要贴到不可能出现飞机的位置。复制粘贴增强的关键在于保证贴图后阴影和光照协调否则模型的泛化收益会被伪影抵消。6. 用最佳置信度和失败样本判定模型能否上线一个交付前检查习惯真正决定这个数据集值不值得被你留下继续投入的不是训练 loss 也不是验证 mAP而是验证集上的 PR 曲线和失败样本分布。训练结束后我会先不看 mAP而是做两件事第一找出 F1 最大时对应的置信度阈值第二把所有“置信度高但预测错”的样本拼成一张大图扫一遍。Ultralytics 训练结束后会在runs/detect/train/留下results.csv和val_batch_pred.jpg。部署之前我会把验证集上每个置信度阈值下的 precision 和 recall 拉出来找到最佳 F1。更关键的是观察不同阈值下 recall 的突变点如果置信度从 0.1 提到 0.3recall 掉了 10%说明大量漏检来自模型本身没有自信而不是阈值挑剔这时加增强或调数据权重比调阈值有效。如果 PR 曲线在高置信度区间的回退很陡则说明模型对某些样本过于自信需要重点看失败图。真正让我养成这个习惯的是一次翻车那时项目时间紧验证集 mAP 0.93我直接按 0.5 置信度上线结果傍晚逆光视频几乎全漏。后来排查发现验证集是白天拍的PR 曲线在低置信度区间一路平坦我根本没意识到模型在低光照下完全没有信心。从那以后每次交付前我都会跑一遍失败样本图并顺手把验证集按“光照/背景/目标大小”分层各抽样 100 张分别看准确率。这一步比多训练 20 轮更值。希望这个例子能帮你在拿到无人机视角飞机目标检测数据集后少走一次“mAP 漂亮但现场翻车”的路。本文还有配套的精品资源点击获取