【YOLO】数据集处理训练自己的数据集

前端之家收集整理的这篇文章主要介绍了【YOLO】数据集处理训练自己的数据集前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1. 数据集

只训练了一类hand
首先我们需要对自己的数据集进行处理得到类似于voc的数据集:

import os
from os import listdir,getcwd
from os.path import join
if __name__ == '__main__':
    source_folder='/home/papa/Downloads/gesture/JPEGImages/'#地址是所有图片的保存地点
    #dest='/home/papa/Downloads/gesture/train.txt' #保存train.txt的地址
    #dest2='/home/papa/Downloads/gesture/val.txt' #保存val.txt的地址
    dest3='/home/papa/Downloads/gesture/trainval.txt'  #保存trainval.txt的地址
    file_list=os.listdir(source_folder)       #赋值图片所在文件夹的文件列表
    #train_file=open(dest,'a') #打开文件
    #val_file=open(dest2,'a') #打开文件
    trainval_file=open(dest3,'a')              #打开文件
    file_num=0
    for file_obj in file_list:                #访问文件列表中的每一个文件
        file_path=os.path.join(source_folder,file_obj) 
        #file_path保存每一个文件的完整路径
        file_name,file_extend=os.path.splitext(file_obj)
        #file_name 保存文件的名字,file_extend保存文件扩展名 
        if(file_num<12949): #and file_num%4!=0): #前面是你的图片数目,后面是为了保留文件用于训练
            #print file_num
            trainval_file.write(file_name+'\n')
            #train_file.write(file_name+'\n') #用于训练前900个的图片路径保存在train.txt里面,结尾加回车换行
        #else :
            #val_file.write(file_name+'\n') #其余的文件保存在val.txt里面
        file_num+=1
    #train_file.close()#关闭文件
    #val_file.close()
    trainval_file.close()

运行完是这样的:

我在这里费时最久,在结尾我再说一下我的问题,我们需要对官方生成label文件进行修改voc_label.py

如果你的xml文件也是这样的格式,可以按照下面的意见进行修改

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir,getcwd
from os.path import join

classes = ["aeroplane"] #对应里面的name,按照实际情况修改

#这个函数是voc自己的不用修改,在下面的函数调用
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) 

#生成标签函数,从xml文件提取有用信息写入txt文件
def convert_annotation(image_id):
    in_file = open('VOCdevkit/VOC/Annotations/%s.xml'%(image_id)) #Annotations文件夹地址
    out_file = open('VOCdevkit/VOC/labels/%s.txt'%(image_id),'w') #labels文件夹地址
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        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)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')

#主函数,从之前生成的train.txt/val.txt/trainval.txt获取文件名循环
image_ids = open('trainval.txt'(image_set)).read().strip().split() #之前生成的train.txt/val.txt/trainval.txt地址
#list_file = open('infrared_train.txt','w') #你希望的图片路径txt保存地址
for image_id in image_ids:
    #list_file.write('/VOCdevkit/VOC/JPEGImage/%s.jpg\n'%(image_id)) #你实际的图片路径,这句话是直接写入程序务必写对
    convert_annotation(image_id)
#list_file.close()

注意当你用trainval.txt时再运行函数convert_annotation(image_id)其他时候引掉,需要把这个程序运行三遍,分别对train.txt/val.txt/trainval.txt

此时我们会有标签生成了,格式与voc里的标签相同~

同时会生成infrared_train.txt,infrared_vol.txt

完成!!

2. 修改文件

  1. cfg/voc.data


    根据地址进行修改backup用于存放weights

  2. cfg/yolo_voc.cfg

    文件结尾,斜杠处需要修改,classes改为1,,filters值要进行修改,改成(classes+ coords+ 1)* (NUM) ,我的情况中:(1+4+1)* 5=30,我把filters 的值改成了30。

  3. data/gesture.names
    只有一行,hand

3. 训练

./darknet detector train cfg/gesture.data cfg/yolo-gesture.2.0.cfg darknet19_448.conv.23 | tee gesture.txt

也可以对结果进行评估啦~参照我的上篇文章http://www.jb51.cc/article/p-cqvczxuc-bpm.html

4. 我的问题

我的数据集是这种格式的,框是旋转的矩形,为了把它变成我需要的数据集,对生成标签程序进行了如下修改

import xml.etree.ElementTree as ET
import pickle
import os
import math
from os import listdir,getcwd
from os.path import join

def convert(size,Box):#voc_label.py 自带函数,没有修改
    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,h)

def convert_annotation(image_id):
    in_file = open('/home/papa/Downloads/gesture/Annotations/%s.xml'%(image_id))
    out_file = open('/home/papa/Downloads/gesture/labels2/%s.txt'%(image_id),'w') #与此xml对应的转换后的txt,这个txt的保存完整路径
    tree = ET.parse(in_file)
    hand = tree.find("hand") 
    w = 1920
    h = 1080
    cls_id = 0

    point1 = hand.attrib['leftup'].split(",")
    point2 = hand.attrib['rightup'].split(",")
    point3 = hand.attrib['rightdown'].split(",")
    point4 = hand.attrib['leftdown'].split(",")
    x1 = float(point1[0])
    x2 = float(point2[0])
    x3 = float(point3[0])
    x4 = float(point4[0])
    y1 = float(point1[1])
    y2 = float(point2[1])
    y3 = float(point3[1])
    y4 = float(point4[1])
    a = float(hand.attrib['rad'])

    x0 = (x3 - x1) * 0.5 + x1
    y0 = (y1 - y3) * 0.5 + y3
    xmax = (x2 - x0) * math.cos(a) + (y2 - y0) * math.sin(a) + x0
    ymax = (y2 - y0) * math.cos(a) - (x2 - x0) * math.sin(a) + y0
    xmin = (x4 - x0) * math.cos(a) + (y4 - y0) * math.sin(a) + x0
    ymin = (y4 - y0) * math.cos(a) - (x4 - x0) * math.sin(a) + y0

    b = (xmin,xmax,ymin,ymax)
    bb = convert((w,b)
    #print(bb)
    out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')

#image_ids = open('/home/papa/Downloads/gesture/ImageSets/Main/val.txt').read().strip().split()
image_ids = open('/home/papa/Downloads/gesture/ImageSets/Main/trainval.txt').read().strip().split()
#list_file = open('/home/papa/Downloads/gesture/infrared_val.txt','w')
for image_id in image_ids:
    #list_file.write('/home/papa/Downloads/gesture/JPEGImages/%s.jpg\n'%(image_id))
    convert_annotation(image_id)
#list_file.close()

直接让class等于0,并且自己输入数据的长宽,并对坐标进行处理得到需要的xmin等。有需要可以参考。

参考:

http://blog.csdn.net/hysteric314/article/details/54097845#comments

感谢作者!!

原文链接:https://www.f2er.com/xml/293894.html

猜你在找的XML相关文章