美文网首页caffe-深度学习
如何将rolabelImg工具制作的.xml文件转成MSRA-T

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

作者: 运动小爽 | 来源:发表于2018-03-26 12:21 被阅读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>
    

    其中:

    • cx, cy表示bndbox的中心点坐标(坐标系方向和一般的图像坐标系相同,左上角为原点,向右为x正方向,向下为y正方向);
    • h和w是字符块的高和宽;
    • angle是旋转角度信息,这里得注意,roLabelImg标注得到的旋转角度值规则:首先是画一个水平bndbox,此时的angle=0,如果你往顺时针方向旋转,得到的角度值是一个弧度单位的正值。按照这种思路,如果往逆时针方向旋转,得到的角度值应该是一个弧度单位的负值,但实际并不是这样,比如上面的例子,实际角度应该是往逆时针方向旋转了一小点,但得到的角度值=3.081593,也是正值?假设规定往逆时针方向旋转时角度为负,那么它的角度theta应该是:theta=angle-pi,只要注意这一点就没问题了。

    下面是我用来将上面这种近似水平的文本转换成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的格式。

    相关文章

      网友评论

      • IT人故事会:贵在坚持,么么哒!我也是个爱写文章的人
        IT人故事会:@运动小爽 哈哈 互相关注学习
        运动小爽:@IT人故事会 哈哈😄,这是我的笔记收到的第一条评论,“也”字用的不对,我是半个月前才开始写博客来记笔记的……很开心😅希望慢慢养成习惯

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

      本文链接:https://www.haomeiwen.com/subject/dnulcftx.html