voc旋转标注数据转dota类型

2023-05-16

voc旋转标注数据转dota类型

  • voc2dota.py
  • ListFilesToTxt.py
  • roxml_to_dota.py

在cv领域数据集的标注过程中,用labelImg工具我们可以对数据进行标注,标注生成的voc类型的xml框一般是如下格式:(bndbox)(x1,y1,x2,y2)

普通的xml标注

但是在标注的过程中,往往会遇到使用水平的矩形框无法完整地框出类别的特征的情况,这会导致无用特征的冗余。
在dota类型的标注中,就能解决这个问题:
我们可以定义三个类型的bbox:HBB,OBB,POLY
在这里插入图片描述
HBB由左上点和右下点表示。 HBB 的最后一个维度应该是 4。
OBB由中心点(x, y)、宽度(w)、高度(h) 和θ 表示。宽度是较长边的长度。高度是较短边的长度。Theta 是长边和 x 轴之间的角度。 OBB 的最后一个维度应该是 5。
POLY由四点坐标表示。这些点的顺序无关紧要,但相邻的点应该是POLY的一侧。 POLY的最后一个维度应该是8

很明显,普通的xml标注文件属于HBB类型。而在旋转目标检测中,我们如果用到labelImg2来标注旋转的矩形框:
在这里插入图片描述
以及他生成的xml标注文件:
在这里插入图片描述

很明显,格式产生了变化
(robndbox)(cx,cy,w,h)

为了统一使用,我们可以将两种格式的框统一转成dota格式的txt文件(也就是poly格式)

他的格式一般是这样:
在这里插入图片描述
————数字分别对应从左上角开始顺时针旋转的四个点坐标

接下来直接附上voc转dota的代码,适用于xml混合bndbox和robndbox的情况

voc2dota.py

import math
import shutil
import os
import numpy as np
import xml.etree.ElementTree as ET

dataset_dir = r'/home/xiaopeng/dataset/test_oriented/1/img'
ana_dir = r'/home/xiaopeng/dataset/test_oriented/1/xml'
save_dir = r'/home/xiaopeng/dataset/test_oriented/1/dota_txt'
train_img_dir = r'/home/xiaopeng/dataset/test_oriented/1/imgSets/test.txt' #txt文件保存的是所有文件的名称

f1 = open(train_img_dir, 'r')
train_img = f1.readlines()

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 rota(x, y, w, h, a):  # 旋转中心点,旋转中心点,框的w,h,旋转角
    x0, y0 = rotatePoint(x, y, x - w / 2, y - h / 2, -a)
    x1, y1 = rotatePoint(x, y, x + w / 2, y - h / 2, -a)
    x2, y2 = rotatePoint(x, y, x + w / 2, y + h / 2, -a)
    x3, y3 = rotatePoint(x, y, x - w / 2, y + h / 2, -a)
    return x0, y0, x1, y1, x2, y2, x3, y3  # 旋转后的四个点,左上,右上,右下,左下


for img in train_img:
    shutil.copy(os.path.join(dataset_dir, img[:-1] + '.jpg'),
                os.path.join(save_dir,  'images', img[:-1] + '.jpg'))

    xml_file = open(os.path.join(ana_dir, img[:-1] + '.xml'), encoding='utf-8')
    tree = ET.parse(xml_file)
    root = tree.getroot()
    with open(os.path.join(save_dir,  'labelTxt', img[:-1] + '.txt'), 'w') as f:
        for obj in root.iter('object'):
            cls = obj.find('name').text

            box = obj.find('robndbox')
            # print(box)
            if(box!=None): #xml for labelImg2
              x_c = float(box.find('cx').text)
              y_c = float(box.find('cy').text)
              h = float(box.find('h').text)
              w = float(box.find('w').text)
              theta = float(box.find('angle').text)

              bdx = rota(x_c, y_c, w, h, theta)
              # print(bdx)
              x1=bdx[0]
              y1=bdx[1]
              x2=bdx[2]
              y2=bdx[3]
              x3=bdx[4]
              y3=bdx[5]
              x4=bdx[6]
              y4=bdx[7]
              f.write("{} {} {} {} {} {} {} {} {} 0\n".format(str(x1), str(y1), str(x2), str(y2), str(x3), str(y3), str(x4), str(y4), cls))

            else:
                #xml for labelImg
                box1=obj.find('bndbox')
                xmin = int(box1[0].text)
                ymin = int(box1[1].text)
                xmax = int(box1[2].text)
                ymax = int(box1[3].text)
                f.write("{} {} {} {} {} {} {} {} {} 0\n".format(xmin,ymax,xmax,ymax,xmax,ymin,xmin,ymin,cls))

生成目录下所有文件名的txt文件代码:

ListFilesToTxt.py

def ListFilesToTxt(dir, file, wildcard, recursion):
    exts = wildcard.split(" ")
    for root, subdirs, files in os.walk(dir):
        for name in files:
            # name1=name.split(".")[0]
            for ext in exts:
                if (name.endswith(ext)):
                    file.write(name.split('.')[0] + "\n")
                    break
        if (not recursion):
            break


def Test():
    dir = "/home/xiaopeng/dataset/test_oriented/1/split_class/Rough yarn/img"
    outfile = "/home/xiaopeng/dataset/test_oriented/1/split_class/Rough yarn/test.txt"
    wildcard = ".txt .exe .dll .lib .jpg"

    file = open(outfile, "w")
    if not file:
        print("cannot open the file %s for writing" % outfile)
    ListFilesToTxt(dir, file, wildcard, 0)

    file.close()


if __name__ == '__main__':
     Test()

***———————————***2022.6.30更新
之前的voc转dota代码我自己用了之后觉得不好用,对于旋转角度比较小的情况,旋转框往往转换不出来。
在借鉴别人脚本的基础上,进行了改进,分享给大家。只需要下面一个脚本便可实现xml格式转dota格式:

roxml_to_dota.py

# 文件名称   :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):
    """
    修改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(xml_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 = '/home/xiaopeng/dataset/test_oriented/3/split/for-try (copy)'
    out_path = '/home/xiaopeng/dataset/test_oriented/3/split/try_txt/'
    # 想要生成的txt文件保存的路径,这里可以自己修改

    files = os.listdir(xml_path)
    for file in files:

        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('bndbox')
            x0 = int(float(box.find('x0').text))
            y0 = int(float(box.find('y0').text))
            x1 = int(float(box.find('x1').text))
            y1 = int(float(box.find('y1').text))
            x2 = int(float(box.find('x2').text))
            y2 = int(float(box.find('y2').text))
            x3 = int(float(box.find('x3').text))
            y3 = int(float(box.find('y3').text))
            file.write("{} {} {} {} {} {} {} {} {} 0\n".format(x0, y0, x1, y1, x2, y2, x3, y3, cls))
        file.close()
        print(output)


if __name__ == '__main__':
    # -----**** 第一步:把xml文件统一转换成旋转框的xml文件 ****-----
    dir = "/home/xiaopeng/dataset/test_oriented/3/split/for-try (copy)"  # 目录下保存的是需要转换的xml文件
    filelist = os.listdir(dir)
    for file in filelist:
        edit_xml(os.path.join(dir, file))

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

voc旋转标注数据转dota类型 的相关文章

  • 人工智能学习:PASCAL VOC数据集读取(6)

    PASCAL VOC是一个国际的计算机视觉挑战赛 xff0c 数据集包含了20个分类的3万多张图片 挑战赛及其数据集基础上涌现不少知名的目标检测模型如R CNN xff0c YOLO xff0c SSD等 可以通过下载和读取的方法载入PAS
  • 转化Foggy_Cityscapes数据集为voc和yolo格式用作目标检测

    目录 一 数据集下载 xff08 1 xff09 解压后文件夹目录 xff08 2 xff09 gtFine格式如下所示 xff1a 二 转换为VOC数据集格式 xff08 1 xff09 生成xml标签 xff08 2 xff09 将le
  • labelimg voc与yolo数据标签互转脚本

    xml2txt span class token keyword import span os span class token punctuation span path span class token keyword import s
  • voc旋转标注数据转dota类型

    voc旋转标注数据转dota类型 voc2dota pyListFilesToTxt pyroxml to dota py 在cv领域数据集的标注过程中 xff0c 用labelImg工具我们可以对数据进行标注 xff0c 标注生成的voc
  • (深度学习)yolo(txt)与voc(xml)格式相互转换脚本

    提供了两个用来将voc格式的xml文件相互转换的简单脚本 xff0c 修改一下class类和文件目录即可使用 voc转yolo xff1a xml2txt py span class token keyword import span os
  • 检测之YOLO转VOC

    文章目录 1 整理Yolo图像和标签文件2 实现yolo到voc的转换 检测系列相关文章参考如下链接 xff1a VOC数据的结构介绍及自定义生成 xff0c 用labelimg自已标注VOC标准数据的生成及分析 VOC易用labelimg
  • 检测之VOC转YOLO

    文章目录 检测所用数据有几种文件格式 xff0c 我们对于检测 xff0c 将使用VOC格式做为基础 xff0c 与其它格式的的互转实现部分如下 xff1a 检测系列相关文章参考如下链接 xff1a VOC数据的结构介绍及自定义生成 xff
  • YOLO格式 转为 旋转数据标注rolabelimg/labelimg2的VOC格式(集成主成分提取角度)

    之前用labelimg标注了七十张的yolo格式数据集 xff0c 但是现在要换识别的模型 xff0c 需要用到带有角度的VOC格式数据集 xff0c 传统VOC格式数据集包含的位置信息是 xff08 xmin ymin xmax ymax
  • yolov3的训练(五)darknet的VOC测试集和训练集以及训练前准备

    VOC测试集和训练集 同学们 xff0c 这个系列的文件不要直接就跟着我操作了 xff0c 因为这个是踩坑的记录 xff0c 不是教程 xff0c 我只是将整个流程记录下来 xff0c 让后面的同学操作的时候能够避开这些坑 xff0c 希望
  • 使用Python将DOTA数据集的格式转换成VOC2007数据集的格式

    一 VOC2007数据集二 DOTA数据集三 将DOTA数据集的格式转换成VOC2007数据集的格式 一 VOC2007数据集 VOC2007数据集的文件结构如下图所示 其中 xff0c 文件夹Annotations中存放的是图像的标注信息
  • 【笔记】从零开始制作自己的Pascal VOC数据集

    1 Pascal VOC 数据集简介 1 1 概要 图像分类和目标检测顶会论文的实验部分总是可以看到基于Pascal VOC数据集的算法结果分析 xff0c 它为图像分类 目标检测和图像分割都提供了优秀的数据支撑 xff0c 2005年到2
  • VOC数据集颜色表colormap与代码

    VOC颜色和分类的对于关系 code如下 xff0c 这里提供两个版本 xff0c 一个是list tuple 版本 xff0c 支持直接在opencv的color参数使用 xff1b 另一个是ndarray版返回 list 版 def v
  • PASCAL VOC数据集

    一 简介 PASCAL pattern analysis statistical modelling and computational learning VOC visual object classes 该挑战赛的竞赛项目主要包括 图像
  • 【labelme格式json转为labelimg格式的xml(VOC)】

    64 TOC readme 用labelme标注图片 xff0c 得到的是json格式文件 xff0c 有时候需要voc格式的数据 xff0c 可以使用以下转换脚本 xff0c 只需把文件路径替换 code span class token
  • 手把手实战教学!语义分割从0到1:一、数据集制作

    本篇博客 是 手把手实战教学 语义分割从0到1 系列的第一篇实战教学 将重点介绍语义分割相关数据集 以及如何制作自己的数据集 本系列总的介绍 以及其他章节的汇总 见 https blog csdn net oYeZhou article d
  • COCO数据集转VOC(提取自己需要的类)

    github https github com zcc720 COCO2VOC git 接上篇VOC数据集提取自己需要的类 这次我们依然从coco数据集中提取我们想要的类 并转为voc格式 用于目标检测 一 去官网下载数据集 train20
  • 目标识别数据集互相转换——xml、txt、json数据格式互转

    VOC数据格式与YOLO数据格式互转 1 VOC数据格式 VOC Visual Object Classes 是一个常用的计算机视觉数据集 它主要用于对象检测 分类和分割任务 VOC的标注格式 也被许多其他的数据集采用 因此理解这个数据格式
  • mAP的计算方法

    侵删 转载于 https blog csdn net hysteric314 article details 54093734 摘要 在训练YOLO v2的过程中 系统会显示出一些评价训练效果的值 如Recall IoU等等 为了怕以后忘了
  • PASCAL VOC数据集分析

    PASCAL VOC数据集分析 PASCAL VOC为图像识别和分类提供了一整套标准化的优秀的数据集 从2005年到2012年每年都会举行一场图像识别challenge 本文主要分析PASCAL VOC数据集中和图像中物体识别相关的内容 在
  • 目标检测数据集分析

    原文链接 https ghlcode cn pages 250d97 目标检测数据集分析 新增支持数据集可视化 Ghlerrix DataAnalyze 平时我们经常需要对我们的数据集进行各种分析 以便我们找到更好的提高方式 所以我将我平时

随机推荐