有两个博主,选转载好像不能弄,不要脸的选了原创
批量将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);