darknet yolo v2 训练自己的数据

    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格式的标记文件,代码如下:

  1. import xml.etree.ElementTree as ET  
  2. import pickle  
  3. import os  
  4. from os import listdir, getcwd  
  5. from os.path import join  
  6.   
  7. TrainLabel_Dir = '/home/ubuntu/data/labels'  #XML所在目录  
  8.   
  9. def convert(size, box):  
  10.     dw = 1./size[0]  
  11.     dh = 1./size[1]  
  12.     x = (box[0] + box[1])/2.0  
  13.     y = (box[2] + box[3])/2.0  
  14.     w = box[1] - box[0]  
  15.     h = box[3] - box[2]  
  16.     x = x*dw  
  17.     w = w*dw  
  18.     y = y*dh  
  19.     h = h*dh  
  20.     return (x,y,w,h)  
  21.   
  22. if not os.path.exists('labels/'):  #生成的label放在label目录下  
  23.     os.makedirs('labels/')  
  24. for rootDir,dirs,files in os.walk(TrainLabel_Dir):  
  25.     for file in files:  
  26.         file_name = file.split('.')[0]  
  27.         out_file = open('labels/%s.txt'%(file_name),'w')  
  28.         in_file = open("%s/%s"%(rootDir,file))  
  29.         tree = ET.parse(in_file)  
  30.         root = tree.getroot()  
  31.         size = root.find('size')  
  32.         w = int(size.find('width').text)  
  33.         h = int(size.find('height').text)  
  34.           
  35.         for obj in root.iter('object'):  
  36.             xmlbox = obj.find('bndbox')  
  37.             b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))  
  38.             bb = convert((w,h), b)  
  39.             out_file.write("0" + " " + " ".join([str(a) for a in bb]) + '\n')     #我这里只有一类,所以类别只是0.  
  40.         out_file.close()    
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代码如下:

  1. import xml.etree.ElementTree as ET  
  2. import pickle  
  3. import os  
  4. from os import listdir, getcwd  
  5. from os.path import join  
  6.   
  7. TrainDir = '/home/ubuntu/data/train'  #训练文件所在目录  
  8.   
  9. out_file = open('train.txt','w')  #生成的txt文件  
  10. for root,dirs,files in os.walk(TrainDir):  
  11.     for file in files:  
  12.         out_file.write('%s/%s\n'%(root,file))  
  13. out_file.close()  
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

  1. cd <darknet_root>  
  2. make clean  
  3. make -j16  
cd <darknet_root>
make clean
make -j16

3. 训练

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

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

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

  1. ./darknet detector train cfg/voc.data cfg/yolo-voc.cfg darknet19_448.conv.23  
./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是下载的预训练模型。

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

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值