0
点赞
收藏
分享

微信扫一扫

YOLO-批量将xml转换为txt和利用txt在原图上重现标注框

林肯公园_97cc 2022-03-12 阅读 72

有两个博主,选转载好像不能弄,不要脸的选了原创

批量将xml转换为txt

运行流程

1.你需要先把所有的.xml文件的文件名统一保存在一个txt文本中(批量的方法)
2.程序依次读取txt文本中的文件名,对xml文件进行处理
3.输出txt

目录结构

#AAA\ImageSets\Main\train.txt (存放所有的.xml文件名,不会批量点上面的链接)
#AAA\annotations\xmls.xml (所有的.xml文件)
#AAA\labels.txt (所有最后生成的.txt文件)
#AAA\train.txt (保存所有图片的路径)

#我根据原博主的代码修改的
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
# train.txt 就是ImageSets\Main 下对应的txt名称
sets=[('train')]

# classes 是所有类别名称,名称要与.xml里的对应
classes = ["D00",  "D01", "D10", "D11", "D20", "D30", "D44", "D43"]

#@params  size  图片宽高
#@params  box  groud truth 框的x y w h
def convert(size, box):
    dw = 1./size[0]              # 用于下面框的坐标和高宽归一化
    dh = 1./size[1]
    x = (box[0] + box[1])/2.0     # 求中心坐标
    y = (box[2] + box[3])/2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)

def convert_annotation(image_id):
    in_file = open('Czech_data/annotations/xmls/%s.xml'%(image_id))    # 读取 image_id 的xml文件
    out_file = open('Czech_data/labels/%s.txt'%(image_id), 'w')      # 保存txt文件地址
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')         # 读取图片 w h
    w = int(size.find('width').text)
    h = int(size.find('height').text)
    for obj in root.iter('object'):
        if obj.find('difficult'):
            difficult = float(obj.find('difficult').text)
        else:
            difficult = 0
        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 = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
        bb = convert((w,h), b) # w,h,x,y归一化操作
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')   # 一个框写入

wd = getcwd() # 获取当前地址

for image_set in sets:
    if not os.path.exists('Czech_data/labels/'): #不存在的话就会自动生成labels文件夹
        os.makedirs('Czech_data/labels/')
    image_ids = open('Czech_data/ImageSets/Main/%s.txt'%(image_set)).read().strip().split()  # 从记事本中获取图片名称列表
    list_file = open('Czech_data/%s.txt'%( image_set), 'w') 
    for image_id in image_ids:
        list_file.write('/Czech_data/images/%s.jpg\n'%( image_id))   # 写入所有图片的绝对路径(不知清楚有什么作用)
        convert_annotation(image_id)
    list_file.close()

将txt格式的标注框打印在原图上

文件目录

AAA\labels.txt (存放的所有txt)
AAA\images.jpg (存放的所有正常图片)
AAA\yuanbiaozhu.jpg (存放处理后的图片)
AAA\train.txt (存放保存图片名的txt)

import cv2

def show_labels_img(imgname):
    img = cv2.imread(DATASET_PATH + imgname + ".jpg")
    h, w = img.shape[:2]
    # print(w,h)
    label = []
    with open("D:\\AllProject\\bishe\\mat_txt\\Czech_data\labels\"+imgname+".txt",'r') as flabel:
        for label in flabel:
            label = label.split(' ')
            label = [float(x.strip()) for x in label]
            print(CLASSES[int(label[0])])
            pt1 = (int(label[1] * w-label[3] * w/2), int(label[2] * h-label[4] * h/2))
            pt2 = (int(label[1] * w+label[3] * w/2), int(label[2] * h+label[4] * h/2))
            cv2.putText(img,CLASSES[int(label[0])],pt1,cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255))
            cv2.rectangle(img,pt1,pt2,(0,0,255,2))

    cv2.imwrite("Czech_data/yuanbiaozhu/%s.jpg"%(imgname),img)
if __name__ == '__main__':
    CLASSES=['D00','D01','D10','D11','D20','D30','D43','D44']   #这里是类型
    DATASET_PATH="D:\\AllProject\\bishe\\mat_txt\\Czech_data\\images\\"
    image_ids = open('Czech_data/ImageSets/Main/train.txt').read().strip().split()  # 读取图片名称
    for image_id in image_ids:
        show_labels_img(image_id);

举报

相关推荐

0 条评论