Ultralytics YOLO OBB 数据集格式全解:YOLO OBB 标注规范、DOTA 格式转换与定向框训练实战
本篇技术指南以 Ultralytics 仓库中 OBB(Oriented Bounding Box,定向边界框)数据集文档为核心,系统讲解 YOLO OBB 标注格式、数据集 YAML 配置规范、DOTA 系列数据集的接入方式,以及如何用内置转换工具将 DOTA 原始标注一键转换为 YOLO OBB 格式。读完本文,你将能够独立完成 OBB 数据集的配置、格式转换与模型训练全流程。
1. 为什么需要 OBB 数据集格式
训练带有定向边界框的目标检测模型,要求数据集中的标注能够表达物体的任意朝向。传统轴对齐框(axis-aligned box)无法贴合航拍、卫星影像中旋转 90 度的飞机、船舶等目标,而 OBB 允许框体旋转以紧密贴合目标轮廓。Ultralytics YOLO 通过 task="obb" 的任务类型支持这一能力,在数据集加载层由 YOLODataset 中的标志位控制:
# ultralytics/data/dataset.py(L97-L99)
self.use_segments = task == "segment"
self.use_keypoints = task == "pose"
self.use_obb = task == "obb"
从源码结构看,只要任务类型被解析为 obb,数据管道就会切换到 OBB 专属的标签读取与增强分支(如 augment.py 中的 preserve_obb 逻辑,保证 mosaic、裁剪等增强后定向框的方向不被破坏)。
2. YOLO OBB 标注格式:四角点表示法
YOLO OBB 格式用四个角点坐标表示一个定向框,所有坐标均归一化到 0~1 区间,每行一个目标,格式为:
class_index x1 y1 x2 y2 x3 y3 x4 y4
其中 (x1,y1)~(x4,y4) 是顺时针或逆时针排列的四个顶点。值得注意的是,标注文件使用四角点,但 YOLO 内部处理损失与推理输出时采用 xywhr 格式——即边界框中心点 (x, y)、宽 w、高 h 以及旋转角 r。
一个包含 class 0 目标的 *.txt 标签文件示例:
0 0.780811 0.743961 0.782371 0.74686 0.777691 0.752174 0.776131 0.749758
两种表示法之间的相互转换由 utils/ops.py 中的两个函数完成:
xyxyxyxy2xywhr(ultralytics/utils/ops.py#L369):将四角点转为中心 + 宽高 + 旋转角的xywhr表示;xywhr2xyxyxyxy(ultralytics/utils/ops.py#L404-L433):将xywhr转回四角点,用于绘制与后处理。
在训练管道的标签构造阶段(augment.py#L2426-L2428),OBB 样本的 bboxes 字段就是通过 xyxyxyxy2xywhr 对多边形顶点计算得到的,注释明确说明"need to normalize obb in xywhr format for width-height consistency"(需要把 OBB 归一化为 xywhr 以保证宽高的方向一致性),这解释了为什么四角点标注最终会以带旋转角的参数化形式参与损失计算。
3. 数据集 YAML 配置格式
Ultralytics 框架使用 YAML 文件定义 OBB 数据集的路径、类别与下载来源。仓库自带的 ultralytics/cfg/datasets/dota8.yaml 是最简可用示例:
# DOTA8 dataset (8 images from the DOTAv1 split) by Ultralytics
# Example usage: yolo train model=yolov8n-obb.pt data=dota8.yaml
path: dota8 # dataset root dir
train: images/train # train images (relative to 'path') 4 images
val: images/val # val images (relative to 'path') 4 images
# Classes for DOTA 1.0
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
# Download script/URL (optional)
download: https://github.com/ultralytics/assets/releases/download/v0.0.0/dota8.zip
几点关键说明:
train、val、test三个字段均支持三种取值:目录路径、目录列表,或逐行列出图片路径的*.txt文件;*.txt清单中,以./开头的相对路径是相对于该 txt 文件所在目录解析的,而绝对路径或无./前缀的相对路径则按常规方式解析。清单文件非常适合"只训练目录的一个子集"、"跳过无标注图片"或"把多个来源合并为一个 split"等场景:
# dataset.yaml
path: datasets/dota8 # dataset root
train: train.txt # 可以是目录、目录列表 [images/a, images/b],或 *.txt 清单
val: val.txt
names:
0: plane
# train.txt(每行一个图片路径,可与 .yaml 同目录)
./images/im0.jpg
./images/im1.jpg
/data/shared/im2.jpg
- 仓库中还维护了完整 DOTA 版本的 YAML:DOTAv1.yaml、DOTAv1.5.yaml 与 dota128.yaml,首次训练时会自动从 Ultralytics 资源仓库下载数据(DOTAv1/1.5 约 2 GB)。
4. 训练 OBB 模型:Python 与 CLI 用法
数据集准备就绪后,可直接训练 OBB 模型。以下示例使用 DOTAv1 数据集从头创建 YOLO26n-OBB 模型:
from ultralytics import YOLO
# Create a new YOLO26n-OBB model from scratch
model = YOLO("yolo26n-obb.yaml")
# Train the model on the DOTAv1 dataset
results = model.train(data="DOTAv1.yaml", epochs=100, imgsz=1024)
等价的 CLI 命令(obb 子命令显式指定任务类型):
# Train a new YOLO26n-OBB model on the DOTAv1 dataset
yolo obb train data=DOTAv1.yaml model=yolo26n-obb.pt epochs=100 imgsz=1024
实战建议(与文档中各数据集页面的示例一致):
- 先跑小数据集做管线验证:
yolo obb train data=dota8.yaml model=yolo26n-obb.pt epochs=100 imgsz=640,DOTA8 仅 8 张图(4 训练 + 4 验证),下载体积约 1 MB,是 OBB 训练流水线的快速冒烟测试与 CI 检查的标准选择(参见 docs/en/datasets/obb/dota8.md); - 航拍目标通常较小且密集,DOTAv1 官方示例采用
imgsz=1024以保留小目标细节; - DOTA8 的 15 个类别继承自 DOTAv1(plane、ship、storage tank 等),完整 DOTA 版本类别数更多,见下一节。
5. 支持的数据集
仓库当前支持以下 OBB 数据集(详见 docs/en/datasets/obb/index.md 及各数据集分册):
| 数据集 | 说明 | 文档/配置 |
|---|---|---|
| DOTA-v1.0 | 2,806 张航拍图、188,282 个实例,15 个类别;train 1,411 / val 458 / test 937 | docs/en/datasets/obb/dota-v2.md |
| DOTA-v1.5 | 与 v1.0 相同图像,补充标注小于 10 像素的极小实例,新增 container crane 类别,共 403,318 个实例 | 同上 |
| DOTA-v2.0 | 11,268 张图像、1,793,658 个实例、18 个类别(新增 airport、helipad),含 Google Earth 与 GF-2 卫星影像 | 同上 |
| DOTA8 | DOTAv1 前 8 张子集(4 train + 4 val),约 1 MB,用于流程测试与 CI | docs/en/datasets/obb/dota8.md、dota8.yaml |
| DOTA8 Multispectral | 8 张、10 通道 TIFF 子集,用于多光谱 OBB 训练测试 | dota8-multispectral.yaml |
| DOTA128 | DOTA 128 张子集,全部放在 train 目录(train/val 共用),规模与多样性均衡 | docs/en/datasets/obb/dota128.md |
对于 DOTA 原始下载包(大图常超过 10,000 像素边长),需要先切片再喂给 YOLO。仓库提供 ultralytics/data/split_dota.py 中的 split_trainval / split_test 工具,可将多尺度(rates=[0.5, 1.0, 1.5])、带间隙(gap=500)的 1024×1024 重叠切片输出为标准 YOLO 目录结构(images/train、labels/train 等),切片结果可直接被数据集 YAML 引用:
from ultralytics.data.split_dota import split_test, split_trainval
# Split train and val set, with labels.
split_trainval(
data_root="path/to/DOTAv1.0/",
save_dir="path/to/DOTAv1.0-split/",
rates=[0.5, 1.0, 1.5], # multiscale
gap=500,
)
# Split test set, without labels.
split_test(
data_root="path/to/DOTAv1.0/",
save_dir="path/to/DOTAv1.0-split/",
rates=[0.5, 1.0, 1.5], # multiscale
gap=500,
)
6. 转换标注格式:DOTA 原始格式 → YOLO OBB 格式
DOTA 官方标注是每行"8 个像素坐标 + 类别名"的文本文件。Ultralytics 内置转换函数 convert_dota_to_yolo_obb(定义于 ultralytics/data/converter.py#L450-L539),一行调用即可完成转换:
from ultralytics.data.converter import convert_dota_to_yolo_obb
convert_dota_to_yolo_obb("path/to/DOTA")
结合源码可以明确它的输入/输出契约:
期望的输入目录结构:
DOTA
├─ images
│ ├─ train
│ └─ val
└─ labels
├─ train_original
└─ val_original
转换逻辑(逐行读原始标签):
- 每行需至少 9 个字段,第 9 个字段(
parts[8])是类别名,通过内置class_mapping映射为 0~17 的类别索引,覆盖 DOTA 全部 18 个类别(plane、ship、storage-tank、baseball-diamond、tennis-court、basketball-court、ground-track-field、harbor、bridge、large-vehicle、small-vehicle、helicopter、roundabout、soccer-ball-field、swimming-pool、container-crane、airport、helipad); - 前 8 个像素坐标按对应图片的宽高分别归一化(
convert_label中偶数索引除以图像宽、奇数索引除以图像高),并按 6 位有效数字(f"{coord:.6g}")写出,行格式即上文第 2 节的class_index x1 y1 x2 y2 x3 y3 x4 y4; - 仅处理
.png图像文件,同时遍历train与val两个阶段; - 输出写入
labels/train与labels/val目录(与原始*_original目录并列),保持与图片同名的*.txt标签文件,可直接被 YOLO 数据集加载。
注意:DOTAv1/1.5 数据仅限学术用途,商业使用需遵守 DOTA 数据集许可条款(参见 docs/en/datasets/obb/dota-v2.md 中的提示)。
7. 接入你自己的 OBB 数据集
如果你有自己的带定向框标注的数据,文档给出的接入路径是:
- 格式对齐:将标注转换为 YOLO OBB 四角点格式(每行
class_index x1 y1 x2 y2 x3 y3 x4 y4,坐标归一化到 0~1)。如果你的原始标注是 DOTA 风格文本,直接用convert_dota_to_yolo_obb即可;其他标注工具(Labelme、CVAT 等)的多边形/旋转框标注,可参照同一行式格式自行写出。 - 编写 YAML:在配置文件中声明数据集根目录、各 split 路径(目录/目录列表/
*.txt清单均可)与names类别映射。 - 训练:确认数据与格式无误后,按第 4 节的 Python/CLI 方式启动训练。
自定义数据集训练示例(Python 与 CLI 双版本):
from ultralytics import YOLO
# Create a new YOLO26n-OBB model from scratch
model = YOLO("yolo26n-obb.yaml")
# Train the model on the custom dataset
results = model.train(data="your_dataset.yaml", epochs=100, imgsz=640)
# Train a new YOLO26n-OBB model on the custom dataset
yolo obb train data=your_dataset.yaml model=yolo26n-obb.yaml epochs=100 imgsz=640
8. 常见问题(FAQ)
OBB 是什么,Ultralytics YOLO 如何表示它?
OBB 是允许旋转以贴合目标朝向的框标注,尤其适用于物体方向与图像轴不对齐的航拍/卫星场景。在 YOLO 中,落盘的标注是四角点(class_index x1 y1 ... x4 y4,0~1 归一化),而内部训练与推理则以 xywhr(中心点、宽、高、旋转角)计算损失与输出,两种表示可通过 utils/ops.py 中的 xyxyxyxy2xywhr / xywhr2xyxyxyxy 相互转换。
如何把已有的 DOTA 标签转成 YOLO OBB 格式?
调用 ultralytics/data/converter.py 的 convert_dota_to_yolo_obb("path/to/DOTA"),它会读取 labels/{train,val}_original 下的原始标注,归一化坐标后写出 labels/{train,val} 下的 YOLO OBB 标签(参考文档 docs/en/reference/data/converter.md)。
支持哪些 OBB 数据集?
DOTA-v1.0、DOTA-v1.5、DOTA-v2.0、DOTA8、DOTA8 Multispectral、DOTA128,以及任何符合 YOLO OBB 格式 + 自定义 YAML 的自研数据集。仓库内置 YAML 位于 ultralytics/cfg/datasets/ 目录(DOTAv1.yaml、DOTAv1.5.yaml、dota8.yaml、dota128.yaml、dota8-multispectral.yaml)。
OBB 训练流水线如何快速验证?
用 DOTA8(8 张图、约 1 MB)先跑一遍 yolo obb train data=dota8.yaml model=yolo26n-obb.pt epochs=100 imgsz=640,确认数据下载、标签解析、增强与损失计算全链路无错误后,再切换到 DOTAv1(imgsz=1024)等完整数据集训练。
9. 小结
OBB 数据集工作的三个关键约定值得记住:标注用四角点归一化坐标、内部用 xywhr 参数化、YAML 的 split 字段支持目录/列表/清单三种写法。配合 convert_dota_to_yolo_obb 与 split_dota 两个工具函数,从 DOTA 原始下载到可训练的 YOLO OBB 数据集只需要两条命令。完整参数说明可参见 docs/en/modes/train.md 与 OBB 任务文档 docs/en/tasks/obb.md。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00