DOTAv1数据集格式:

'imagesource':imagesource 'gsd':gsd x1, y1, x2, y2, x3, y3, x4, y4, category, difficult x1, y1, x2, y2, x3, y3, x4, y4, category, difficult ...

imagesource: 图片来源   gsd: 分辨率 x1, y1, x2, y2, x3, y3, x4, y4:四边形的四个顶点的坐标 顶点按顺时针顺序排列,第一个起点为左上第一个点 category:实例类别 difficult:表示该实例是否难以检测(1表示困难,0表示不困难)

COCO转DOTA:

import json

import cv2

import numpy as np

import os

def calculate_rotated_bbox(poly):

"""将多边形坐标转换为旋转边界框"""

contour = np.array(poly).reshape((-1, 1, 2)).astype(np.float32)

rect = cv2.minAreaRect(contour)

box = cv2.boxPoints(rect)

return np.int0(box)

def coco_to_dota(coco_annotation_path, dota_annotation_folder, imagesource="Unknown", gsd="Unknown"):

"""将COCO格式的标注转换为DOTA格式,包括imagesource和gsd信息"""

# 类别ID到名称的映射

category_map = {

1: 'Class1',

2: 'Class2',

}

# 确保输出目录存在

if not os.path.exists(dota_annotation_folder):

os.makedirs(dota_annotation_folder)

# 读取COCO格式的JSON文件

with open(coco_annotation_path, 'r') as f:

coco_data = json.load(f)

# 遍历每个图像的标注

for image in coco_data['images']:

image_id = image['id']

image_filename = image['file_name']

dota_filename = os.path.splitext(image_filename)[0] + '.txt' # 去掉原始扩展名,添加.txt

dota_filepath = os.path.join(dota_annotation_folder, dota_filename)

with open(dota_filepath, 'w') as dota_file:

# 写入imagesource和gsd信息

# dota_file.write(f"'imagesource':{imagesource}\n'gsd':{gsd}\n")

# 找到当前图像的所有标注

for annotation in filter(lambda x: x['image_id'] == image_id, coco_data['annotations']):

if 'segmentation' in annotation:

for seg in annotation['segmentation']:

if type(seg[0]) is list: # 检查是否是多边形格式

seg = seg[0]

box = calculate_rotated_bbox(seg)

# 从映射中获取类别名称

category_name = category_map.get(annotation['category_id'], 'Unknown')

# 格式化DOTA标注

box_str = ' '.join(map(str, box.flatten().tolist()))

dota_annotation = f"{box_str} {category_name} 0\n"

dota_file.write(dota_annotation)

# 调用函数,转换COCO到DOTA

coco_annotation_path = 'instances.json'

dota_annotation_folder = 'dota'

coco_to_dota(coco_annotation_path, dota_annotation_folder)

标注可视化:

import cv2

import numpy as np

import os

def draw_rotated_box(img, box, label):

"""在图像上绘制旋转的边界框和标签。"""

points = np.int0(box)

cv2.drawContours(img, [points], 0, (0, 255, 0), 2) # 绘制旋转框

cv2.putText(img, label, tuple(points[0]), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1) # 添加文本标签

def visualize_dota_annotations(image_folder, annotation_folder, output_folder):

"""批量处理图像和DOTA标注文件,绘制旋转边界框和标签"""

# 确保输出文件夹存在

if not os.path.exists(output_folder):

os.makedirs(output_folder)

# 遍历图像文件

for img_filename in os.listdir(image_folder):

img_path = os.path.join(image_folder, img_filename)

if os.path.isfile(img_path) and img_filename.endswith(('.jpg', '.png')):

annot_filename = os.path.splitext(img_filename)[0] + '.txt'

annot_path = os.path.join(annotation_folder, annot_filename)

output_img_path = os.path.join(output_folder, img_filename)

# 读取图像

img = cv2.imread(img_path)

if img is None:

continue # 如果图像文件无法读取,则跳过

# 处理对应的标注文件

if os.path.isfile(annot_path):

with open(annot_path, 'r') as f:

lines = f.readlines()

# 跳过文件开头的imagesource和gsd信息

for line in lines[2:]: # 开始处理从第三行起的标注信息

parts = line.strip().split(' ')

if len(parts) < 9: # 跳过非标准行

continue

box = np.array([float(part) for part in parts[:8]]).reshape(4, 2)

label = parts[8] # 标签

draw_rotated_box(img, box, label)

# 保存绘制了旋转边界框的图像

cv2.imwrite(output_img_path, img)

# 路径配置

image_folder = 'images'

annotation_folder = 'dota'

output_folder = 'visual'

visualize_dota_annotations(image_folder, annotation_folder, output_folder)

推荐链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。