caffe-深度学习

如何将rolabelImg工具制作的.xml文件转成MSRA-T

2018-03-26  本文已影响136人  运动小爽

最近在使用RRPN模型来训练自己的数据集,旋转bounding box的标注工具使用的是roLabelImg。下面记录如何将roLabelImg标注得到的.xml文件转成MSRA-TD500格式。

MSRA-TD500的数据集标注格式特点

MSRA-TD500标注格式

每一张图片的label信息保存在一个文本文件中,每一行记录一个旋转bndbox信息,x,y值记录的是水平包围框的左上角顶点坐标;旋转角度值特点:未旋转时角度为0,顺时针旋转角度为正,逆时针旋转时角度为负,角度单位为弧度。

roLabelImg标注的.xml文件特点

比如针对下面这张图片(特点是文字方向近似水平):

近似水平的字符

使用roLabelImg标注得到的图中左上角的“CAIU"的label信息如下:

<robndbox>
      <cx>100.0</cx>
      <cy>79.5</cy>
      <w>134.0</w>
      <h>50.0</h>
      <angle>3.081593</angle>
    </robndbox>

其中:

下面是我用来将上面这种近似水平的文本转换成MSRA-TD500格式的python代码:

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

if __name__ == '__main__':
    #source_dir是存放.xml文件的文件夹
    source_dir = '/home/ys/pycaffe/RRPN_dataset/Annotations/type2/'
    #dst_dir是存放生成的文本文件的文件夹
    dst_dir = '/home/ys/pycaffe/RRPN_dataset/gt/'
    k = 0
    for file in os.listdir(source_dir):
        tree = ET.parse(source_dir + file)
        objs = tree.findall('object')
        num_objs = len(objs)
        boxes_list=[]
        for ix, obj in enumerate(objs):
            bbox = obj.find('robndbox')
            # Make pixel indexes 0-based
            # .xml中的cx,cy,w,h都是小数,应该强制类型转换成int,angle就是float,不用转
            cx = int(float(bbox.find('cx').text)) - 1
            cy = int(float(bbox.find('cy').text)) - 1
            w = int(float(bbox.find('w').text))
            h = int(float(bbox.find('h').text))
            angle = float(bbox.find('angle').text)
            #将.xml格式的中心点坐标转换成MSRA格式的左上角顶点坐标
            x = cx - int(w/2)
            y = cy - int(h/2)
            #使用round()将小数点位数保留6位
            if angle<1.57:
                theta = round(angle, 6)
            else:
                theta = round(angle - np.pi, 6)
            lines = str(ix) + ' 0 ' + str(x) + ' ' + str(y) + ' ' + str(w) + ' ' +str(h) + ' ' +str(theta) + '\n'
            boxes_list.append(lines)
        tmp = file.split(sep='.')
        #gt_name是要保存的文本格式的文件名
        gt_name = dst_dir + tmp[0] + '.gt'
        gt_file = open(gt_name, 'w')
        gt_file.writelines(boxes_list)
        gt_file.close()
        k+=1
    print('there are %d images in total' % int(k))
    print('done')

另外一种情形

当我们标注下面这种类型的图片时:

近似竖直方向的字符

此时,我们的标注方式可能就有所不同了:我们通常不是像上面的例子那样,画一个扁平的水平矩形,然后逆时针旋转一个超过90度的大角度,此时,往往我们的做法是画一个竖直方向细长的矩形,然后调整一个小角度。

这种情形和上面第一种情形相同吗?显然是不同的。在RRPN中,字符的宽w规定为长边,高h规定为短边,但是刚才说的这种标注方式得到的.xml信息是这样的:

<robndbox>
      <cx>43.5546</cx>
      <cy>157.4847</cy>
      <w>31.0</w>
      <h>292.0</h>
      <angle>3.061593</angle>
    </robndbox>

就是w变成的短边而h变成了长边。为了统一,针对这种类型的标注文件进行转换时需要重新修改一下转换python代码,下面是我使用的代码:

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

if __name__ == '__main__':
    #source_dir是存放.xml文件的文件夹
    source_dir = '/home/ys/pycaffe/RRPN_dataset/Annotations/type1/'
    #dst_dir是存放生成的文本文件的文件夹
    dst_dir = '/home/ys/pycaffe/RRPN_dataset/gt/'
    k = 0
    for file in os.listdir(source_dir):
        tree = ET.parse(source_dir + file)
        objs = tree.findall('object')
        num_objs = len(objs)
        boxes_list=[]
        for ix, obj in enumerate(objs):
            bbox = obj.find('robndbox')
            # Make pixel indexes 0-based
            # .xml中的cx,cy,w,h都是小数,应该强制类型转换成int,angle就是float,不用转
            cx = int(float(bbox.find('cx').text)) - 1
            cy = int(float(bbox.find('cy').text)) - 1
            w = int(float(bbox.find('w').text))
            h = int(float(bbox.find('h').text))
            angle = float(bbox.find('angle').text)
            # 这里需要注意,若要和MSRA-TD500中的标签格式统一,转换成左上角顶点坐标时,
            # cx应该减去长边h/2,cy应该减去短边w/2
            x = cx - int(h/2)
            y = cy - int(w/2)
            # 为了统一,w是长边,则w和h的值应该交换一下
            tmp = w
            w = h
            h = tmp
            # 同样,angle应该也要在第一种情况的基础上减去一个pi/2
            if angle<1.57:
                theta = round(angle - np.pi*0.5, 6)
            else:
                theta = round(angle - np.pi*1.5, 6)
            lines = str(ix) + ' 0 ' + str(x) + ' ' + str(y) + ' ' + str(w) + ' ' +str(h) + ' ' +str(theta) + '\n'
            boxes_list.append(lines)
        tmp = file.split(sep='.')
        gt_name = dst_dir + tmp[0] + '.gt'
        gt_file = open(gt_name, 'w')
        gt_file.writelines(boxes_list)
        gt_file.close()
        k+=1
    print('there are %d images in total' % int(k))
    print('done')

针对近似竖排字符,这样以上的处理才符合MSRA-TD500的格式。

上一篇下一篇

猜你喜欢

热点阅读