话不多说,先上代码
import os
import xml.etree.cElementTree as ET
class_code = {"person": 0, "bird": 1, "cat": 2, "cow": 3, "dog": 4, "horse": 5, "sheep": 6, "aeroplane": 7,
"bicycle": 8, "boat": 9, "bus": 10, "car": 11, "motorbike": 12, "train": 13, "bottle": 14,
"chair": 15, "diningtable": 16, "pottedplant": 17, "sofa": 18, "tvmonitor": 19}
"""
将VOC2012的xml标注文件转化为txt形式的标注文件,内容为图片名称、物体种类、中心点坐标、box宽高:
[图片名称 物体1的class_code 物体1中心点x 物体1中心点y 物体1box宽度 物体1box高度 物体2的class_code......]
类初始化时,参数为官方下载VOC2012数据解压后VOC2012文件夹地址
类实例化对象调用时,参数为:
1.存放txt目标文件夹地址
2.mode===>str类型:
"train":只转化VOC2012数据集下目标检测数据集的train集
"val":只转化VOC2012数据集下目标检测数据集的val集
"trainval":只转化VOC2012数据集下目标检测数据集的trainval集(train与val并集)
"all":转化VOC2012数据集下目标检测数据集,包括train、val、trainval各集
"""
class GetobjectdetectiondatafromVoc2012():
def __init__(self, base_root):
self.baseroot = base_root
def findobjectdetectiondatafromvoc2012(self): # 在VOC2012找到目标检测相关dataset划分并分类返回
allobjtxtlsit = []
obj_traintxtfile = os.path.join(self.baseroot, "ImageSets", "Main", "train.txt")
obj_valtxtfile = os.path.join(self.baseroot, "ImageSets", "Main", "val.txt")
obj_trainvaltxtfile = os.path.join(self.baseroot, "ImageSets", "Main", "trainval.txt")
allobjtxtlsit.append(obj_traintxtfile)
allobjtxtlsit.append(obj_valtxtfile)
allobjtxtlsit.append(obj_trainvaltxtfile)
# print(allobjtxtlsit)
datanames = {}
for txtfilename in allobjtxtlsit:
with open(txtfilename, "r") as f:
txtfiledirname = os.path.basename(txtfilename)
datanames[txtfiledirname] = f.readlines()
return datanames["train.txt"], datanames["val.txt"], datanames["trainval.txt"]
def __call__(self, target_dir, mode):
if os.path.exists(target_dir): # 存放新txt目标文件夹检测,若没有则创建
print("lables数据文件夹已存在:{}".format(target_dir))
else:
os.mkdir(target_dir)
print("lables数据文件夹已创立:{}".format(target_dir))
traindatanameslist, valdatanameslist, trainvaldatanameslist = self.findobjectdetectiondatafromvoc2012()
target_dataset = []
if mode == "train":
target_dataset.append(traindatanameslist)
elif mode == "val":
target_dataset.append(valdatanameslist)
elif mode == "trainval":
target_dataset.append(trainvaldatanameslist)
elif mode == "all":
target_dataset.append(traindatanameslist)
target_dataset.append(valdatanameslist)
target_dataset.append(trainvaldatanameslist)
order = ["train", "val", "trainval"]
txtfilename_index = 0
for mission in target_dataset:
picnum = 0
boxnum = 0
if mode == "all":
txtfilename = order[txtfilename_index]
else:
txtfilename = mode
for datanames in mission:
lable = []
lable.append(datanames[:-1] + ".jpg")
xml_file = os.path.join(self.baseroot, "Annotations", datanames[:-1] + ".xml")
tree = ET.parse(xml_file)
try:
for obj in tree.iter("object"):
lable.append(class_code[obj.findtext("name")])
xmin = int(obj.findtext("bndbox/xmin"))
ymin = int(obj.findtext("bndbox/ymin"))
xmax = int(obj.findtext("bndbox/xmax"))
ymax = int(obj.findtext("bndbox/ymax"))
cx = (xmin + xmax) / 2
cy = (ymin + ymax) / 2
w = xmax - xmin
h = ymax - ymin
lable.append(str(cx))
lable.append(str(cy))
lable.append(str(w))
lable.append(str(h))
boxnum += 1
except:
print(lable[0])
with open(os.path.join(target_dir, txtfilename + "_annotations.txt"), "a+") as f:
lable = [str(e) + " " for e in lable]
lable.append("\n")
f.writelines(lable)
picnum += 1
print("{}_labes.txt成功共转化{}张图片的标签,共计{}个物体框".format(txtfilename, picnum, boxnum))
txtfilename_index += 1
if __name__ == '__main__':
database_root = r"G:\AI data\VOCdevkit\VOC2012" # VOC2012数据文件夹地址
target_root = r"G:\Coding\yolov3\data\label_txt" # 存放txt文件地址
labletxtgentor = GetobjectdetectiondatafromVoc2012(database_root)
labletxtgentor(target_root, "all")
官方下载VOC2012数据后,VOC2012官方数据包下载解压后如图:
无需其他任何操作,简单调整参数后直接跑代码,结果:
此代码文章仅供免费学习使用,请勿用于个人商用,如果你觉得有用,请点个赞,谢谢。