无人机目标检测数据集:YOLO/VOC/COCO标签与训练实战 简介面向无人机视觉应用开发者与目标检测初学者YOLO无人机目标检测数据集提供5000张真实场景航拍图片标注框质量较高并同步整理VOCxml、COCOjson、YOLOtxt三种标签格式可直接接入YOLO系列模型训练。压缩包内共2000个文件以xml标签文件为主体另有Python脚本、说明文档及txt索引文件整体301.59MB结构清晰便于查找。包内附带数据集划分脚本支持一键生成训练集、验证集与测试集并自动写入对应文件夹同时提供Linux与Windows双平台的YOLO环境搭建和训练教程涵盖从环境配置、数据准备到修改案例训练自有数据集的关键环节附有常见问题说明便于跟随操作。已有433人浏览学习适合需要进行无人机目标检测实践、课程设计或算法对比的开发者既能获得标准数据也能参照完整训练流程快速产出结果。1. 无人机目标检测的第一步从来不是模型而是数据YOLO无人机目标检测数据集这份资源里5000张真实场景无人机视角图片已经按VOC(xml)、COCO(json)、YOLO(txt)三种格式做好了标签省掉的是标图、格式互转、划分脚本三道最磨人的流程。实际做检测项目的人都清楚无人机目标往往只占画面几十个像素手工标注一张小目标图片就要一分钟以上框稍微偏一点后续训练直接受影响。这份资源把场景覆盖和标注质量都做到了可以直接开工的程度适合正在做目标检测算法研究、无人机视觉毕设以及想迁移到自家场景微调YOLO模型的工程人员。下面按标签格式、划分脚本、环境搭建到避坑排查的顺序把包里的东西逐个拆开讲。2. 三种标签格式与划分脚本VOC、COCO、YOLO的坐标差异其实很要命先说把三种格式放在一个包里的价值。第一次做检测的人会觉得“随便转一下就行反正模型只看txt”。实际不是这样。VOC的xml是绝对像素坐标的左上右下COCO的json是绝对像素坐标的左上宽高YOLO的txt是宽高归一化后的中心点坐标三者差异不只是文件格式还有坐标基准与归一化方式。自己写转换脚本时最容易翻车的地方是类别顺序、目标越界和浮点精度。包已经分文件夹存好三种格式省掉的恰恰是这段血泪经验。2.1 三种标签格式的核心差异先看一张表把最容易搞混的三处标出来格式文件后缀坐标形式典型字段单位VOC.xmlxmin, ymin, xmax, ymaxbndbox下的四个坐标像素绝对坐标COCO.jsonx, y, width, heightannotations 下的 bbox 字段像素绝对坐标YOLO.txtclass x_center y_center width height每行五个浮点数归一化除以图片宽高VOC 和 COCO 虽然都是像素坐标但一个用对角点一个用“左上角 宽高”。YOLO 的 txt 则要再除以图片宽高把它转成 0~1 之间的相对值。真正容易出错的不是坐标换算本身而是下面三件事。第一类别 ID 的顺序对齐。COCO 的 categories 数组顺序必须和 YOLO 的 class 编号一致VOC 的name是字符串转换时要先建一张“类名→ID”的映射表。顺序一旦乱了模型学到的就是一个串位的类别。第二目标边缘溢出。无人机数据集里目标经常贴边甚至飞到画面外一半标注框的 xmax 可能等于或超过图片宽度直接除以宽高转 YOLO 时中心点和宽高会超过 1.0训练读取 txt 时会跳过该框或报错。常见做法是转格式时把坐标限幅到 0~1 之间再落盘。第三小目标的框质量。UAV 视角里小目标特别多标注框稍微多一点就导致下一阶段转换误差被放大所以这份资源里“标注框质量高”反而成了最值钱的部分。2.2 三个划分脚本的用途包里的脚本有三个不要一上来全部跑一遍先分清各自用途split_train_val生成ImageSets下txt文件划分脚本.py用来生成 VOC 风格 ImageSets/Main 下的 train.txt、val.txt这是老版 YOLO 项目读取路径列表的固定格式里面的行是不带扩展名的图片名。训练集、验证集划分脚本图片标签划分写入新文件夹.py把图片和标签按比例复制进新目录适合只需要 train/val 两折的项目。训练集、验证集、测试集划分脚本图片标签划分写入新文件夹.py多留出一个 test 文件夹适合要做最终泛化验证的项目。三个脚本的差异用一句话概括是“只生成清单”还是“真的把文件复制走”。如果你用的是 ultralytics 这条技术路线新版 YOLO 系列直接指文件夹路径就能训练复制走的方式更直观还能顺手排除坏图如果你在维护老版 YOLOv3/YOLOv4 的经典项目就必须靠 txt 清单。下面这段脚本逻辑与包中“训练集、验证集、测试集划分脚本”等价我在原脚本基础上加了校验逻辑你可以直接照着改import random import shutil from pathlib import Path IMG_DIR Path(JPEGImages) # 图片目录 TXT_DIR Path(labels) # 以YOLO txt标签为例VOC/COCO同理换目录 OUT_DIR Path(dataset_split) # 输出的新目录 TRAIN_R, VAL_R 0.7, 0.15 # 剩余0.15给测试集 random.seed(42) images sorted([p for p in IMG_DIR.iterdir() if p.suffix.lower() in (.jpg, .jpeg, .png)]) random.shuffle(images) n_train int(len(images) * TRAIN_R) n_val int(len(images) * VAL_R) groups { train: images[:n_train], val: images[n_train:n_train n_val], test: images[n_train n_val:], } for split, items in groups.items(): out_img OUT_DIR / split / images out_txt OUT_DIR / split / labels out_img.mkdir(parentsTrue, exist_okTrue) out_txt.mkdir(parentsTrue, exist_okTrue) for img_path in items: txt_path TXT_DIR / (img_path.stem .txt) if not txt_path.exists(): # 图片无标签时跳过并打印 print(f[warn] missing label: {txt_path.name}) continue shutil.copy(img_path, out_img / img_path.name) shutil.copy(txt_path, out_txt / txt_path.name)关键逻辑说明这里用iterdir()拿路径对象再sorted排序是因为os.listdir在 Windows 和 Linux 下返回顺序不固定直接 shuffle 会造成图片与标签错位random.seed(42)固定后每次重跑划分结果一致方便复现。默认 0.7/0.15/0.15 比例适合 5000 张左右的规模样本量更小时我一般把验证集压到 0.1让训练集更充足。标签目录这里写的是 txt如果你想保持 VOC(xml) 和 COCO(json) 同样跟随图片走把TXT_DIR换成对应文件夹复制逻辑完全一样不需要改造。提示VOC、COCO、YOLO 三种标签最好整组跟随同一张图片走划分后不要拆散。比如同一张图只把 txt 复制走了xml 还留在原目录下次换格式训练又得重新划分一次。2.3 从ImageSets的txt到train_list.txt的路径逻辑VOC 风格的 txt 和 train_list.txt 经常把人绕晕。生成 ImageSets/Main 下 txt 的脚本输出的每一行是图片文件名不带扩展名而 train_list.txt 这类文件每一行通常是完整路径是给老版 YOLO 训练器直接读取数据源用的。两者差的是一层“路径补全”。如果你用 classic darknet 体系训练命令里传的 train.txt 作为训练列表那么路径必须是相对命令行所在目录的相对路径或者直接写死绝对路径如果用 ultralytics 体系几乎不用 train_list.txtdata.yaml 里写train: images/train即可程序会自己扫目录。包内既保留 ImageSets 划分脚本又附带 train_list.txt是为两条路线都留好入口。我习惯从一开始就在 data.yaml 里用相对路径并统一用正斜杠避免 Windows 生成的 train_list.txt 带反斜杠到 Linux 上全部失效。还有一个高频小坑train_list.txt 里到底写图片路径还是标签路径老版 YOLO 读的是图片路径程序通过后缀替换自动找同名的 txt 标签。所以要保证 txt 与图片严格同名。处理文件名时不要用split(.)[0]文件名里可能多个点号用Path(file).stem最稳这也是我看了无数个“莫名找不到标签”问题后得出的结论。3. 环境搭建与训练教程Linux与Windows两条路线怎么快速改通包里的 HTML 教程按平台拆成 Linux 和 Windows 两套。很多人下载后只看了 Windows 版结果训练速度差一大截。先说结论有条件优先用 LinuxWindows 不是不能跑而是要注意驱动、CUDA、PyTorch 三者的版本匹配这个匹配关系搞不定后面每一步都难受。3.1 两个环境教程怎么选先对齐CUDA和PyTorch版本环境搭建这件事卡住 80% 新手的不是命令不会敲而是版本对不上。常见现象是装完 ultralytics 之后torch.cuda.is_available()输出 False模型在 CPU 上慢慢爬。包里的 Linux 教程是从 Ubuntu 安装开始讲起的Windows 教程则默认你已经有可用的显卡驱动两者的共同关键点是先确认本机 CUDA 能力。我一般建议按这个顺序做nvidia-smi # 看显卡驱动支持的最高CUDA版本 python -c import torch; print(torch.__version__, torch.cuda.is_available())如果第二行输出 False原因基本是 torch 装成了 CPU 版本或者系统里 CUDA runtime 与 torch 编译版本不匹配。Windows 我习惯用 Anaconda 新建独立环境再装 PyTorch最后pip install ultralytics顺序不要乱。教程 HTML 里写的版本号可能比当前新版本旧一点但底层逻辑一致你不需要为了教程降级驱动显卡驱动对同一代 CUDA 向下兼容。环境搭完跑一次完整的前向验证不要急着开训练yolo predict sourcetest.jpg modelyolov8n.pt能正常出框说明环境链路通出不来框先回查 CUDA 与 torch 版本别去怀疑代码。3.2 把教程里的案例模型改成训练自己的数据集训练教程的 HTML 标题写得很直白“根据案例修改训练自己的数据集”。核心动作其实只有三步整理目录结构、写对 data.yaml、改训练命令。数据集图片本身不用做任何预处理JPEGImages 原图直接可以喂。第一步把包里的图片和标签按标准结构放好datasets/uav/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/第二步写 data.yaml。注意类别名不要自己凭感觉编要以标签里实际出现的为准path: ./datasets/uav # 数据集根目录建议用相对路径 train: images/train val: images/val test: images/test nc: ? # 改成你的类别数先数labels下txt第一列有几个取值 names: [] # 顺序必须和txt里的class id一一对应第三步确认类别编号到底有几个。这是训练教程里最容易漏的一步跑一下这段脚本from pathlib import Path ids set() for p in Path(labels).glob(*.txt): with p.open() as f: for line in f: if line.strip(): ids.add(int(line.split()[0])) print(sorted(ids))输出类似[0, 1, 2]表示有三个类别names 就对应填三个字符串顺序不能乱。第四步启动训练。新版 ultralytics 命令行和 Python 接口都能用yolo detect train data./data.yaml modelyolov8n.pt epochs100 imgsz640 batch16from ultralytics import YOLO model YOLO(yolov8n.pt) model.train(datadata.yaml, epochs100, imgsz640, batch16)参数说明modelyolov8n.pt是预训练权重数据量大或者目标小时先用 n 起步不要一上来就 large无人机目标小通道数大的模型不一定有增益显存占用却翻倍imgsz640是默认输入尺寸目标在图中只占十几个像素时可以提到 1280代价是训练时间拉长接近一倍batch按显存调不稳比小更重要一旦爆显存训练中途崩了前面几百轮全部白跑。3.3 训练时长与超参调整的取舍5000 张图片规模不算小但无人机目标检测的角度、高度、背景变化很多不需要一上来就硬跑几百轮。我一般先跑 5 轮验证配置确认 loss 曲线在往下走再放开训练。如果 loss 震荡剧烈优先降学习率而不是急着换网络结构。小目标场景还有一个判断技巧训练时看 val_batch0_labels.jpg也就是第一张验证集标注图如果发现有很多目标框小到只剩几个像素就要认真考虑把 imgsz 往上提。提到 1280 后显存占用会明显增加此时 batch 要降下来比如从 16 降到 8这是性价比最高的取舍方案。另一个经验是数据增强不要全部打开无人机目标容易因为旋转增强被裁掉半边我一般适度保留 mosaic关掉 mixup对小目标更友好。这些经验在教程 HTML 里未必展开但属于跑无人机数据集时很实在的调参方向。4. 划分脚本常见问题排查四个翻车现场和事后处理这一章是根据我拆包和复现时见过的高频问题整理的每一条按“现象 → 原因 → 解决”来讲新手可以直接对照自己的日志判断卡在哪一步。4.1 图片和标签错位loss在下降预测却完全乱套现象训练命令能跑loss 也在降但打开验证集预测图框总是落在目标旁边的背景上或者同一张图片一会儿框这个、一会儿框那个。原因划分脚本里图片和标签分别用两套os.listdir拿文件名Windows 和 Linux 的目录遍历顺序恰好不一致文件复制到新文件夹后名字相同但内容对不上另一种常见是复制时只按*.jpg找图没有检查同名 txt 是否存在标签缺失后程序拿着上一张的标签继续读。解决只维护一个文件名列表图片和标签都基于它生成路径。复制完成后做一次主键校验from pathlib import Path imgs {p.stem: p for p in Path(datasets/uav/images/train).glob(*.jpg)} labs {p.stem: p for p in Path(datasets/uav/labels/train).glob(*.txt)} missing (imgs.keys() - labs.keys()) | (labs.keys() - imgs.keys()) print(mismatch:, missing) if missing else print(ok)输出mismatch为空才说明图片和标签一一对应。4.2 类别编号对不上mAP从0.8掉到0.3现象训练过程完全正常模型也能出框但某一类的精度和召回率一直是 0或者混淆矩阵里正确答案被算到相邻类别 ID 上。原因txt 标签里的 class id 和 data.yaml 的 names 排列顺序不一致。数据包里的标签本身没问题但你自己扩写 names 时加了一种类别或者用了另一份类别顺序完全不同的预训练权重导致第一列编号对应错位。解决训练前强制跑一遍类别编号统计用 2.2 节那段脚本输出所有出现过的 ID并把 data.yaml 里的 names 按输出顺序逐项核对。凡是出现类似“明明只有两类txt 却有三个 ID 取值”的情况都要回到标签目录清理。提示改 names 顺序后如果不重新划分数据直接接着断点训练几乎必出类别错位。改完 names 建议把 runs/detect 下的旧权重放到一边从头开始一轮新训练。4.3 训练中途报“cant open image”路径分隔符和漏复制现象训练跑到中途突然报错提示某张图片打不开但手动查看该路径文件是存在的。原因大概率是 Windows 划分后直接生成了反斜杠路径而训练环境在 Linux或者只复制了图片目录标签目录漏了部分文件还有一个隐蔽点文件名里带多个点号用split(.)[0]切分被切坏。解决所有路径生成统一用pathlib写入 train_list.txt 时强制转成/分隔符。推荐在脚本结尾加一段with open(train_list.txt, w) as f: for p in sorted(out_img.glob(*.jpg)): f.write(str(p.resolve()).replace(\\, /) \n)这样拿到的每一行都是正斜杠绝对路径Windows 生成、Linux 使用都不会出问题。4.4 负样本不足导致误检失控从数据集到现场部署的最后一课现象在数据集验证集上 mAP 很高拿到自己的无人机现场测试把电线杆、屋顶反光、树冠阴影全框成目标。原因训练集里标注框质量高但所有正样本都是干净视角模型把背景纹理也学成了特征缺少“什么都没有”的负样本图片来压住误检。解决从现场采集一批无目标或难例图片按 10%~20% 比例混进训练集图片不配标签即可。这是公开数据集迁移到实际部署场景前必备的一步不是数据集的缺陷而是任何真实项目都绕不开的环节。划分脚本复制图片时无标签图片默认会跳过并打 warn需要单独把负样本图片放进训练目录。5. 验证与部署技巧指标怎么看、TensorRT怎么走5.1 训练完成后的三个验证信号训练结束不要只看 metrics 表先打开runs/detect/train下的val_batch0_labels.jpg和val_batch0_pred.jpg对比标签框和预测框的位置确认无人机小目标没有被漏检。然后看混淆矩阵对角线小目标类被分到背景的比例一旦偏高就要回查标签或增强策略。最后才是 mAP50 和 mAP50-95无人机目标尺寸小mAP50-95 比 mAP50 更能反映定位精度。验证命令yolo detect val data./data.yaml modelbest.pt建议把best.pt同时拿到一段从未见过的视频上跑一遍视觉判断比指标更直观。5.2 从ONNX导出到TensorRT部署的常见步骤训练完要上线实时推理常见做法是先导出 ONNX再转成 TensorRT engine。无人机巡检场景里T4 这类卡做 25 FPS、1080p 视频流用 FP16 精度核心里输入分辨率定死在 640 更合适动态 shape 虽然灵活但会增加额外显存和延迟。导出命令yolo export modelbest.pt formatonnx dynamicTrue trtexec --onnxbest.onnx --saveEnginebest.engine --fp16dynamicTrue适合后期做多尺寸推理如果只想固定 640 输入去掉这个参数能减少转换后算子的复杂度。能带多少路视频流取决于显存与预处理流水线FP16 引擎下 2~4 路通常有富余。这套部署流程不依赖训练数据集本身但它是把数据集价值兑现到线上系统的最后一步。每次拿到新的数据集我都强制先跑一遍三段式校验类别编号统计、图片与标签配对、路径统一为正斜杠然后才开始训练。这套习惯让我少走了很多弯路拆这个包时也顺手把排查顺序整理成了前面四章。希望帮到你。本文还有配套的精品资源点击获取