数据集格式转换 ICDAR->VOC
文章目录- ICDAR2015数据集转换为VOC
- 简介
- 一、原数据和目标数据格式
- 二、格式转换过程
- 三、代码
- 四、最终效果
- 总结
简介
在做一个OCR项目,训练CTPN需要VOC格式的数据集,用手里的ICDAR2015格式的数据集做了一个转换。数据集是我自己的,和官方的ICDAR2015数据集内容不一样但标注格式是一样的,且为了方便这里没有分训练数据和测试数据,转换后的数据也是train和test在一起的,用的时候再划分。
一、原数据和目标数据格式
原数据集,即icdar2015格式的文件结构如下。
icdar_c4_train_imgs存放了1000张图片(我训练用的图片一共1000张),txt_1000-存放了对应的1000个txt文件。
icdar的txt标注格式示例:
目标数据集,即本次要转换的VOC格式的文件结构如下。这里Annotations存放处理好的1000份xml文件。
转换后的xml标注文件示例
转换流程:
将原图像移动到新目录->读取txt文件->写入xml
icdar标注格式:x1,y1,x2,y2,x3,y3,x4,y4,text
前面的8个float分别是标注框4个点的坐标。如图的gt1,gt2,gt3,gt4,假如原始标注是绿色框,那么要做的就是把它变成了横平竖直的框。因为这里我转换的是普通的不带旋转角度的VOC,标注只有xmin,xmax,ymin,ymax 4个数值,而icdar原始的标注框可以是任意方向的。因此需要对标注框的坐标做一个转换。
这里的转换方法是取xmin为四个点的横坐标中最小的,xmax为四个点的横坐标中最大的,然后下取整。纵坐标同理。
最终转换完成是图示蓝色框效果。
存在一个缺陷就是实际标注应该是红色框更加准确一些,我这样简单粗暴地取了最值会导致边框会比文字稍大,不过我的数据集大部分是TB商品图,水平文字占大多数。
如果是官方的icdar2015街景什么的倾斜文字比较多的情况可能需要转换成带倾斜角度的VOC格式,那个就是h, w, theta等;日后有需要再研究。
路径要改成自己的存放图像和标注文件的路径
#! /usr/bin/python
# coding:utf-8
import os, sys
import glob
from PIL import Image
import cv2
# target dir
base_dir = "../VOC" # target root dir
target_img_dir = base_dir + "/" + "JPEGImages/"
target_ann_dir = base_dir + "/" + "Annotations/"
target_set_dir = base_dir + "/" + "ImageSets/"
# source train dir
train_img_dir = "../datasets/icdar_c4_train_imgs/" # train image dir
train_txt_dir = "../datasets/txt_1000-/" # train txt dir
# test_img_dir = "../"
# test_txt_dir = "../ "
# rename and move img to target_img_dir
for file in os.listdir(train_img_dir):
os.rename(os.path.join(train_img_dir, file), os.path.join(target_img_dir, os.path.basename(file)))
# for file in os.listdir(test_img_dir):
# os.rename(os.path.join(test_img_dir, file),
# os.path.join(target_img_dir, "ICDAR2015_Test_" + os.path.basename(file)))
img_list = []
for file_name in os.listdir(target_img_dir):
img_list.append(file_name)
for idx in range(len(img_list)):
img_name = target_img_dir + img_list[idx]
stem, suffix = os.path.splitext(img_list[idx])
gt_name = train_txt_dir + stem + '.txt'
gt_obj = open(gt_name, 'r', encoding='utf-8')
gt_txt = gt_obj.read()
gt_split = gt_txt.split('n')
img = cv2.imread(img_name)
im = Image.open(img_name)
imgwidth, imgheight = im.size
# write in xml file
xml_file = open((target_ann_dir + img_list[idx].split('.')[0] + '.xml'), 'w')
xml_file.write('n')
xml_file.write(' VOC n')
xml_file.write(' ' + img_list[idx] + ' n')
xml_file.write(' n')
xml_file.write(' ' + str(imgwidth) + ' n')
xml_file.write(' ' + str(imgheight) + ' n')
xml_file.write(' 3 n')
xml_file.write(' n')
f = False
difficult = 0
for gt_line in open(gt_name, encoding='utf-8'):
gt_ind = gt_line.split(',')
if len(gt_ind) > 3:
# pt1, pt2, pt3, pt4为标签框的四个角坐标 dtxt为文字内容 这个参见icdar2015的txt数据格式
# 根据原始坐标求取xmin,xmax,ymin,ymax
xmin = int(min(float(gt_ind[0]), float(gt_ind[2]), float(gt_ind[4]), float(gt_ind[6])))
xmax = int(max(float(gt_ind[0]), float(gt_ind[2]), float(gt_ind[4]), float(gt_ind[6])))
ymin = int(min(float(gt_ind[1]), float(gt_ind[7]), float(gt_ind[3]), float(gt_ind[5])))
ymax = int(max(float(gt_ind[1]), float(gt_ind[7]), float(gt_ind[3]), float(gt_ind[5])))
dtxt = gt_ind[8]
if "###" in dtxt:
difficult = 1
else:
difficult = 0
xml_file.write(' n')
xml_file.write('')
# write info into target_set_dir
img_lists = glob.glob(target_ann_dir + '/*.xml')
img_names = []
for item in img_lists:
temp1, temp2 = os.path.splitext(os.path.basename(item))
img_names.append(temp1)
train_fd = open(target_set_dir + "/Main/trainval.txt", 'w', encoding='utf-8')
for item in img_names:
train_fd.write(str(item) + 'n')
转换好后生成的trainval.txt在./VOC/ImageSets/Main/中,根据个人的VOC目录格式可以稍作修改
四、最终效果一张图像及其对应的xml标注(labelImg打开):
由于是公司的图像因此只放了部分。终于不用人工打标注了红红火火恍恍惚惚。
VOC
TB1b5dBLXXXXXXeXVXXunYpLFXX.jpg
750
750
3
总结
主要问题就是bbox坐标转换这块,标注框会不太贴合文字,不知道会对训练CTPN有什么影响,如果有路过的大佬希望给点建议,谢谢!



