为yoov3_Tensorflow培训制作自己的VOC数据集,用于,YOLOV3TensorFlow,训练

发表时间:2020-09-14

一、数据集标注

我用的是labelme进行标注的。首先打开labelme——》Open Dir——》edit——》Creat Rectangle,之后就可以进行图片标注了。每张图片标注之后会形成一个对应的json文件,而json文件默认是保存在数据集目录下,也就是和图片混合存储在一个文件夹下。如下图所示:

图片标注完以后,需要将json文件转换为VOC数据集的xml格式,转换代码如下:

import os 
from typing import List, Any
import numpy as np 
import codecs 
import json 
from glob import glob 
import cv2 
import shutil 
from sklearn.model_selection import train_test_split
 
# 1.标签路径 
labelme_path = "F:/test_datas/2020_PlantPictures1/YOLO_2_data/"  # 原始labelme标注数据路径 
saved_path = "VOC2007/"  # 保存路径 
isUseTest=True#是否创建test集 

# 2.创建要求文件夹 
if not os.path.exists(saved_path + "Annotations"): 
    os.makedirs(saved_path + "Annotations") 
if not os.path.exists(saved_path + "JPEGImages/"): 
    os.makedirs(saved_path + "JPEGImages/") 
if not os.path.exists(saved_path + "ImageSets/Main/"): 
    os.makedirs(saved_path + "ImageSets/Main/") 

# 3.获取待处理文件 
files = glob(labelme_path + "*.json") 
files = [i.replace("\\","/").split("/")[-1].split(".json")[0] for i in files] 
print(files)
 
# 4.读取标注信息并写入 xml 
for json_file_ in files: 
    json_filename = labelme_path + json_file_ + ".json" 
    json_file = json.load(open(json_filename, "r", encoding="utf-8")) 
    height, width, channels = cv2.imread(labelme_path + json_file_ + ".jpg").shape 
    with codecs.open(saved_path + "Annotations/" + json_file_ + ".xml", "w", "utf-8") as xml: 
        xml.write('<annotation>\n') 
        xml.write('\t<folder>' + 'WH_data' + '</folder>\n') 
        xml.write('\t<filename>' + json_file_ + ".jpg" + '</filename>\n') 
        xml.write('\t<source>\n') 
        xml.write('\t\t<database>WH Data</database>\n') 
        xml.write('\t\t<annotation>WH</annotation>\n') 
        xml.write('\t\t<image>flickr</image>\n') 
        xml.write('\t\t<flickrid>NULL</flickrid>\n') 
        xml.write('\t</source>\n') 
        xml.write('\t<owner>\n') 
        xml.write('\t\t<flickrid>NULL</flickrid>\n') 
        xml.write('\t\t<name>WH</name>\n') 
        xml.write('\t</owner>\n') 
        xml.write('\t<size>\n') 
        xml.write('\t\t<width>' + str(width) + '</width>\n') 
        xml.write('\t\t<height>' + str(height) + '</height>\n') 
        xml.write('\t\t<depth>' + str(channels) + '</depth>\n') 
        xml.write('\t</size>\n') 
        xml.write('\t\t<segmented>0</segmented>\n') 
        for multi in json_file["shapes"]: 
            points = np.array(multi["points"]) 
            labelName=multi["label"] 
            xmin = min(points[:, 0]) 
            xmax = max(points[:, 0]) 
            ymin = min(points[:, 1]) 
            ymax = max(points[:, 1]) 
            label = multi["label"]
             if xmax <= xmin:
                 pass 
            elif ymax <= ymin: 
                pass 
            else: 
                xml.write('\t<object>\n') 
                xml.write('\t\t<name>' + labelName+ '</name>\n') 
                xml.write('\t\t<pose>Unspecified</pose>\n') 
                xml.write('\t\t<truncated>1</truncated>\n') 
                xml.write('\t\t<difficult>0</difficult>\n')
                xml.write('\t\t<bndbox>\n') 
                xml.write('\t\t\t<xmin>' + str(int(xmin)) + '</xmin>\n') 
                xml.write('\t\t\t<ymin>' + str(int(ymin)) + '</ymin>\n') 
                xml.write('\t\t\t<xmax>' + str(int(xmax)) + '</xmax>\n')
                xml.write('\t\t\t<ymax>' + str(int(ymax)) + '</ymax>\n') 
                xml.write('\t\t</bndbox>\n') 
                xml.write('\t</object>\n') 
                print(json_filename, xmin, ymin, xmax, ymax, label) 
        xml.write('</annotation>')
 
# 5.复制图片到 VOC2007/JPEGImages/下 
image_files = glob(labelme_path + "*.jpg") 
print("copy image files to VOC007/JPEGImages/") 
for image in image_files: 
    shutil.copy(image, saved_path + "JPEGImages/") 

# 6.split files for txt 
txtsavepath = saved_path + "ImageSets/Main/" 
ftrainval = open(txtsavepath + '/trainval.txt', 'w') 
ftest = open(txtsavepath + '/test.txt', 'w') 
ftrain = open(txtsavepath + '/train.txt', 'w') 
fval = open(txtsavepath + '/val.txt', 'w') 
total_files = glob("./VOC2007/Annotations/*.xml") 
total_files = [i.replace("\\","/").split("/")[-1].split(".xml")[0] for i in total_files] 
trainval_files=[] 
test_files=[] 
if isUseTest: 
    trainval_files, test_files = train_test_split(total_files, test_size=0.15, random_state=55) 
else: 
    trainval_files=total_files 
for file in trainval_files: 
    ftrainval.write(file + "\n") 
# split 
train_files, val_files = train_test_split(trainval_files, test_size=0.15, random_state=55) 
# train 
for file in train_files:
 
    ftrain.write(file + "\n") 
# val 
for file in val_files: 
    fval.write(file + "\n") 
for file in test_files: 
    print(file) 
    ftest.write(file + "\n") 
ftrainval.close() 
ftrain.close() 
fval.close() 
ftest.close()

转换后的结果如下图所示:

其中Annotation是存放的xml文件,JPEGImages中存放的是对应的原图,在ImageSets文件夹下有一个Main文件,是划分好的train.txt和test.txt文件等,内容如下图所示:

二、创建VOC数据集格式的文件夹

上面的步骤已经划分好了测试集和训练集,但是YOLOV3_TensorFlow的作者写的模型所需要的文件格式不是这样,因此需要用以下代码转换一次。

import os
from shutil import copyfile
#根据tarin.txt和test.txt将数据集分为标准数据集
train_text_path = 'VOC2007/ImageSets/Main/train.txt'
test_text_path = 'VOC2007/ImageSets/Main/test.txt'
#图片存放地址
image_path = 'VOC2007/JPEGImages'
#xml文件存放地址
xml_path = 'VOC2007/Annotations'

#输出的目录
outdir = 'hat_data'
#创建各级文件夹
test_xml_out = os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/Annotations')
os.makedirs(test_xml_out)
os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/ImageSets/Layout'))
os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/ImageSets/Main'))
os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/ImageSets/Segmentation'))
test_img_out = os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/JPEGImages')
os.makedirs(test_img_out)
os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/SegmentationClass'))
os.makedirs(os.path.join(outdir,'VOC/test/VOCdevkit/VOC2007/SegmentationObject'))
train_xml_out = os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/Annotations')
os.makedirs(train_xml_out)
os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/ImageSets/Layout'))
os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/ImageSets/Main'))
os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/ImageSets/Segmentation'))
train_img_out = os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/JPEGImages')
os.makedirs(train_img_out)
os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/SegmentationClass'))
os.makedirs(os.path.join(outdir,'VOC/train/VOCdevkit/VOC2007/SegmentationObject'))

with open(train_text_path) as f:
    lines = f.readlines()
    for i in lines:
        img_save_path = os.path.join(train_img_out,i.rstrip('\n')+'.jpg')
        xml_save_path = os.path.join(train_xml_out, i.rstrip('\n') + '.xml')
        copyfile(os.path.join(image_path,i.rstrip('\n')+'.jpg'),img_save_path)
        copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path)
        print(i)
with open(test_text_path) as f:
    lines = f.readlines()
    for i in lines:
        img_save_path = os.path.join(test_img_out, i.rstrip('\n') + '.jpg')
        xml_save_path = os.path.join(test_xml_out, i.rstrip('\n') + '.xml')
        copyfile(os.path.join(image_path, i.rstrip('\n') + '.jpg'), img_save_path)
        copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path)
        print(i)

在此之后会生成一个名为hat_data的文件夹,里面存储的才是我们真正使用的数据集格式。

最后一步,分别在test和train文件夹下运行一个split.py的脚本,终端运行命令如下:

python .\split.py F:\test_datas\hat_data\VOC\test\VOCdevkit\VOC2007

python .\split.py F:\test_datas\hat_data\VOC\train\VOCdevkit\VOC2007
import os
import random
import sys

if len(sys.argv) < 2:
    print("no directory specified, please input target directory")
    exit()

root_path = sys.argv[1]

xmlfilepath = root_path + '/Annotations'

txtsavepath = root_path + '/ImageSets/Main'

if not os.path.exists(root_path):
    print("cannot find such directory: " + root_path)
    exit()

if not os.path.exists(txtsavepath):
    os.makedirs(txtsavepath)

trainval_percent = 0.9
train_percent = 0.8
total_xml = os.listdir(xmlfilepath)
num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)

print("train and val size:", tv)
print("train size:", tr)

ftrainval = open(txtsavepath + '/trainval.txt', 'w')
ftest = open(txtsavepath + '/test.txt', 'w')
ftrain = open(txtsavepath + '/train.txt', 'w')
fval = open(txtsavepath + '/val.txt', 'w')

for i in list:
    name = total_xml[i][:-4] + '\n'
    if i in trainval:
        ftrainval.write(name)
        if i in train:
            ftrain.write(name)
        else:
            fval.write(name)
    else:
        ftest.write(name)

ftrainval.close()
ftrain.close()
fval.close()
ftest.close()

至此,YOLOV3_TensorFlow所要求的VOC训练数据集就算制作完成了。

文章来源互联网,如有侵权,请联系管理员删除。邮箱:417803890@qq.com / QQ:417803890

微配音

Python Free

邮箱:417803890@qq.com
QQ:417803890

皖ICP备19001818号-4
© 2019 copyright www.pythonf.cn - All rights reserved

微信扫一扫关注公众号:

联系方式

Python Free