SSDD+的xml标签转DOTA的8参数标签;以及转JSON格式

DOTA和DIOR等其他数据集类似,转载+修改

# 修改者:TZF
# 文件名称   :roxml_to_dota.py
# 功能描述   :把rolabelimg标注的xml文件转换成dota能识别的xml文件,
#             再转换成dota格式的txt文件
#            把旋转框 cx,cy,w,h,angle,转换成四点坐标x1,y1,x2,y2,x3,y3,x4,y4
import os
import xml.etree.ElementTree as ET
import math


def edit_xml(xml_file, dotaxml_file):
    """
    修改xml文件
    :param xml_file:xml文件的路径
    :return:
    """
    tree = ET.parse(xml_file)
    objs = tree.findall('object')
    for ix, obj in enumerate(objs):
        x0 = ET.Element("x0")  # 创建节点
        y0 = ET.Element("y0")
        x1 = ET.Element("x1")
        y1 = ET.Element("y1")
        x2 = ET.Element("x2")
        y2 = ET.Element("y2")
        x3 = ET.Element("x3")
        y3 = ET.Element("y3")
        # obj_type = obj.find('bndbox')
        # type = obj_type.text
        # print(xml_file)

        if (obj.find('robndbox') == None):
            obj_bnd = obj.find('bndbox')
            obj_xmin = obj_bnd.find('xmin')
            obj_ymin = obj_bnd.find('ymin')
            obj_xmax = obj_bnd.find('xmax')
            obj_ymax = obj_bnd.find('ymax')
            xmin = float(obj_xmin.text)
            ymin = float(obj_ymin.text)
            xmax = float(obj_xmax.text)
            ymax = float(obj_ymax.text)
            obj_bnd.remove(obj_xmin)  # 删除节点
            obj_bnd.remove(obj_ymin)
            obj_bnd.remove(obj_xmax)
            obj_bnd.remove(obj_ymax)
            x0.text = str(xmin)
            y0.text = str(ymax)
            x1.text = str(xmax)
            y1.text = str(ymax)
            x2.text = str(xmax)
            y2.text = str(ymin)
            x3.text = str(xmin)
            y3.text = str(ymin)
        else:
            obj_bnd = obj.find('robndbox')
            obj_bnd.tag = 'bndbox'  # 修改节点名
            obj_cx = obj_bnd.find('cx')
            obj_cy = obj_bnd.find('cy')
            obj_w = obj_bnd.find('w')
            obj_h = obj_bnd.find('h')
            obj_angle = obj_bnd.find('angle')
            cx = float(obj_cx.text)
            cy = float(obj_cy.text)
            w = float(obj_w.text)
            h = float(obj_h.text)
            angle = float(obj_angle.text)
            obj_bnd.remove(obj_cx)  # 删除节点
            obj_bnd.remove(obj_cy)
            obj_bnd.remove(obj_w)
            obj_bnd.remove(obj_h)
            obj_bnd.remove(obj_angle)

            x0.text, y0.text = rotatePoint(cx, cy, cx - w / 2, cy - h / 2, -angle)
            x1.text, y1.text = rotatePoint(cx, cy, cx + w / 2, cy - h / 2, -angle)
            x2.text, y2.text = rotatePoint(cx, cy, cx + w / 2, cy + h / 2, -angle)
            x3.text, y3.text = rotatePoint(cx, cy, cx - w / 2, cy + h / 2, -angle)

        # obj.remove(obj_type)  # 删除节点
        obj_bnd.append(x0)  # 新增节点
        obj_bnd.append(y0)
        obj_bnd.append(x1)
        obj_bnd.append(y1)
        obj_bnd.append(x2)
        obj_bnd.append(y2)
        obj_bnd.append(x3)
        obj_bnd.append(y3)

        tree.write(dotaxml_file, method='xml', encoding='utf-8')  # 更新xml文件


# 转换成四点坐标
def rotatePoint(xc, yc, xp, yp, theta):
    xoff = xp - xc
    yoff = yp - yc
    cosTheta = math.cos(theta)
    sinTheta = math.sin(theta)
    pResx = cosTheta * xoff + sinTheta * yoff
    pResy = - sinTheta * xoff + cosTheta * yoff
    return str(int(xc + pResx)), str(int(yc + pResy))


def totxt(xml_path, out_path):
    # 想要生成的txt文件保存的路径,这里可以自己修改

    files = os.listdir(xml_path)
    num = len(files)
    for file in files:
        # trainval = random.sample(list, tv)
        # train = random.sample(trainval, tr)
        if '.ipynb_checkpoints' in file:
            num = num - 1
            print('error')
            continue

        tree = ET.parse(xml_path + os.sep + file)
        # root = tree.getroot()

        name = file.strip('.xml')
        output = out_path + name + '.txt'
        file = open(output, 'w')

        objs = tree.findall('object')
        for obj in objs:
            cls = obj.find('name').text
            box = obj.find('rotated_bndbox')
            x0 = int(float(box.find('x1').text))
            y0 = int(float(box.find('y1').text))
            x1 = int(float(box.find('x2').text))
            y1 = int(float(box.find('y2').text))
            x2 = int(float(box.find('x3').text))
            y2 = int(float(box.find('y3').text))
            x3 = int(float(box.find('x4').text))
            y3 = int(float(box.find('y4').text))
            file.write("{} {} {} {} {} {} {} {} {} 0\n".format(x0, y0, x1, y1, x2, y2, x3, y3, cls))
        file.close()
    print(num)


if __name__ == '__main__':
    # -----**** 第一步:把xml文件统一转换成旋转框的xml文件 ****-----
    # roxml_path = "./crack/roxml"  # 目录下保存的是需要转换的xml文件
    dotaxml_path = '../VOC/Annotations/'
    out_path = '../VOC/labels/'

    if not os.path.exists(out_path):
        os.mkdir(out_path)

    # filelist = os.listdir(roxml_path)
    # for file in filelist:
    #     edit_xml(os.path.join(roxml_path, file), os.path.join(dotaxml_path, file))

    # -----**** 第二步:把旋转框xml文件转换成txt格式 ****-----
    totxt(dotaxml_path, out_path)


附:DOTA数据的voc格式转JSON格式

import json
import os
import os.path as osp
import random

from PIL import Image

from dota_poly2rbox import poly2rbox_single_v2, poly2rbox_single


def parse_ann_info(img_base_path, label_base_path, img_name):
    lab_path = osp.join(label_base_path, img_name+'.txt')
    bboxes, labels, bboxes_ignore, labels_ignore = [], [], [], []
    with open(lab_path, 'r') as f:
        for ann_line in f.readlines():
            ann_line = ann_line.strip().split(' ')
            bbox = [float(ann_line[i]) for i in range(8)]
            # 8 point to 5 point xywha
            bbox = poly2rbox_single_v2(bbox)
            class_name = ann_line[8]
            difficult = int(ann_line[9])
            # ignore difficult =2
            if difficult == 0:
                bboxes.append(bbox)
                labels.append(class_name)
            elif difficult == 1:
                bboxes_ignore.append(bbox)
                labels_ignore.append(class_name)
    return bboxes, labels, bboxes_ignore, labels_ignore


def generate_txt_labels(src_path, out_path, trainval=True):
    """Generate .txt labels recording img_names
    Args:
        src_path: dataset path containing images and labelTxt folders.
        out_path: output txt file path
        trainval: trainval or test?
    """
    img_path = os.path.join(src_path, 'images')
    label_path = os.path.join(src_path, 'labelTxt')
    img_lists = os.listdir(img_path)
    with open(out_path, 'w') as f:
        for img in img_lists:
            img_name = osp.splitext(img)[0]
            label = os.path.join(label_path, img_name+'.txt')
            if(trainval == True):
                if(os.path.exists(label) == False):
                    print('Label:'+img_name+'.txt'+' Not Exist')
                else:
                    f.write(img_name+'\n')
            else:
                f.write(img_name+'\n')


def generate_json_labels(src_path, out_path, trainval=True):
    """Generate .json labels which is similar to coco format
    Args:
        src_path: dataset path containing images and labelTxt folders.
        out_path: output json file path
        trainval: trainval or test?
    """
    img_path = os.path.join(src_path, 'images')
    label_path = os.path.join(src_path, 'labelTxt')
    img_lists = os.listdir(img_path)

    data_dict = []

    with open(out_path, 'w') as f:
        for id, img in enumerate(img_lists):
            img_info = {}
            img_name = osp.splitext(img)[0]
            label = os.path.join(label_path, img_name+'.txt')
            img = Image.open(osp.join(img_path, img))
            img_info['filename'] = img_name+'.jpg'
            img_info['height'] = img.height
            img_info['width'] = img.width
            img_info['id'] = id
            if(trainval == True):
                if(os.path.exists(label) == False):
                    print('Label:'+img_name+'.txt'+' Not Exist')
                else:
                    bboxes, labels, bboxes_ignore, labels_ignore = parse_ann_info(
                        img_path, label_path, img_name)
                    ann = {}
                    ann['bboxes'] = bboxes
                    ann['labels'] = labels
                    ann['bboxes_ignore'] = bboxes_ignore
                    ann['labels_ignore'] = labels_ignore
                    img_info['annotations'] = ann
            data_dict.append(img_info)
        json.dump(data_dict, f)


if __name__ == '__main__':
    generate_json_labels('../DOTA_voc/train/',
                         '../DOTA_voc/train/train.json')
    generate_json_labels('../DOTA_voc/test/',
                         '../DOTA_voc/test/test.json', trainval=False)
    print('done!')

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SSDD(Scene Text Detection and Recognition)数据集换成Yolo格式需要以下步骤: 1. 下载和准备数据集:首先,从官方网站或相关资源中下载SSDD数据集。确保数据集中包含图像和相应的标注文件。将它们存储在合适的文件夹中。 2. 理解SSDD数据集的标注格式SSDD数据集标注文件通常是以XMLJSON格式存储的。该文件中包含了每张图像中的文本区域的坐标和标签等信息。 3. 解析标注文件:使用适当的解析工具(如Python中的xmljson解析库),读取标注文件,提取图像路径,文本区域的坐标和标签等信息。 4. 图像预处理:对于每张图像,进行必要的预处理,如调整大小、归一化或增强等操作。 5. 换为Yolo格式:根据Yolo的要求,将每个文本区域的坐标和标签换为Yolo格式。Yolo格式通常包含类别的索引、边界框中心点相对于图像宽度和高度的归一化值,以及边界框的宽度和高度相对于图像宽度和高度的归一化值。 6. 生成Yolo标签文件:将Yolo格式的信息保存到与对应图像相同的文件名的TXT文件中。每个文本区域的Yolo信息占据一行。 7. 拆分训练集和测试集:根据自己的需求,将数据集分为训练集和测试集,并分别创建包含图像路径和对应标签信息的TXT文件。 8. 配置Yolo模型:根据创建的数据集和标签文件的路径,修改Yolo模型的配置文件。设置类别的数量、路径和其他相关参数。 9. 训练和测试:通过使用修改后的Yolo模型配置文件,训练模型并在测试集上进行测试。 10. 验证结果:将模型检测到的文本区域的坐标和标签信息进行解析和验证,以确保换成功。 以上步骤提供了将SSDD数据集换为Yolo格式的一般过程。根据实际情况,可能需要进行一些适应性的调整和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值