将 DOTA 数据集的标注转换为 COCO 格式

DOTA 数据集:http://captain.whu.edu.cn/DOTAweb/index.html
COCO 数据集:http://cocodataset.org/#download
COCO API:https://github.com/cocodataset/cocoapi
API make 报错,安装 Cython 即可

1
conda install cython

COCO 数据集简介

COCO 数据集包含 instance,keypoint 和 caption 等部分,本文只介绍 instance 相关内容

COCO 数据集的组织方式

coco
├── annos.txt (optional)
├── annotations
├── classes.txt (optional)
└── images

annotations 文件夹放数据集的标注文件(json格式),images 文件夹放数据集的所有图片,(annos.txt 放数据集的原始标注文件,class.txt 放标注的类别名称,每行一个类别,不含背景)

COCO 的数据标注格式

COCO 数据集以 json 文件格式存储数据集的标注信息,标注的格式可以参考 官网 和这个 知乎专栏,在这里就不重复了。

确定了标注的格式以后,分析 DOTA 数据集的标注格式,可以提取其中的信息然后以 json 格式存储下来就可以了

格式转换脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import json
import dota_utils as util
import os
from PIL import Image

info = {"description": "DOTA dataset from WHU", "url": "http://caption.whu.edu.cn", "year": 2018, "version": "1.0"}
licenses = {"url": "http://creativecommons.org/licenses/by-nc/2.0/", "id": 1, "name": "Attribution-NonCommercial License"}
categories = []
for i, catName in enumerate(util.wordname_15, start=1):
categories.append({"id": i, "name": "%s" % catName, "supercategory": "%s" % catName})

images = []
annotations = []
aug = "/home/lxy/dota/data/aug"
augmented = "/home/lxy/dota/data/augmented"
train_small = "/home/lxy/dota/data/train_small"
trainsplit_HBB = "/home/lxy/dota/data/trainsplit_HBB"
val_small = "/home/lxy/dota/data/val_small"
valsplit_HBB = "/home/lxy/dota/data/valsplit_HBB"
dataset_path = [augmented, train_small, trainsplit_HBB, val_small, valsplit_HBB]
imgid = 0
annid = 0
for path in dataset_path:
img_path = os.path.join(path, "images")
label_path = os.path.join(path, "labelTxt")
for file in os.listdir(label_path):
img_name = file.replace("txt", "png")
im = Image.open(os.path.join(img_path, img_name))
w, h = im.size
imgid += 1
images.append({"license": 1, "file_name": "%s" % img_name, \
"height": h, "width": w, "id": imgid})

f = open(os.path.join(label_path, file))
for line in f.readlines():
line = "".join(line).strip("\n").split(" ")
# a bbox has 4 points, a category name and a difficulty
if len(line) != 10:
print(path, file)
else:
annid += 1
catid = util.wordname_15.index(line[-2]) + 1
w_bbox = int(line[4][:-2]) - int(line[0][:-2])
h_bbox = int(line[5][:-2]) - int(line[1][:-2])
bbox = [line[0], line[1], str(w_bbox)+'.0', str(h_bbox)+'.0']
annotations.append({"id": annid, "image_id": imgid, "category_id": catid, \
"segmentation": [line[0:8]], "area": float(w_bbox*h_bbox), \
"bbox": bbox, "iscrowd": 0})

f.close()

my_json = {"info": info, "licenses": licenses, "images": images, "annotations": annotations, "categories": categories}

with open("/home/lxy/dota/data/coco/annotations/train.json", "w+") as f:
json.dump(my_json, f)
print("writing json file done!")

检查转换结果

这里需要用到 COCO API,具体用法参考 repo 里的 demo 文件,读取转换完成的数据集并显示标注结果,观察标注是否有误