Yolov3:win10下训练自己的数据(GPU版)(详细步骤)

时间:2024-03-15 10:57:36

版权声明:本文为博主原创文章,未经博主允许不得转载。https://mp.csdn.net/postedit/88577729

前言

      最近在做用yolov3进行目标识别,关于前期已经成功检测成功了,大家有兴趣的可以看我之前写的一篇博客:VS2015+opencv3.4.2+yolov3成功检测,这篇博客主要介绍如何训练自己的数据。训练的环境是:win10+GPU

      最后,如果有什么写得不对的地方,希望大家不吝赐教,谢谢!

第二章 训练自己的数据

2.1 制作自己的数据集

  2.1.1 下载labellmg

       点击这个直接下载:下载labellmg

  2.1.2 采集图片

       图片大小最好是416*416,这个方便后面作为网络的输入。我是用摄像头直接采集图片,下面是我写的程序,可以参考下,用VS2015调用opencv库写的。

#include<opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	VideoCapture cap(0);
	string name;
	int num = 1;
	while (1)
	{
		Mat image;
		cap >> image;
		imshow("image", image);
		waitKey(1);

		Mat image2;
		resize(image, image2, Size(416, 416));
		imshow("image2", image2);
		waitKey(1);

		if (!cap.isOpened())
		{
			cout << "don't open creama!" << endl;
		}
		char key = waitKey(1);
		if (key == 'a')
			break;
		if (key == 'q' || key == 'Q')
		{
			name = to_string(num++) + ".jpg";
			imwrite(name, image2);
		}
		
	}
	waitKey(30);
	return 0;
}

  2.1.3 标记图片

     当采集完图片后,就是用labellmg软件进行标记得到.xml文件和.txt文件。具体步骤如下:

       解压了之后,可以直接打开data文件夹,可以把采集的图片都添加进来,然后在predefined_classes.txt文件中添加自己需要标记的类别,一个类别一行。

      然后打开labellmg.exe

(1)打开一张图片

Yolov3:win10下训练自己的数据(GPU版)(详细步骤)

(2)进行标框,选择类别

Yolov3:win10下训练自己的数据(GPU版)(详细步骤)

 

Yolov3:win10下训练自己的数据(GPU版)(详细步骤)

(3)保存即可,就会得到对应的.xml文件。

(4)得到.txt文件。网上有很多方法是写一个python程序,运行下就有了,但是对于那个程序有很多地方需要修改路径,反正我是没有成功的,后来发现labellmg软件同样可以得到.txt文件,方法如下:

切换选择保存的格式为:YOLO即可,就会得到对应的.txt文件。

Yolov3:win10下训练自己的数据(GPU版)(详细步骤)

(5)最后得到的结果

Yolov3:win10下训练自己的数据(GPU版)(详细步骤)

2.2 整理数据集

    (1)在F:\darknet-master\scripts下创建一个新的文件夹:VOCdevkit文件夹。再在VOCdevkit文件夹下面分别创建这几个文件夹:

VOC2018文件夹          ------文件名称可以改

JPEGImages文件夹     -----存放所有的.jpg图片

(2)在VOC2018文件夹下创建这几个文件夹:

Annotations文件夹       -------存放所有的.xml文件

ImageSets文件夹        

Labels文件夹              --------存放所有的.txt文件

(3)在ImageSets文件夹下创建一个Main文件

Main文件夹

(4)在Main文件夹下创建两个.txt文本:train.txt、val.txt

train.txt        ------存放图片的名称,不带后缀,如下图所示

val.txt

 

Yolov3:win10下训练自己的数据(GPU版)(详细步骤)

这个写图片名,其实有个python程序可以直接生成,如下所示,记得修改到对应的路径。


import os

from os import listdir, getcwd

from os.path import join

if __name__ == '__main__':

    source_folder='F:\\darknet-master\\scripts\\VOCdevkit\\JPEGImages'

    dest='F:\\darknet-master\\scripts\\VOCdevkit\\VOC2018\\ImageSets\\Main\\train.txt' 

    dest2='F:\\darknet-master\\scripts\\VOCdevkit\\VOC2018\\ImageSets\\Main\\val.txt'  

    file_list=os.listdir(source_folder)       

    train_file=open(dest,'a')                 

    val_file=open(dest2,'a')                  

    for file_obj in file_list:                

        file_path=os.path.join(source_folder,file_obj) 

       

        file_name,file_extend=os.path.splitext(file_obj)

       

        file_num=int(file_name) 

        

        if(file_num<776):                     

            

            train_file.write(file_name+'\n')  

        else :

            val_file.write(file_name+'\n')    

    train_file.close()

val_file.close()

 

2.3 修改voc_label.py生成对应Main中train.txt和val.txt,记得修改对应的路径。

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

sets=[('2018', 'train'), ('2018', 'val')]  #这里需要修改成对应的Main中

classes = ["cup"]  #这里需要改成对应的类别,可以有多类


def convert(size, box):
    dw = 1./(size[0])
    dh = 1./(size[1])
    x = (box[0] + box[1])/2.0 - 1
    y = (box[2] + box[3])/2.0 - 1
    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)

def convert_annotation(year, image_id):
    in_file = open('G:\\darknet-master\\scripts\\VOCdevkit\\VOC%s\\Annotations\\%s.xml'%(year, image_id))
    out_file = open('G:\\darknet-master\\scripts\\VOCdevkit\\VOC%s\\labels\\%s.txt'%(year, image_id), 'w')
    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
        if cls not in classes or int(difficult)==1:
            continue
        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')

wd = getcwd()

for year, image_set in sets:
    if not os.path.exists('G:\\darknet-master\\scripts\\VOCdevkit\\VOC%s\\labels\\'%(year)):
        os.makedirs('G:\\darknet-master\\scripts\\VOCdevkit\\VOC%s\\labels\\'%(year))
    image_ids = open('G:\\darknet-master\\scripts\\VOCdevkit\\VOC%s\\ImageSets\\Main\\%s.txt'%(year, image_set)).read().strip().split()
    list_file = open('%s_%s.txt'%(year, image_set), 'w')
    for image_id in image_ids:
        list_file.write('%sG:\\darknet-master\\scripts\\VOCdevkit\\VOC%s\\JPEGImages\\%s.jpg\n'%(wd, year, image_id))
        convert_annotation(year, image_id)
    list_file.close()

os.system("cat 2018_train.txt 2018_val.txt  > train.txt")

然后运行,就会生成对应的2018_train.txt、2018_val.txt、train.txt

2.4 下载预先训练的权重

点击:darknet53.conv.74下载

2.5 整理所有的文件到对应的地方

其实最终我们只需要.jpg、.xml、2018_train.txt、2018_val.txt、darknet53.conv.74

(1)在F:\darknet-master\build\darknet\x64\data下创建两个文件夹:

obj文件夹             -----存放所有的.jpg图片和.xml文件

weights文件夹      -------存放训练后的权重文件

(2)对于2018_train.txt和2018_val.txt文件,我们用记事本打开,会发现就是图片的绝对路径而已,在这里需要修改成现在图片的路径,如下所示,其实在运行那个voc_lable.py时可以修改下图片的路径为这里的obj路径。

F:\darknet-master\build\darknet\x64\data\obj\1.jpg
F:\darknet-master\build\darknet\x64\data\obj\2.jpg
F:\darknet-master\build\darknet\x64\data\obj\3.jpg
F:\darknet-master\build\darknet\x64\data\obj\4.jpg
F:\darknet-master\build\darknet\x64\data\obj\5.jpg
F:\darknet-master\build\darknet\x64\data\obj\6.jpg
F:\darknet-master\build\darknet\x64\data\obj\7.jpg
F:\darknet-master\build\darknet\x64\data\obj\8.jpg
F:\darknet-master\build\darknet\x64\data\obj\9.jpg
F:\darknet-master\build\darknet\x64\data\obj\10.jpg

 (3)至于darknet53.conv.74文件直接放到F:\darknet-master\build\darknet\x64这个下面即可。

2.6 修改其他的文件

(1)修改voc.data

记住这里的voc.data是在F:\darknet-master\build\darknet\x64\data这下面的,做如下修改:

类别数为对应你想检测的类别,train和valid对应的路径,backup就是最后训练好的权重存放位置。

classes= 1
train  = data/2018_train.txt
valid  = data/2018_val.txt
names = data/voc.names
backup = data/weights

(2)修改yolov3-voc.cfg

记住这里的yolov3-voc.cfg是在F:\darknet-master\build\darknet\x64下的,做如下修改:

一共需要改三处,每处有两个地方需要修改,每次都是先修改[yolo]下的classes为对应的类别数,再修改[yolo]对应上面的[convolutional]下的filters为(classes+5)*3

[convolutional]
size=1
stride=1
pad=1
filters=18               #(classes+5)*3
activation=linear

[yolo]
mask = 3,4,5
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=1        #类别数
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1

(3)修改voc.names

记住这里的voc.names是在F:\darknet-master\build\darknet\x64\data下的,做如下修改:

写上自己需要检测的类别名即可,一行一个,我这里只有一个。

cup

2.7 开始训练

    我这里是在win10系统下进行训练的,所有打开cmd,cd F:\darknet-master\build\darknet\x64,到这个路径下,然后输入:

darknet.exe detector train data/voc.data yolov3-voc.cfg darknet53.conv.74 data/weights

这里需要等待很长时间,大概一百多次就会生成一个yolov3-voc_last.weights

2.8 测试

   测试就不跟大家多说了,主要就是为了生成权重文件,就已经大功告成了,剩下的就是效果的问题,效果好坏和数据集的大小还有训练迭代的次数有关系。