简介一套面向无人机视觉应用的目标检测数据集包含5000张真实场景高清图像覆盖多种飞行环境与目标形态。数据使用LabelImg标注标签质量较高并同时提供VOCxml、COCOjson与YOLOtxt三种格式分别存放于不同文件夹可无缝接入YOLO系列模型训练与评测流程。资源共2000个文件以xml标签文件为主1986个另含Python划分脚本、环境配置与训练教程html/txt等压缩包大小约301.59MB。随包附带训练集、验证集、测试集划分脚本支持一键生成ImageSets下的txt索引方便按需划分数据同时提供Linux与Windows双平台的YOLO环境搭建和训练案例教程可引导用户快速修改配置训练自己的数据集。目前已有433人学习下载适合刚入门目标检测或需要规范标注数据的开发者能显著减少数据准备与环境配置的时间成本。1. 5000张无人机目标检测数据集省掉最磨人的标注环节做目标检测训练的人都知道模型跑不起来可以调代码但数据不行就是真不行。尤其是无人机视角的数据自己飞、自己拍、自己用labelimg一张张框5000张图工作量有多恐怖干过的人心里都有数。这份资源解决的就是这个痛点——5000张真实场景的无人机目标检测图片VOCxml、COCOjson、YOLOtxt三种格式标签全部配齐外加三个数据集划分脚本和一套完整的YOLO训练教程从环境搭建到改参数训练自己的数据集一条龙给你铺好。适合谁想做无人机视角目标检测、遥感图像检测、小目标检测方向的学生和从业者以及被标注和格式转换折腾到崩溃的YOLO新手。当然老手也能用它的划分脚本省点事。2. 数据集与三种标签格式先搞懂VOC、COCO、YOLO标签到底差在哪2.1 5000张真实场景图与labelimg标注数据质量看这三个点拿到一份目标检测数据集先别急着开训第一步是评估数据能不能用。这份无人机数据集的图片来自真实场景不是渲染图或者合成图这点对模型落地非常关键。无人机视角最大的特点是目标尺度小、背景复杂、光照变化大如果数据里全是合成图训练出来的模型一到真实场景就原形毕露。真实场景图虽然标注成本高但泛化能力是合成图比不了的。标注质量是第二个重点。资源里明确写了用labelimg标注软件完成标注框质量高。我从实操角度解释一下这个质量高意味着什么标注框贴边没有大面积留白、类别没有标串、遮挡目标只框可见部分。这些细节直接决定训练出来的模型边界框回归准不准。如果你之前用过那些自动标注工具生成的数据集就会发现很多框都是歪的或者明显偏大模型学出来框永远是虚的。第三个点是场景丰富度。5000张图如果全是同一片天空同一块草地那训练集再大也白搭。这份数据集的场景覆盖了不同高度、不同光照、不同背景这保证了模型的鲁棒性。我的经验是拿到数据集先随机抽50张图看一眼确认场景多样性和标注质量再决定要不要花时间训练。这个习惯能帮你省掉后面很多排查时间。2.2 三种标签格式的结构差异XML、JSON、TXT各管什么目标检测领域有三种主流标注格式几乎所有的训练框架都绕不开它们。这份数据集把三种格式都给你了存放在不同文件夹下可以直接用于YOLO系列模型训练。先看三种格式的本质区别格式所属标准文件后缀坐标表示方式典型框架VOCPASCAL VOCxml左上角x、y 右下角x、y像素坐标Faster R-CNN、SSDCOCOMS COCOjson左上角x、y 宽、高像素坐标Detectron2、MMDetectionYOLODarknet/Ultralyticstxt中心点x、y 宽、高归一化到0~1YOLOv5、YOLOv8这三种格式的区别不只是文件后缀不同坐标系定义逻辑完全不一样。VOC格式是绝对值记录的是标注框左上角和右下角的真实像素位置COCO格式也是绝对值但记录的是左上角坐标加宽高YOLO格式则是相对值所有数值都除以了图片宽高归一化到0到1之间。这个归一化的好处是无论图片resize成什么尺寸标签都不用改这也是YOLO系列训练起来省心的原因之一。2.3 三种格式都留着的原因不同训练框架的喂数据方式不同很多初学者会问我只用YOLO训练为什么还要留VOC和COCO格式原因很简单你可能今天用YOLOv8明天想试试MMDetection里的Faster R-CNN或者跑一下Detectron2的Mask R-CNN做实例分割这些框架对标签格式的要求完全不同。VOC格式转YOLO只需要用脚本解析xml再归一化但YOLO转VOC就麻烦得多因为归一化坐标要还原成像素坐标还得生成xml的完整结构。所以拿到一份三种格式齐全的数据集等于给自己留了后悔药。我经常跟朋友说的一句话是格式转换是目标检测里最没技术含量但最耗时间的工作。你花两小时写转换脚本调试到凌晨结果发现某个标签文件格式少了个字段整个训练直接报错。这份数据集的作者已经把三种格式按文件夹分好用哪个取哪个省掉的这部分时间足够你把训练跑完一轮了。3. 用划分脚本按需切分数据集训练集、验证集、测试集怎么分才合理3.1 三个划分脚本的分工先搞清楚你要用哪个压缩包里给了三个Python脚本功能各不相同我用之前先把它们区别列出来脚本名称功能适用场景训练集、验证集、测试集划分脚本图片标签划分写入新文件夹.py按比例把图片和标签同时分配到三个新文件夹数据量充足需要独立测试集做最终评估训练集、验证集划分脚本图片标签划分写入新文件夹.py按比例把图片和标签同时分配到两个新文件夹数据量一般只分训练集和验证集split_train_val生成ImageSets下txt文件划分脚本.py只生成包含文件名的txt索引文件不移动文件VOC格式训练前的标准动作配合VOCdevkit目录结构使用三个脚本的核心理念都是图片和标签必须同时移动这是最容易踩坑的地方。很多人自己写划分脚本时只移动了图片结果训练时报错找不到对应标签文件又要重新折腾。这三个脚本直接把图片和标签按同比例、同随机种子分配到目标文件夹从根上避免这个问题。3.2 训练集、验证集划分脚本的参数与逻辑解析先看两文件夹版本的脚本核心逻辑不长但几个细节值得注意import os import random import shutil # 配置参数 image_dir JPEGImages # 原图文件夹 label_dir labels # 原标签文件夹txt格式 train_image_dir images/train # 训练图片输出目录 train_label_dir labels/train # 训练标签输出目录 val_image_dir images/val # 验证图片输出目录 val_label_dir labels/val # 验证标签输出目录 val_ratio 0.2 # 验证集比例可自行修改 # 创建输出目录 os.makedirs(train_image_dir, exist_okTrue) os.makedirs(train_label_dir, exist_okTrue) os.makedirs(val_image_dir, exist_okTrue) os.makedirs(val_label_dir, exist_okTrue) # 获取所有图片文件名不含后缀 all_images [f for f in os.listdir(image_dir) if f.lower().endswith((.jpg, .jpeg, .png))] # 固定随机种子保证每次运行结果一致 random.seed(42) random.shuffle(all_images) # 按比例切分 val_count int(len(all_images) * val_ratio) val_images all_images[:val_count] train_images all_images[val_count:] # 图片和标签同步移动 for img_name in train_images: base_name os.path.splitext(img_name)[0] shutil.copy(os.path.join(image_dir, img_name), os.path.join(train_image_dir, img_name)) shutil.copy(os.path.join(label_dir, base_name .txt), os.path.join(train_label_dir, base_name .txt)) for img_name in val_images: base_name os.path.splitext(img_name)[0] shutil.copy(os.path.join(image_dir, img_name), os.path.join(val_image_dir, img_name)) shutil.copy(os.path.join(label_dir, base_name .txt), os.path.join(val_label_dir, base_name .txt)) print(f划分完成: 训练集 {len(train_images)} 张, 验证集 {len(val_images)} 张)这段脚本的核心设计有三个要点。第一random.seed(42)固定随机种子让每次划分结果一致这个习惯非常好——不然你每次运行脚本数据分布都不一样复现实验结果时会很崩溃。第二图片和标签通过base_name关联保证一张图一定带着自己的标签一起走不会出现图在训练集、标签在验证集这种低级错误。第三用的是shutil.copy而不是os.rename原文件保留相当于复制操作万一划分不合理可以重新来这就是后悔药。3.3 split_train_val生成ImageSets下txt文件VOC训练前的必经一步如果你打算用VOC格式跑训练第三只脚本才是你真正需要的。VOC系列数据集的目录结构要求ImageSets/Main下必须有train.txt、val.txt、trainval.txt这些索引文件里面一行一个图片文件名不带后缀训练框架通过这些txt去JPEGImages里找图、去Annotations里找xml标注。import os import random # 配置参数 xml_dir Annotations # xml标注文件夹 save_dir ImageSets/Main # 索引文件输出目录 train_ratio 0.8 # 训练集比例 val_ratio 0.1 # 验证集比例剩余为测试集 os.makedirs(save_dir, exist_okTrue) # 获取所有xml文件名不含后缀 all_names [os.path.splitext(f)[0] for f in os.listdir(xml_dir) if f.endswith(.xml)] random.seed(42) random.shuffle(all_names) total len(all_names) train_count int(total * train_ratio) val_count int(total * val_ratio) train_names all_names[:train_count] val_names all_names[train_count:train_count val_count] test_names all_names[train_count val_count:] # 生成txt索引文件 with open(os.path.join(save_dir, train.txt), w) as f: f.write(\n.join(train_names)) with open(os.path.join(save_dir, val.txt), w) as f: f.write(\n.join(val_names)) with open(os.path.join(save_dir, test.txt), w) as f: f.write(\n.join(test_names)) with open(os.path.join(save_dir, trainval.txt), w) as f: f.write(\n.join(train_names val_names)) print(ftrain: {len(train_names)}, val: {len(val_names)}, test: {len(test_names)})这里有一个容易被忽略的点trainval.txt是训练集加验证集的并集。很多VOC框架的配置里训练的起始点读的是trainval.txt而不是train.txt如果你只生成了train.txt运行训练脚本时会报找不到trainval.txt。另外注意这个脚本只生成索引文件不会动你的图片和标注文件夹所以它对原数据的侵入性为零跑错了删掉txt重新生成就行。3.4 划分比例怎么定不同数据量下的常见做法划分比例没有绝对标准但有个经验值可以参考数据量在几千张这个级别训练集、验证集、测试集按8:1:1分配比较稳妥如果总量只有几百张建议只分训练集和验证集比例9:1测试集直接复用验证集做粗略评估数据量过万时可以调成训练集占90%以上因为大数据量下验证集不需要太大就能反映分布。我在实际项目里的做法是先用脚本按8:1:1划分训练完一轮后检查验证集的loss曲线。如果验证集loss和训练集loss差距很大说明划分可能有问题这时检查是不是某类目标只出现在验证集里。数据分布的随机性有时候会和你开玩笑一个小类别在全量数据里占比只有2%随机划分后可能验证集里一个都没有训练集里一堆——所以固定随机种子并且重复实验很重要多跑几次划分挑一个类别分布最均匀的结果。4. YOLO环境搭建与训练教程Linux和Windows两条路都给你铺平4.1 Linux版本环境搭建Ubuntu 显卡驱动 CUDA的配置顺序资源里的教程用HTML格式编写从Linux之Ubuntu环境安装讲起一路覆盖到YOLO环境搭建和训练。这套顺序是合理且完整的我自己装环境的顺序也是如此。Linux下装深度学习环境最常见的坑是顺序错了导致显卡驱动和CUDA冲突。先看Ubuntu环境准备的基本流程# 更新系统源 sudo apt update sudo apt upgrade -y # 安装基础开发工具 sudo apt install -y build-essential cmake git # 安装NVIDIA显卡驱动建议通过ubuntu-drivers自动安装 ubuntu-drivers devices sudo apt install -y nvidia-driver-550 # 重启后验证驱动 nvidia-smi # 安装Anaconda wget https://repo.anaconda.com/archive/Anaconda3-2024.02-1-Linux-x86_64.sh bash Anaconda3-2024.02-1-Linux-x86_64.sh # 创建虚拟环境并安装PyTorch conda create -n yolo python3.10 -y conda activate yolo pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118驱动安装这块有个经验不要自己去NVIDIA官网下载驱动然后手动装很容易把系统搞崩溃或者出现循环登录问题。用ubuntu-drivers devices查看推荐版本然后apt install自动安装这是最稳的路径。nvidia-smi能正常输出就说明驱动OK。CUDA这块需要解释一下nvidia-smi显示的CUDA版本是驱动支持的版本不代表你现在就能用。实际训练用到的是PyTorch内置的CUDA所以只要PyTorch装对了你不需要单独装完整的CUDA工具包。很多人看到nvidia-smi显示CUDA 12.4就跑去装CUDA 12.4然后又装了对应的cuDNN折腾半天——其实根本不用。PyTorch的pip安装包里自带CUDA运行时版本匹配就行。教程里如果让你装CUDA Toolkit记住那个是给编译C扩展用的纯训练用不上。4.2 Windows版本环境搭建Anaconda PyTorch踩坑记录Windows环境相对好装因为你不需要单独处理显卡驱动和CUDA的兼容性问题——用Anaconda创建环境后装对PyTorch版本就行。Windows版本教程里完整覆盖了这条路径配图跟着做就行。但有几个细节我说一下# Windows下用conda创建虚拟环境 conda create -n yolo python3.10 -y conda activate yolo # 安装PyTorchCUDA 11.8版本 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装ultralyticsYOLOv8官方库 pip install ultralytics # 验证环境是否可用 python -c import torch; print(torch.cuda.is_available())如果输出False先说结论90%的情况是PyTorch装成了CPU版本。检查方法是在Python里跑torch.cuda.is_available()如果返回False再跑torch.__version__看看版本号。如果版本号里带cpu后缀删掉重装cu118版本就行。Windows上这个问题出现频率极高教程里如果没特别强调你大概率也会栽一次。4.3 训练教程怎么改从官方案例到自己的数据集资源里附带的训练教程核心价值在于根据案例修改训练自己的数据集这句话说透了YOLO训练的本质。官方提供的yolov8n.pt预训练权重虽然能跑通流程但直接用别人的权重检测无人机目标效果很差因为COCO数据集的80个类别里没有无人机目标。你需要做的就是三件事准备数据、改配置文件、跑训练命令。数据准备部分第三步已经做完了图片和标签按训练集、验证集分好YOLO格式的txt标签也在。接下来最关键的是写data.yaml# data.yaml train: D:/drone_dataset/images/train # 训练集图片路径 val: D:/drone_dataset/images/val # 验证集图片路径 nc: 4 # 类别数量改成你的实际类别数 names: [drone, helicopter, plane, bird] # 类别名称这里有个最常见的翻车点路径分隔符。Windows下用反斜杠\在yaml里会被当成转义符导致路径解析失败。我一般建议统一改成正斜杠/Windows下也能正常识别。另一个坑是相对路径和绝对路径混用推荐统一用绝对路径避免训练脚本的工作目录变化导致文件找不到。然后跑训练命令# Linux/Windows通用 yolo train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch16epochs参数决定了训练轮数无人机小目标检测场景100轮起步比较稳前期可以先用50轮跑通流程确认没问题再全量训练。imgsz这个参数影响很大你的数据集图片如果分辨率较高比如1920x1080的航拍图建议用imgsz640输入这个是速度和精度的平衡点。如果想进一步提升小目标检测效果可以试imgsz1280代价是训练时间几乎翻倍。batch参数受显卡显存限制显存不够时优先把它调小。5. 避坑指南格式、路径、显存这些坑我都替你踩过5.1 图片和标签文件名对不上训练报错现象训练刚开始没几分钟就报错提示File not found或者assertion failed查看具体信息是某个图片找不到对应的txt标签文件。原因数据集是从不同渠道收集的一些图片文件没有对应的标注文件或者标注文件后缀不对比如png图片配了jpg的标签名。YOLO系列的加载逻辑是默认每张图必须有一个同名的txt文件缺一个就整体中断。解决训练前写一个校验脚本遍历所有图片文件检查同名txt是否存在。我一般会直接在命令行里快速检查# 检查图片目录和标签目录的文件数量差异 ls images/train | wc -l ls labels/train | wc -l # 找出来缺少标签的图片 for img in images/train/*.jpg; do base$(basename $img .jpg) if [ ! -f labels/train/$base.txt ]; then echo Missing: $img fi done如果有缺失两种处理方式图片质量好的手动补一个空标签图片本身有问题直接删除。不要嫌麻烦这个校验步骤能帮你省掉训练中途崩溃的时间。5.2 txt标签里出现异常数据loss直接变成nan现象训练开始时loss正常几十个iteration后loss突然变成nan然后一直保持nan模型完全学不进去。原因标签文件里出现了异常值。最常见的两种情况一是某个txt文件内容是空的全空文件会让损失函数计算出错二是坐标值中有0或者大于1的数比如宽高算出来是0导致边界框回归的损失变成无穷大。解决写个Python脚本扫一遍所有标签文件过滤异常数据。检查逻辑是每行必须有5个值且后四个值都在0到1之间且大于某个极小值比如0.0001import os def validate_labels(label_dir): for f in os.listdir(label_dir): if not f.endswith(.txt): continue path os.path.join(label_dir, f) with open(path, r) as fp: lines fp.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(fInvalid line in {f}: {line}) else: # 检查坐标是否在(0,1)范围内 for val in parts[1:]: if float(val) 0 or float(val) 1: print(fOut-of-range value in {f}: {line}) break validate_labels(labels/train)这条检查花两分钟能避免你浪费好几个小时在无效训练上。5.3 路径带中文或是空格数据加载阶段神秘报错现象数据和代码都按要求放好了训练脚本也能正常启动但每次跑到数据加载阶段就报各种奇怪的错误——有时候是FileNotFoundError有时候是Image open failed同一个文件夹在Python里能os.listdir出来但图像就是加载不进去。原因路径里有中文或者空格字符。OpenCV和PyTorch的某些底层图像加载函数对非ASCII路径支持不好尤其Windows环境下问题更严重。解决最省事的办法是一开始就避免——所有目录都用英文命名不要有空格、不要有中文。如果已经踩了坑把数据文件夹整个移到英文路径下然后修改data.yaml里的路径即可不需要重新改标签。这个问题的隐蔽性很高因为它不是稳定复现的有时候加载100张图只报5张的错。5.4 显存不足CUDA out of memory现象训练刚开始就报CUDA out of memory或者训练到一半通常是数据进入GPU的瞬间直接崩掉。原因batch_size设得太大或者imgsz设得太大。很多人在教程里看到batch16就照着填但自己的显卡是6GB显存跑640x640的图16张一次性进显存肯定爆。解决# 降低batch_size重新训练 yolo train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch4如果batch调到2还爆显存就要检查是不是有其他进程占用了显存。用nvidia-smi查看GPU占用情况把不用的Python进程杀掉。还有一招是降低imgsz到480或者416对小目标检测会稍微损失一点精度但至少能跑起来。5.5 验证集mAP很高但实际检测效果很差现象训练结束验证集上mAP达到0.85甚至更高但拿自己的图片一测试完全检测不出来或者检测结果乱七八糟。原因这就是典型的过拟合到训练数据分布上。你的验证集划分没问题但训练数据本身和真实使用场景存在分布差异——比如训练数据全是晴天光线好的照片实际使用环境是多云或者逆光。解决分两步自查。第一步检查训练集和验证集是否来自同一分布做法是随机抽训练集和验证集各50张图做对比看光照、角度、目标大小是否接近。第二步是使用数据增强策略YOLO内置了mosaic、hsv变换、random flip等增强手段确认训练时这些增强没有被关闭。如果问题依旧最有效的办法是补充更多场景的数据把泛化能力这个物理问题交给数据量来解决。6. 验证训练结果用精确率、召回率和置信度门限判断模型能不能用6.1 从训练日志到实时检测看懂每项指标再决定要不要调训练结束后会生成runs/detect/train目录里面包含results.png、confusion_matrix.png、PR_curve.png等文件。我的习惯是先看三个数字验证集上的精确率Precision、召回率Recall和mAP50。然后写个快速检测脚本找几张训练集和验证集之外的真实照片跑一遍yolo detect predict modelruns/detect/train/weights/best.pt source/path/to/test_images imgsz640如果跑出来的效果跟预期差距大最应该调的是置信度门限conf threshold。这个参数直接决定模型输出多少个预测框——设置太高会漏检设置太低会误检。# 用不同置信度跑同一张图观察输出变化 yolo predict modelbest.pt sourcetest.jpg conf0.1 yolo predict modelbest.pt sourcetest.jpg conf0.56.2 用混淆矩阵定位模型到底错在哪confusion_matrix.png能直观告诉你模型把哪两个类别搞混了。无人机检测场景里最常见的混淆是小型无人机和飞鸟——这两个目标在图片上特征很像都是深色小斑点如果没有足够的训练样本去区分细微差异模型就会在这两个类别上来回横跳。如果混淆矩阵显示这个错误占比很高说明你需要在数据层面补充更多无人机和鸟同框的图片让模型学会用飞行姿态和纹理差异来区分而不是单纯加大训练轮数。那是无数个睡眠被精简标注和训练日志蚕食掉的夜晚换来的经验从那以后我每次训练自己的数据集都会强制走一遍这套检查流程先看标签有没有脏数据、再确认划分分布合理、训练完绝不只看mAP还要用真实场景图验证、最后检查混淆矩阵——每一步都至少节省我一周的排查时间。这份资源把数据集、标签格式、划分脚本和训练教程放在了同一个压缩包里你不需要再去网上零散地找各种工具和说明省下的时间可以全部花在模型调优和实际项目落地上面希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?