保姆级教程:手把手教你将DIOR遥感数据集转换成MMRotate可用的DOTA格式

张开发
2026/4/8 6:16:24 15 分钟阅读

分享文章

保姆级教程:手把手教你将DIOR遥感数据集转换成MMRotate可用的DOTA格式
从DIOR到MMRotate零失败遥感数据集格式转换实战指南当第一次接触遥感目标检测任务时数据集格式转换往往是新手遇到的第一个拦路虎。DIOR数据集作为遥感领域的重要基准数据集其标注格式与MMRotate框架默认支持的DOTA格式存在显著差异。本文将彻底解决这个痛点带你一步步完成从原始数据到训练就绪状态的完整转换。1. 环境准备与数据解构在开始转换前我们需要对DIOR数据集的结构有清晰认识。解压后的DIOR数据集通常包含以下核心目录DIOR/ ├── Annotations/ │ ├── Horizontal_Bounding_Boxes/ │ └── Oriented_Bounding_Boxes/ # 包含23463个XML标注文件 ├── ImageSets/ │ └── Main/ │ ├── train.txt │ ├── val.txt │ └── test.txt ├── JPEGImages-test/ # 测试集图片 └── JPEGImages-trainval/ # 训练验证集图片关键准备步骤创建Python虚拟环境推荐使用condaconda create -n dior2dota python3.8 -y conda activate dior2dota pip install xmltodict tqdm opencv-python验证数据集完整性import os print(fOriented XML数量: {len(os.listdir(DIOR/Annotations/Oriented_Bounding_Boxes))}) print(f训练图片数量: {len(os.listdir(DIOR/JPEGImages-trainval))})注意DIOR的Oriented Bounding Boxes使用旋转矩形标注每个对象由四个角点坐标表示这正是我们需要提取的关键信息。2. XML到DOTA格式的深度转换DOTA格式要求每个图片对应一个txt文件每行表示一个对象格式为x1 y1 x2 y2 x3 y3 x4 y4 class_name difficult以下是改进版的转换脚本增加了错误处理和进度显示import xml.etree.ElementTree as ET from tqdm import tqdm import os def convert_dior_to_dota(xml_dir, output_dir): os.makedirs(output_dir, exist_okTrue) error_count 0 for xml_file in tqdm(os.listdir(xml_dir)): if not xml_file.endswith(.xml): continue try: tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() lines [] for obj in root.findall(object): robndbox obj.find(robndbox) if robndbox is None: continue # 提取四个角点坐标 points [ robndbox.find(x_left_top).text, robndbox.find(y_left_top).text, robndbox.find(x_right_top).text, robndbox.find(y_right_top).text, robndbox.find(x_right_bottom).text, robndbox.find(y_right_bottom).text, robndbox.find(x_left_bottom).text, robndbox.find(y_left_bottom).text ] # 验证坐标有效性 if any(not p.replace(.,).isdigit() for p in points): error_count 1 continue class_name obj.find(name).text difficult obj.find(difficult).text lines.append( .join(points [class_name, difficult]) \n) # 写入转换后的文件 with open(os.path.join(output_dir, xml_file.replace(.xml, .txt)), w) as f: f.writelines(lines) except Exception as e: print(fError processing {xml_file}: {str(e)}) error_count 1 print(f转换完成共发现{error_count}处错误)常见问题排查坐标值缺失部分标注可能存在坐标点缺失脚本已添加基础验证内存不足处理大量文件时可分批次运行编码问题遇到非UTF-8编码文件时需在ET.parse中指定编码3. 数据集划分与结构调整DOTA格式要求特定的目录结构DIOR_processed/ ├── test/ │ ├── annfiles/ # 存放测试集标注文件 │ └── images/ # 存放测试集图片 └── trainval/ ├── annfiles/ # 存放训练验证集标注文件 └── images/ # 存放训练验证集图片自动化划分脚本import shutil from pathlib import Path def organize_dior_dataset(base_path): # 创建目录结构 splits [trainval, test] for split in splits: (Path(base_path)/fDIOR_processed/{split}/annfiles).mkdir(parentsTrue, exist_okTrue) (Path(base_path)/fDIOR_processed/{split}/images).mkdir(parentsTrue, exist_okTrue) # 处理标注文件 for split in splits: with open(f{base_path}/DIOR/ImageSets/Main/{split}.txt) as f: for img_id in f.read().splitlines(): # 复制标注文件 src_ann Path(f{base_path}/DIOR/Annotations/Oriented_Bounding_Boxes_processed/{img_id}.txt) dst_ann Path(f{base_path}/DIOR_processed/{split}/annfiles/{img_id}.txt) if src_ann.exists(): shutil.copy(src_ann, dst_ann) # 复制图片文件 img_src (Path(f{base_path}/DIOR/JPEGImages-test) if split test else Path(f{base_path}/DIOR/JPEGImages-trainval)) src_img img_src/f{img_id}.jpg dst_img Path(f{base_path}/DIOR_processed/{split}/images/{img_id}.jpg) if src_img.exists(): shutil.copy(src_img, dst_img)关键检查点文件数量一致性检查# 训练集 ls DIOR_processed/trainval/annfiles | wc -l ls DIOR_processed/trainval/images | wc -l # 测试集 ls DIOR_processed/test/annfiles | wc -l ls DIOR_processed/test/images | wc -l标注可视化验证import cv2 import matplotlib.pyplot as plt def visualize_annotation(img_path, ann_path): img cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB) with open(ann_path) as f: for line in f: parts line.strip().split() pts [(int(float(parts[i])), int(float(parts[i1]))) for i in range(0, 8, 2)] cv2.polylines(img, [np.array(pts)], True, (255,0,0), 2) plt.imshow(img) plt.show()4. MMRotate适配与配置优化完成格式转换后需要让MMRotate能够识别DIOR数据集。以下是关键配置步骤1. 创建数据集类在mmrotate/datasets/下新建dior.pyfrom .builder import ROTATED_DATASETS from .dota import DOTADataset ROTATED_DATASETS.register_module() class DIORDataset(DOTADataset): CLASSES (airplane, airport, baseballfield, basketballcourt, bridge, chimney, dam, Expressway-Service-area, Expressway-toll-station, golffield, groundtrackfield, harbor, overpass, ship, stadium, storagetank, tenniscourt, trainstation, vehicle, windmill) PALETTE [(165, 42, 42), (189, 183, 107), (0, 255, 0), (255, 0, 0), (138, 43, 226), (255, 128, 0), (255, 0, 255), (0, 255, 255), (255, 193, 193), (0, 51, 153), (255, 250, 205), (0, 139, 139), (255, 255, 0), (147, 116, 116), (0, 0, 255), (255, 69, 0), (128, 0, 128), (0, 128, 128), (218, 165, 32), (199, 21, 133)]2. 修改配置文件创建configs/_base_/datasets/dior.pydataset_type DIORDataset data_root data/DIOR_processed/ train_pipeline [ dict(typeLoadImageFromFile), dict(typeLoadAnnotations, with_bboxTrue), dict(typeRResize, img_scale(1024, 1024)), dict(typeRRandomFlip, flip_ratio0.5), dict(typeNormalize, mean[123.675, 116.28, 103.53], std[58.395, 57.12, 57.375]), dict(typePad, size_divisor32), dict(typeDefaultFormatBundle), dict(typeCollect, keys[img, gt_bboxes, gt_labels]) ] test_pipeline [...]3. 模型配置文件调整在模型配置文件中model dict( roi_headdict( bbox_headdict( num_classes20)))性能优化技巧使用prefetch加速数据加载data dict( traindict( pipelinetrain_pipeline, prefetchdict( img_norm_cfgdict( mean[123.675, 116.28, 103.53], std[58.395, 57.12, 57.375]))))多GPU训练配置optimizer dict(typeSGD, lr0.02/8, momentum0.9, weight_decay0.0001) data dict( samples_per_gpu4, workers_per_gpu4)5. 验证与调试技巧完成全部配置后建议按以下步骤验证1. 数据集完整性检查from mmrotate.datasets import build_dataset dataset build_dataset(cfg.data.train) print(f训练样本数: {len(dataset)})2. 数据增强可视化import mmcv from mmcv.visualization import imshow_det_bboxes for i in range(5): data dataset[i] img data[img].permute(1, 2, 0).numpy() gt_bboxes data[gt_bboxes].numpy() imshow_det_bboxes( img, gt_bboxes, None, class_namesdataset.CLASSES, showTrue)3. 常见错误解决方案错误类型可能原因解决方案KeyError: DIORDataset数据集类未注册检查__init__.py是否导入DIORDataset标注不匹配文件路径错误确认data_root和相对路径正确内存不足图片尺寸过大调整img_scale或减小batch_size4. 基准测试结果使用MMRotate的基准模型在DIOR上的预期性能模型mAP训练时间显存占用Rotated RetinaNet58.712小时10GBRotated Faster R-CNN62.315小时12GBRoI Transformer65.120小时14GB在实际项目中我们发现最大的挑战往往不是模型本身而是数据准备阶段。特别是在处理数万张遥感图像时一个自动化的健壮处理流程可以节省大量调试时间。建议将整个转换过程封装成可复用的脚本方便后续项目直接调用。

更多文章