Ubuntu下使用Yolov3训练自己的数据集
主要内容:
使用yolov3卷积神经网络训练自己的数据集,从而实现道路环境检测。主要检测的目标有三类,分别是行人、路坑以及道路上的石头。
目录
1.采集数据集
2.搭建训练环境
3.下载darknet源码
4.下载预训练模型
5.处理数据集
6.修改网络配置文件
7 . 训练模型
8. 训练注意的问题
1.采集数据集
采集含有目标物的图片,制作成数据集。数据集的数量尽可能的多,包含的场景尽量多,这样训练出的模型效果会更好。 使用labelme软件进行数据集的标注,可以标注多个类别。 最终的数据集格式是一张图片对应一个xml,数据格式如下图所示:所有图片存在一个文件夹,所有xml存在一个文件夹,且图片与xml一一对应。注意事项,图片的名称和标注的类别不能含有中文字符。
2.搭建训练环境
原本打算在虚拟机上训练,由于显卡驱动安装失败,放弃。选择装双系统:win10+Ubuntu16.04。本机GPU为gtx1650,官网找到对应显卡驱动并安装。配置cuda10.0和cudnn,opencv4.0。在配置cuda时注意,由于以及安装了显卡驱动,故有一项关于驱动的安装应选择NO。
3.下载darknet源码
终端输入命令
git clone https://github.com/pjreddie/darknet
进入到darknet目录,修改makefile文件。需要使能GPU,cudnn和opencv。安装opencv4.0版本,make时报错,显示不支持c++11。这里将不使能opencv。
修改cuda路径,即nvcc文件路径。
开始make编译,编译成功如下
4.下载预训练模型
wget https://pjreddie.com/media/files/darknet53.conv.74
./darknet detect cfg/yolov3.cfg darknet53.conv.74 data/dog.jpg
显示如下错误提示
终端输入,解决问题,我也不知道啥意思
export LD_LIBRARY_PATH="/usr/local/cuda-10.0/lib64"
继续以上操作,显示如下错误提示,显存不足
解决办法:
需要修改所使用的模型cfg文件中的subdivision的参数。
由subdivisions=8改成subdivisions=64。
subdivision:这个参数很有意思的,它会让你的每一个batch不是一下子都丢到网络里。而是分成subdivision对应数字的份数,一份一份的跑完后,在一起打包算作完成一次iteration。这样会降低对显存的占用情况。如果设置这个参数为1的话就是一次性把所有batch的图片都丢到网络里,如果为2的话就是一次丢一半。
cd cfg
gedit yolov3.cfg
继续之前操作,可以看到YOLO的运行结果。到这里,YOLOV3已经走通了,是时候开始加入自己的数据了。
5.处理数据集
5.1按照voc2007数据集格式制作文件夹,如下图所示。Annotatios为xml文件夹,JPEGImages为图片文件夹。
ImageSets里Main文件夹,用到4个文件:
-
train.txt 是用来训练的图片文件的文件名列表 ,约trainval的50%
-
val.txt是用来验证的图片文件的文件名列表 ,约trainval的50%
-
trianval.txt是用来训练和验证的图片文件的文件名列表 ,约整个数据集的50%
-
test.txt 是用来测试的图片文件的文件名列表 ,约整个数据集的50%
使用Matlab做VOC里的txt文件
clear;clc;
%%%%%%%%% 第一类检测目标pedestrian 制作TXT文件 %%%%%%%%%%%%%%%
file1 = dir('G:\My_Project\train_yolov3_bymyself\VOC2007\Annotations\pedestrian'); % pedestrian xml文件地址xml文件地址
path1 = 'G:\My_Project\train_yolov3_bymyself\VOC2007\ImageSets\Main\pedestrian'; % txt文件存放的地址
len1 = length(file1)-2;
num1_trainval=sort(randperm(len1, floor(1*len1/2))); %trainval集占所有数据的1/2,可以根据需要设置
num1_train=sort(num1_trainval(randperm(length(num1_trainval), floor(1*length(num1_trainval)/2)))); %train集占trainval集的1/2,可以根据需要设置
num1_val=setdiff(num1_trainval,num1_train); %trainval集剩下的作为val集
num1_test=setdiff(1:len1,num1_trainval);%剩下的作为test集
fid=fopen(strcat(path1, '_trainval.txt'),'a+');
for i=1:length(num1_trainval)
s = sprintf('%s',file1(num1_trainval(i)+2).name);
fprintf(fid,[s(1:length(s)-4) '\n']);
end
fclose(fid);
fid=fopen(strcat(path1, '_train.txt'),'a+');
for i=1:length(num1_train)
s = sprintf('%s',file1(num1_train(i)+2).name);
fprintf(fid,[s(1:length(s)-4) '\n']);
end
fclose(fid);
fid=fopen(strcat(path1, '_val.txt'),'a+');
for i=1:length(num1_val)
s = sprintf('%s',file1(num1_val(i)+2).name);
fprintf(fid,[s(1:length(s)-4) '\n']);
end
fclose(fid);
fid=fopen(strcat(path1, '_test.txt'),'a+');
for i=1:length(num1_test)
s = sprintf('%s',file1(num1_test(i)+2).name);
fprintf(fid,[s(1:length(s)-4) '\n']);
end
fclose(fid);
%%%%%%%%% 第二类检测目标chuckhole 制作TXT文件 %%%%%%%%%%%%%%%
file2 = dir('G:\My_Project\train_yolov3_bymyself\VOC2007\Annotations\chuckhole'); % chuckhole xml文件地址xml文件地址
path2 = 'G:\My_Project\train_yolov3_bymyself\VOC2007\ImageSets\Main\chuckhole'; % txt文件存放的地址
len2 = length(file2)-2;
num2_trainval=sort(randperm(len2, floor(1*len2/2))); %trainval集占所有数据的1/2,可以根据需要设置
num2_train=sort(num2_trainval(randperm(length(num2_trainval), floor(1*length(num2_trainval)/2)))); %train集占trainval集的1/2,可以根据需要设置
num2_val=setdiff(num2_trainval,num2_train); %trainval集剩下的作为val集
num2_test=setdiff(1:len2,num2_trainval);%剩下的作为test集
fid=fopen(strcat(path2, '_trainval.txt'),'a+');
for i=1:length(num2_trainval)
s = sprintf('%s',file2(num2_trainval(i)+2).name);
fprintf(fid,[s(1:length(s)-4) '\n']);
end
fclose(fid);
fid=fopen(strcat(path2, '_train.txt'),'a+');
for i=1:length(num2_train)
s = sprintf('%s',file2(num2_train(i)+2).name);
fprintf(fid,[s(1:length(s)-4) '\n']);
end
fclose(fid);
fi