DOTAv2.0遥感目标检测数据集实战:VOC与YOLO双格式详解

📅 发布时间:2026/8/27 22:20:05
DOTAv2.0遥感目标检测数据集实战:VOC与YOLO双格式详解
简介目标检测是计算机视觉的核心任务之一尤其在高空遥感影像中检测轮船、飞机、车辆等目标需要高质量的标注数据作为支撑。数据格式的规范化与预处理直接影响模型训练效率和精度。DOTAv2.0数据集是目前遥感目标检测领域广泛使用的基准之一覆盖16个常见类别并提供VOC与YOLO两种组织格式既满足了传统检测框架的调试需求也适配YOLOv8等现代模型的高效训练。基于该数据研究者可以快速验证算法在小目标、旋转目标等复杂场景下的表现并推动从智慧港口到无人机巡检等工程落地。本文围绕该版本数据集的目录结构、标注坐标约定、格式转换原理及YOLOv8全流程实操展开帮助读者避开常见的数据坑。1. 遥感目标检测的数据困局与DOTAv2.0的价值做遥感航拍目标检测的人大概率都经历过这种尴尬GitHub上找到一个很好的检测项目跑通demo用了半小时但真正想在自己的场景里验证效果时发现手里没有一张带标注的遥感图。自己标一张512x512的遥感图里密密麻麻上百个目标标完眼睛都快瞎了。用自然场景数据集COCO、VOC训练模型在俯拍视角下识别轮船、飞机、田径场这种强旋转、大尺度差异的目标效果基本是灾难。DOTAv2.0就是为这个场景而生的数据集。作为遥感目标检测领域的标杆数据集它覆盖了飞机、轮船、储油罐、棒球场、网球场、篮球场、田径场、港口、桥梁、大型车辆、小型车辆、直升机、环岛、足球场、游泳池、集装箱起重机16个常见类别全部来自真实卫星与航拍影像经历了严格的标注和预处理。你手里的这个版本是4840张图、16类别、同时提供VOC和YOLO两种格式的整合包实用性很强。它直接解决了两个痛点一是省去了从DOTA官网下载原图再逐张转换格式的繁琐流程二是踩平了新手转换标签格式时最容易踩的坐标系、归一化、类别映射这些坑。这批数据适合谁来用三类人最合适第一类正在学习YOLO系列目标检测YOLOv5、YOLOv8、YOLOv9、YOLOv10甚至YOLOv11的学生和研究者需要一个开箱即用的遥感场景数据集来练手第二类做工程落地的人比如智慧港口、安防监控、无人机巡检需要先在标准数据集上做基准测试第三类搞算法对比的人需要统一的数据格式、统一的数据划分来做公平对比。但有一点要提前说清楚DOTA系列原图尺寸很大通常800x800到4000x4000不等这个4840张的版本大概率是原作者经过切片crop预处理后的产物每个切片尺寸比较规整更适合直接进YOLO训练管线这也是我决定围绕它写一篇完整实操笔记的原因。顺便给刚接触的人一个定位参考DOTA的全称是Dataset for Object deTection in Aerial images目前社区里常见的是v1.0、v1.5和v2.0三个版本。v2.0相比v1.0增加了更多小目标样本而且新类别更多难度也更高。你手里这个16类的版本虽然没有覆盖官方v2.0的全部18个类别官方多了机场和直升机停机坪两个场景类但样本量极少但在实际工程中把样本稀疏的类别去掉反而能让模型训练更加稳定——这也是很多开源数据集做二次整理时的常见取舍。2. 数据集结构拆解VOC和YOLO格式到底长什么样2.1 拿到压缩包后的第一眼目录结构解压这个.7z文件之后会看到两个核心目录VOC和YOLO另外通常会附带一个classes.txt或label_list.txt。我一直建议动任何数据之前先把这个文件打开看一眼因为它决定了你后续训练时类别顺序是否一致。用我手上的这份数据举例类别清单大概是这样的具体以你解压后的实际文件为准0: plane 1: ship 2: storage-tank 3: baseball-diamond 4: tennis-court 5: basketball-court 6: ground-track-field 7: harbor 8: bridge 9: large-vehicle 10: small-vehicle 11: helicopter 12: roundabout 13: soccer-ball-field 14: swimming-pool 15: container-crane这16个类别的排列顺序就是YOLO训练时各文件夹下的classes.txt内容。这个顺序非常关键——训练时data.yaml里的类别名称必须和它完全一致否则会出现“模型学的是船但标签告诉它这是飞机”的严重错乱。VOC目录内部是标准VOC布局JPEGImages所有jpg图片、Annotations所有xml标注文件、ImageSets/Maintrain.txt、val.txt、test.txt等划分文件。YOLO目录内部则是images和labels两个大文件夹各自下面又有train和val子集划分部分整合包还会带一个test子集。这种双目录结构的好处很明显你可以在同一份数据上无缝切换VOC格式的检测器比如SSD、Faster R-CNN和YOLO格式的检测器不需要任何中间转换。2.2 标注文件的内容与坐标约定随便打开一个VOC的xml文件能看到类似这样的结构annotation folderJPEGImages/folder filenameP0001.jpg/filename size width1024/width height1024/height depth3/depth /size object nameship/name bndbox xmin231/xmin ymin447/ymin xmax694/xmax ymax812/ymax /bndbox /object /annotation这里的坐标是绝对像素值左上角为原点x向右增大y向下增大单位是像素。物体越界的情况在这种切片版本里偶尔会发生目标正好落在切片边缘所以后面我会专门讲一个坐标裁剪的函数。而YOLO格式的每个txt文件里一行对应一个目标格式是class_id x_center y_center width height注意这五个值全部是归一化到0到1之间的相对值计算方式是中心点坐标和宽高分别除以图片的宽和高。坐标是相对于整张图的比例而不是绝对像素。核心转换公式其实就这几行x_center (xmin xmax) / 2 / image_width y_center (ymin ymax) / 2 / image_height width (xmax - xmin) / image_width height (ymax - ymin) / image_height反过来从YOLO格式还原绝对坐标也一样简单xmin (x_center - width / 2) * image_width xmax (x_center width / 2) * image_width ymin (y_center - height / 2) * image_height ymax (y_center height / 2) * image_height如果你需要对换格式我建议花10分钟自己写一遍这个脚本而不是直接复制网上的大而全转换代码因为自己重建一遍的过程中你会真正理解坐标系的含义后面排查问题时也能更快定位到是文件写错了还是代码读错了。2.3 为什么是水平框不是DOTA原本的旋转框这里必须补充一个背景DOTA原版的标注是四边形旋转框每个目标用四个顶点表示即x1,y1,x2,y2,x3,y3,x4,y4不是VOC和YOLO标准支持的水平框。而这个整合版直接提供VOC/YOLO格式说明原数据作者已经做了旋转框到水平外接矩形的转换工作。这意味着什么我在实际使用中发现对于ship、large-vehicle这类长宽比很大的目标旋转框转水平框后框内会混入大量背景比如船旁边的水面、车旁边的路面这会降低定位精度。所以如果你后续做的是旋转框检测比如用Oriented R-CNN、S2ANet、YOLOv8-OBB这些模型就得回到DOTA原始标注的格式去找数据。但如果是快速验证YOLO系列的水平框检测效果这份数据完全够用mAP依然有参考价值因为绝大多数目标的水平外接框和真实目标的重合度在遥感场景里是能接受的。2.4 数据分布与类别均衡性观察我拿到数据后做的第一件事永远是写一段脚本统计各类别的目标数量。方法很简单遍历所有YOLO标签文件统计每个class_id出现的次数。从这份16类版本数据看ship和small-vehicle通常数量最多它们本来就是海洋和城市影像中最常见的对象而helicopter、container-crane这类目标数量会少很多。这种天然的长尾分布在遥感数据中非常普遍因为现实世界里直升机本来就比船少得多。别急着开训练。先看你手头这份数据的真实分布再决定要不要做采样策略调整。如果某个类别目标数不到另一类的十分之一那训练时这个类别基本学不好。我在后面的实操章节里会给一个具体的处理方案。3. 双格式数据集的演进逻辑VOC转YOLO的取舍与为何YOLO成为主流3.1 从XML到TXT不同检测框架下的格式演进VOC格式Pascal VOC标准诞生的年代Faster R-CNN、SSD是主流python生态里解析xml有很成熟的库绝对像素坐标对调试友好可以直接在图片上画框检查。但到了YOLO时代训练管线要求输入尺寸统一如640x640、1024x1024读取标注时更希望直接拿到归一化坐标用于框回归。所以在YOLOv5之后的生态里TXT格式成了事实上默认的标准。如果你自己动手做转换我有一个忠告不要单独写一个只有“转换”功能的脚本而要把校验也做进去。比如转换后立即检查坐标是否越界、width/height是否为负、类别id是否超范围。一旦这些脏数据进入了训练集轻则训练loss曲线异常重则模型推理时直接崩溃。3.2 数据集划分train/val/test的分配策略这个版本的目录结构里已经帮你做了train和val的划分也部分提供了test。通常的比例是811或者82无test。我的习惯是不直接用它的划分而是自己重新划分一遍原因有两个第一遥感图某些切片之间高度相似同一块区域相邻切片如果恰好一批相似的图被分配到train而另一批完全相同的区域被分到val会造成val精度虚高。我建议用洗牌固定随机种子来打散同时检查train和val里不该有同名图片。第二你有没有想过模型的最终部署场景如果目标是无人机实时巡检那val里最好多留一些带小目标的难例如果目标是海面搜救那ship、small-vehicle这些类别的样本分配权重就要重点照顾。标准数据集自带的划分是通用的但你的任务是特定的。这里给一个我常用的五五分配改良版train占70%val占15%test占15%。并且划分之后我会统计三个集合里每类的目标数量计算类别分布比例保证三个集合分布差不多。这一步对后面得出的mAP才有解释力。3.3 为什么遥感数据集特别适合用YOLO做基准YOLO系列做遥感目标检测有天然优势但也有明显短板。优势在于速度和精度均衡YOLOv8在单张3080上训练这个体量的数据几小时就能出一版可看的结果迭代快。这和遥感任务的频繁试错需求非常契合。短板在于水平框表示对旋转目标不友好以及小目标检测能力相对受限——遥感影像中大量目标是几十个像素大小的车辆和船只YOLO的neck和head设计对这类目标的召回率不够理想。所以我的建议是第一版先老老实实用YOLOv8n或者YOLOv8s在640分辨率下跑通整个流程拿到基线第二版把输入分辨率提升到1024或者1280观察小目标recall有没有提升第三版再尝试YOLOv8-OBB做旋转框对比同条件下的mAP差异。每一步都有标准数据集做支撑这样的实验报告才完整。4. 实操全流程从解压到训练出第一版模型4.1 环境准备与数据体检脚本先说环境。这部分是完全通用的操作如果你是第一次搞建议配好python3.8以上版本安装ultralytics库YOLOv8及以上版本统一用这个库pip install ultralytics即可另外需要opencv-python、numpy、matplotlib、pandas这些常规依赖。数据解压后我建议你立刻跑一个数据完整性校验脚本不要把这个问题留到训练中途炸了才发现。这个脚本做三件事检查images和labels下的文件名是否一一对应、检查所有txt文件是否为空或格式错误、统计每类目标数量并打印分布。import os from collections import Counter images_dir yolo/images/train labels_dir yolo/labels/train label_names open(classes.txt).read().strip().split(\n) missing [] format_errors [] cnt Counter() for img_file in os.listdir(images_dir): stem os.path.splitext(img_file)[0] label_file os.path.join(labels_dir, stem .txt) if not os.path.exists(label_file): missing.append(img_file) continue with open(label_file) as f: for line in f: parts line.strip().split() if len(parts) ! 5: format_errors.append(label_file) continue cls_id int(parts[0]) if cls_id len(label_names): format_errors.append(label_file) continue x, y, w, h map(float, parts[1:]) if w 0 or h 0 or x 0 or x 1 or y 0 or y 1: format_errors.append(label_file) cnt[label_names[cls_id]] 1 print(missing labels:, len(missing)) print(format errors:, len(format_errors)) print(class distribution:, cnt.most_common())这段代码花30秒跑完就能对数据集状况有一个全局认识。如果missing或format_errors数量不为0先处理数据质量问题再训练。别嫌麻烦这一步能给你省出后面好几个小时的debug时间。4.2 坐标裁剪与异常标注修正如果有些标注框超出了图片边界比如框的xmax大于图片宽度YOLO训练时通常不会直接报错但损失函数计算时会让模型学习到错误的坐标信息最终推理时可能出现大量越界预测框。我处理这类问题是写一个safety_crop函数把越界坐标直接裁剪到边界内同时丢弃裁剪后面积过小的框。注意一点不能把越界的框直接粗暴删除因为很多目标本来就位于切片边缘直接删了会丢失真实样本。正确做法是把超出边界的部分裁掉保留边界内的有效区域。如果你的标注里出现了负数坐标或者宽高为0的框这种就是脏数据没什么好犹豫的直接删掉那一行。4.3 组织YOLOv8训练所需的data.yaml格式正确的数据必须配一份正确的data.yaml才能开始训练。在ultralytics框架下一份基于这个版本数据的yaml大致长这样path: /your/absolute/path/dota16 train: images/train val: images/val test: images/test nc: 16 names: 0: plane 1: ship 2: storage-tank 3: baseball-diamond 4: tennis-court 5: basketball-court 6: ground-track-field 7: harbor 8: bridge 9: large-vehicle 10: small-vehicle 11: helicopter 12: roundabout 13: soccer-ball-field 14: swimming-pool 15: container-crane这里有一个很容易踩的坑path字段建议填写绝对路径。如果你用相对路径ultralytics在切换工作目录时经常找不到数据导致训练一启动就报错。names的顺序你必须逐一核对不要想当然认为它一定和你classes.txt一致。差一个顺序整个模型的输出类别就全错位了。4.4 训练命令与参数建议YOLOv8做遥感目标检测我给一个亲测比较稳的起步配置yolo train datadota16.yaml modelyolov8s.pt epochs100 imgsz1024 batch16 device0我解释一下这几个关键参数的选择逻辑这不是随手写的。imgsz1024是遥感这个场景下我的第一推荐。官方默认640对常规自然图像够了但遥感图里的目标通常更小、更密集640下很多小目标会直接退化成几个像素模型根本学不到特征。把输入分辨率提到1024以上小目标的AP会有肉眼可见的提升。代价是训练速度变慢、显存占用升高。batch16是在普通消费级显卡12GB到24GB显存上的折中选择。如果你显存只有8GBbatch降到8或者用yolov8n模型。别盲目追求大batchbatch32和16在最终mAP上的差异远没有你想象的大。epochs100是遥感数据集上相对保守的设置。由于遥感目标特征相对清晰船、飞机这种人造目标的结构性很强100个epoch通常在第60到80个epoch就趋于收敛了。你可以配合早停策略patience15自动截断。如果你是第一次训练建议先跑yolov8n而不是yolov8s用20个epoch验证整个管线是否能完整跑通。训练过程能看到loss曲线、mAP曲线当这些指标正常下降时再放心地起长训练。4.5 遥感场景下的性能再提升从检测到分析拿到第一版模型之后不能直接说“完事大吉”。遥感目标检测和自然图像目标检测最大的区别在于后处理和分析的环节非常多。我以前的一个项目里模型mAP在验证集上到了0.62看起来还行但真正到港口视频流上测试时发现舰船目标被检测出来之后同一个目标在连续多帧里被反复大声告警。最终解决不是靠换模型而是在后处理里加了简单的去重逻辑按框中心点距离判断是否为同一目标。这类经验说明数据集的干净程度和标签体系的一致性对最终系统的稳定性影响很大。这份DOTAv2.0版本数据虽然已经比较规整但不同类别的标注标准是否完全一致比如large-vehicle和small-vehicle的划分阈值你还是得通过可视化检查确认一下。用一个简单的opencv脚本把标注画到图上多翻几十张图这是最笨也最有效的办法。我几乎每次换数据集都会做这一步总能发现一些奇奇怪怪的标注问题。5. 常见问题与排查技巧实录5.1 图片数量和标签数量对不上这是解压数据后最常遇到的情况。images下有4840张图labels下却只有4837个txt少了3个。不一定全是缺失也可能是图片和标签文件命名后缀不同比如jpg和JPG混用。先用脚本按文件名匹配统计缺失情况再决定补标还是剔除。如果是缺失我推荐剔除而不是补标。因为一个本来就没有目标的图片被放进训练集YOLO会把它当作负样本对它做背景特征学习。但如果你在推理时用这张图的同一场景模型不见得能正确识别出里面没有目标。从数据一致性角度看剔除是最安全的做法。5.2 类别编号错位训练loss下降了但预测完全不对这是我见过最多人踩的坑也是影响最隐蔽的坑。你训练了很久loss降得很好val mAP看起来也不低但一推理发现模型把船识别成了飞机把飞机识别成了卡车。根本原因就是data.yaml里的names顺序和标签文件里的class_id对应关系不一致。比如你的标签txt里类别2是storage-tank但你在data.yaml里把下标2写成了ship。模型学的其实是储油罐的特征但被你强行命名为ship推理时当然荒谬。排查方法很简单找一个val图片用模型预测后把类别名称和置信度打出来再做可视化对比。或者更直接一点在训练前用前面那种统计脚本把每类的目标数量和data.yaml的names同时打印出来人工核对一遍。5.3 小目标AP偏低是模型问题还是数据问题遥感场景里小目标面积小于32x32像素检测一直是最头疼的问题。如果你的测试结果显示small-vehicle的AP比medium和large目标低了20个点以上别马上开始调模型结构先确认数据里小目标的比例是否足够。一个简单的统计办法是计算每个框的面积和原图面积比再按尺度分桶统计数量。小目标样本不足时加倍这类样本的效率远高于调模型。也可以在mosaic增强的基础上提高mosaic时小目标切片的保留概率。ultralytics库虽然默认开了mosaic但对小目标的增强策略还是预留了调整空间。这个版本数据集如果是在大图上切片生成的小目标样本通常不会太少具体数据分布还是上面那个脚本说了算。5.4 训练时出现NaN lossloss为NaN是训练崩溃的典型信号。在YOLO训练里绝大多数情况不是数据问题而是学习率太高或batch中含有异常标注。如果只是偶尔一次NaN可以降低学习率到默认值的十分之一继续跑如果频繁NaN就去查数据里是否有极端的坐标异常比如width或height为0。有个小技巧先花10分钟跑个基准测试把batch设为1遍历全部数据预跑一次定位是否有某张图导致loss异常。用二分法缩小排查范围能快速定位到具体是哪张图片的问题然后检查它的标签坐标是否合理。5.5 类别不均衡从数据层面拉高尾类性能前面提到过helicopter、container-crane这类目标数量可能只有几十个。如果训练结果里这几个类别的AP很低甚至全程为零这很正常。我建议这么处理最简单的办法就是给尾类样本加权在loss计算时增大稀有类别的权重。ultralytics框架对每个类别设置独立的loss weight并不是开箱即用的所以更通用的做法是数据级增强对包含稀有类别的图片做复制、旋转、翻转、随机裁剪扩充样本量。切不要做直接简单复制而是配合图像变换生成新样本。如果经过这些手段之后尾类AP还是上不去就要接受一个现实主义结论某些类别之间本来就具有强视觉相似性比如环岛和球场、大型车辆和小型车辆在标注边界模糊的情况下模型很难学到完美的区分。这时候宁愿合并相似类别也不要硬顶着十几个类去追求每个类都高出彩。6. 如何在你的项目里用好这份双格式数据6.1 用VOC格式做迁移学习验证可能有人会问我直接用YOLO格式不就完了吗为什么还要保留VOC那种老格式我自己的一个实际经历是在某个边缘设备项目里目标检测模型需要先用OpenCV的DNN模块加载模型推理而DNN模块版本对训练框架的兼容性要求很高。后来重新在PaddleDetection框架下改造模型它对VOC格式数据集的读取支持得更好。这份数据同时提供VOC和YOLO两种格式省去了我用脚本互转的时间也避免了转换时可能出现的坐标偏移误差。更实际的一个价值是VOC格式是学术界评测评测时通用的数据接口如果后面对接Cascade R-CNN、DETR等经典检测框架VOC格式可以直接用完全不需要处理。所以建议你两个目录都保留不要觉得用不到就删等真要跨框架切换的时候就知道了。6.2 YOLO格式的进阶玩法层次化标签体系当你熟悉了这套数据的组织方式可以尝试将16个类别合并成更上位的类别做层次化检测。比如把large-vehicle和small-vehicle合并为vehicle把baseball-diamond、tennis-court、basketball-court、ground-track-field、soccer-ball-field合并为playing-field。这种操作对模型的类别区分压力会小很多适用于第一阶段的快速检测筛选第二阶段再细化分类。做这种合并的最快方式是直接改txt文件里的class_id不需要动图片。比如把原来的large-vehicle9和small-vehicle10统一改成某个新的类别编号。但注意合并后类别数量变了data.yaml和classes.txt也要同步改否则编号还是会错位。我把这个玩法看作一份数据集的最大化利用——它可以同时服务于粗检测和细分类两个任务性价比很高。6.3 从这份数据出发你的下一步该做什么这份DOTAv2.0版本的数据集适合作为起点但真实项目里你最终还是要用自己的数据。我的建议路线是先用这份标准数据跑通整个训练、评估、推理链路确认流程无误然后收集几十张你自己的遥感图片用训练好的模型做半自动标注人工修正后补充进训练集进行增量训练。为什么强调增量训练因为标准数据集的场景和你的真实使用场景一定有差异光照条件、拍摄高度、传感器型号、地理区域直接拿标准数据集训练的模型上岗性能一定会打折扣。但通过半自动标注和增量训练你可以在极小的人工成本下把模型快速适配到自己的场景。7. 写在最后的实操心得我个人在实际操作中的体会是数据集的格式转换和预处理占据了一个目标检测项目三分之一左右的工作量。这份数据集中VOC和YOLO格式的成对提供帮你省掉的不仅仅是那几行转换代码更是大量容易出错的坐标踩坑时间。但即使数据已经做成了双格式也不要跳过数据检查那一步。见过太多人都把精力放在调模型结构上结果数据本身的质量问题让所有调参都变成无用功。再分享一个针对这个数据集的小技巧第一次训练时你把imgsz设为1024训练完后可以再用imgsz1280做一次fine-tune大概只训练30个epoch左右通常mAP还能再涨一到两个百分点。在大分辨率下用更小的学习率做精细调整是遥感目标检测里性价比很高的一手操作。另外训练完成后记得把推理结果可视化输出一批挑几个典型的错误案例漏检、误检、定位偏差大亲自分析一下原因。不要只看mAP数字因为mAP是统计指标不会告诉你模型具体错在哪里。我当时就通过可视化发现small-vehicle在阴影遮挡区域经常漏检于是专门多补了一些类似场景的样本做增量训练比单纯调整学习率效果明显得多。最后想说的是遥感目标检测这个方向数据质量决定模型上限。一个整理清晰、格式统一、类别合理的数据集能让你把更多时间花在真正有价值的算法设计和工程落地思考上而不是消耗在数据格式地狱里。希望这篇笔记能帮你少走一些弯路把时间省下来去做那些真正有意思的事情。本文还有配套的精品资源点击获取