针对wizyoung版本的YOLOv3之xml文件转txt的Python代码及小问题解决

博客内容原创,仅供小白交流,转载可以不问出处~

此代码仅针对wizyoung的版本

wizyoung版本的代码要求txt内的jpg与bndbox信息安置格式如下:
jpg_index jpg_abs_path/jpg_name.jpg jpg_width jpg_height box_index xmin ymin xmax ymax box_index xmin ymin xmax ymax…

jpg_index图片编号从0开始
box_index类索引最小为0

附上py代码仅做参考

import xml.etree.ElementTree as ET
import os

sets = [('2019', 'train', 'train_list', 'train_l'), ('2019', 'val', 'val_list', 'val_l'),
        ('2019', 'test', 'test_list', 'test_l')]
        
classes = ['aeroplane','bicycle','bird','boat','bottle','bus','car','cat','chair','cow','diningtable','dog','horse','motorbike','person','pottedplant','sheep','sofa','train','tvmonitor']

def convert_annotation(year, image_id, list_file, jpg_label):
    in_file = open('my_imgs&labels/%s/labels/%s/%s.xml' % (year, jpg_label, image_id))
    tree = ET.parse(in_file)
    root = tree.getroot()
    xmlsize = root.find('size')
    d = (int(xmlsize.find('width').text), int(xmlsize.find('height').text))
    list_file.write(" " + " ".join([str(c) for c in d]))
    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (int(xmlbox.find('xmin').text), int(xmlbox.find('ymin').text), int(xmlbox.find('xmax').text),
             int(xmlbox.find('ymax').text))
        list_file.write(" " + str(cls_id) + " " + " ".join([str(a) for a in b]))
        
wd = os.getcwd()

for year, image_set, name_list, jpg_label in sets:
    data_base_dir = ("my_imgs&labels/%s/imgs/%s" % (year, image_set))
    file_list = []
    write_file_name = ('my_imgs&labels/%s/imgs/%s/%s.txt' % (year, image_set, name_list))
    write_file = open(write_file_name, "w")
    for file in os.listdir(data_base_dir):
        if file.endswith(".jpg"):
            index = file.rfind('.')
            file = file[:index]
            file_list.append(file)
    number_of_lines = len(file_list)
    for current_line in range(number_of_lines):
        write_file.write(file_list[current_line] + '\n')
    write_file.close()
    image_ids = open('my_imgs&labels/%s/imgs/%s/%s.txt' % (year, image_set, name_list)).read().strip().split()
    list_file = open('my_imgs&labels/%s/final_datas/%s.txt' % (year, image_set), 'w')
    line_ind = 0
    for image_id in image_ids:
        list_file.write('%d %s/my_imgs&labels/%s/imgs/%s/%s.jpg' % (line_ind, wd, year, image_set, image_id))
        convert_annotation(year, image_id, list_file, jpg_label)
        list_file.write('\n')
        line_ind += 1
    list_file.close()

说明:
train_list等文件为图片文件夹下所有的图片名列表txt文件且代码会自动生成此文件
train_l等文件为存放xml的文件夹

工程目录下我的文件夹布局:
my_imgs&labels总目录
2019分目录
分目录含:
imgs(存放图片)
labels(存放与图片对应的xml)
final_datas(存放xml转txt的三个结果文件)

这三个txt就是./data/my_data里面需要的三个文件
我之所以命名2019分目录是为了保持后面遇到新样本时可以复用这种文件夹结构
只不过就是复制改名而已
%s的地方仅为了遍历目录下的文件用
程序在%s处自动获取名称进行读写

参考wizyoung的GitHub链接:https://github.com/wizyoung/YOLOv3_TensorFlow

bndbox标注工具链接:https://github.com/tzutalin/labelImg
建议安装代码版本
在文件当前目录cmd命令载入python labelImg.py即可

PS:
在运行转换程序过程中会出现两处坐标值为浮点型错误
我的处理方法是选择人工输入整数坐标或者直接删除这两张信息
PSS:
在运行xml转txt中还发现train.txt存在xml文件读取object未成功的情况共8处
表现为object的确存在但并未读入txt内造成训练时assert断言报警
原因是这些行的数据个数不足9个

下面贴出代码运行检查是哪些行缺少object坐标信息
我的处理方式是查找出并删除

txt_path='./train/val/test.txt'
with open(txt_path,'r') as fileread:
    while 1:
    line=fileread.readline()
    if not line:
        break
    cur_line_num=line.strip().split(' ')
    if len(cur_line_num)<9:
        print(cur_line_num[0])

根据行数提示进入txt内进行处理
请注意这里是行号而不是图片名
over

你可能感兴趣的:(yolo,yolo,v3)