darknet yolo v2 训练自己的数据

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q6324266/article/details/54375452

        darknet训练自己的数据,官方提供了一个训练VOC的例子,我们参照这个例子,来训练我们自己的数据。


1. 准备数据集

         首先我们应该准备好我们自己的数据集用于训练。要训练一个自己的网络,我们需要有训练集和测试集。在这里,我们建立两个文件夹train和val用于存放这两类数据。接下来,我们要做的是生成数据的标记文件,也就是目标在图片中的类别以及位置信息。

1.1 生成标记文件

生成yolo的标记文件应该遵循以下两个规则:

  1. 每个原图像都对应着一个标记文件,而且文件名都相同,比如图片的名字是1.jpg,那么对应这张图片的标记文件名称应该为1.txt。
  2. 每个标记文件中,内容应该是这样的<object-class> <x> <y> <width> <height>,其中<x> <y> <width> <height>是相对于图像宽高的比例。

知道了这两个规则之后,我们就可以定义我们的标记文件了。这里我已经有了VOC格式标记的XML文件,那么接下来我们使用python来生成YOLO格式的标记文件,代码如下:

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

TrainLabel_Dir = '/home/ubuntu/data/labels'  #XML所在目录

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)

if not os.path.exists('labels/'):  #生成的label放在label目录下
    os.makedirs('labels/')
for rootDir,dirs,files in os.walk(TrainLabel_Dir):
    for file in files:
        file_name = file.split('.')[0]
        out_file = open('labels/%s.txt'%(file_name),'w')
        in_file = open("%s/%s"%(rootDir,file))
        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'):
            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("0" + " " + " ".join([str(a) for a in bb]) + '\n')     #我这里只有一类,所以类别只是0.
        out_file.close()  

这样我们就生成了YOLO格式的标记文件了。如果按照上面的python代码,生成的标记文件在当前路径的label目录下。

用此方法分别生成train和val的标记文件

1.2 生成原图片绝对路径文件

在YOLO的训练中,还需要一个txt文件来记录所有待训练图片的绝对路径。即train文件夹下所有图片的绝对路径,python代码如下:

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

TrainDir = '/home/ubuntu/data/train'  #训练文件所在目录

out_file = open('train.txt','w')  #生成的txt文件
for root,dirs,files in os.walk(TrainDir):
    for file in files:
        out_file.write('%s/%s\n'%(root,file))
out_file.close()

用此方法分别生成train和val的txt文件。

1.3 将原图片和标记文件放在一起

YOLO是直接通过替换原图片绝对路径的后缀名来找到对应标记文件的。比如原图片的绝对路径为/home/ubuntu/data/train/1.jpg。则YOLO将会直接认为其对应的标记文件路径为/home/ubuntu/data/train/1.txt。所以,我们将之前1.1生成的标记文件放到对应的原图片目录下。


2. 修改文件


2.1 创建names文件

在YOLO主目录的data文件夹下,创建一个.names文件,文件名任意。比如mydata.names。在该文件中写入所有类别的名称,每一类占一行。比如我这里只检测行人这一类,那么只在第一行写上"person"即可。

2.2 修改data文件

接下来我们要做的是修改YOLO的cfg文件。在darknet的主目录下,进入cfg目录,找到voc.data打开,修改其中的内容

classes= 1           #训练数据的类别数目,我这里只有一类,所以这里是1
train  = <path-to-voc>/train.txt             #上面1.2步骤生成的train文件路径
valid  = <path-to-voc>2007_test.txt         #上面1.2步骤生成的val文件路径
names = data/voc.names                    #上面2.1步骤创建的names文件路径
backup = backup                       #这是训练得到的model的存放目录,建议自己修改。


2.3 修改cfg文件

如果你想应用yolo_voc.cfg网络来训练你的数据,那么你需要修改这个文件中的一些内容。

  1. [region]层中classes改成你的类别数,我这里只检测行人,所以我改成了classes=1.
  2. [region]层上方的[convolution]层中,filters的数量改成(classes+coords+1)*NUM。我这里改成了(1+4+1)*5=30.具体可以参考https://groups.google.com/forum/#!topic/darknet/B4rSpOo84yg

2.4 修改src/yolo.c文件

  1. 第13行改成 char *voc_names[] = {"person"};  //如果你是一类的话,就改成这样,如果你有多类,自己根据需求改。
  2. 第322行draw_detections函数中,最后一个参数由20改成你的类别数,我这里是1。
  3. 第354行demo函数中,倒数第三个参数由20改成你的类别数,我这里是1.
  4. 第17行改成 char *train_images = "<path-to-voc>/train.txt";     //上面1.2步骤生成的train文件路径
  5. 第18行改成 char *backup_directory = "/home/Ubuntu/Downloads/darknet-master/backup/";     //这个路径自己指定。
  6. 第121行改成 char *base = "/home/Ubuntu/Downloads/darknet-master/results/comp4_det_test_";   //这个路径自己指定。
  7. 第123行改成 list *plist = get_paths("<path-to-voc>/val.txt");  //上面1.2步骤生成的val文件路径
  8. 第209行改成 char *base = "/home/Ubuntu/Downloads/darknet-master/results/comp4_det_test_"; //这个路径自己指定
  9. 第210行改成 list *plist = get_paths("<path-to-voc>/val.txt"); //上面1.2步骤生成的val文件路径

2.5 修改src/yolo_kernels.cu文件

第62行draw_detections函数最后一个参数由20改成你的类别数,我这里是1.

2.6 修改src/detector.c文件

第368行改成 list *plist = get_paths("<path-to-voc>/train.txt");  #上面1.2步骤生成的train文件路径

第539行option_find_int函数的最后一个参数由20改成1.

2.7 重新编译darknet yolo

cd <darknet_root>
make clean
make -j16

3. 训练

所有的步骤都已经准备好了。最后就是训练了。为了加快训练速度,我们可以下载官方提供的预训练模型。下载地址为

curl -O http://pjreddie.com/media/files/darknet19_448.conv.23

最后,我们cd到darknet的主目录,输入下面的指令来进行训练

./darknet detector train cfg/voc.data cfg/yolo-voc.cfg darknet19_448.conv.23

这其中voc.data就是2.2中修改后的data文件,yolo-voc.cfg是网络结构文件,darknet19_448.conv.23是下载的预训练模型。

整个的训练时间比较长,慢慢等吧。。。。。


阅读更多

没有更多推荐了,返回首页