使用yolov4训练模型详细步骤
下载yolov4
##使用git
git clone git@github.com:AlexeyAB/darknet.git
编译
打开Makefile这个文件
选择GPU=1
OPENCV=1
CUDNN=1
cd darknet
vim Makefile
make
测试
下载测试模型
cd darknet
#(注意:yolov4-weights的位置在darknet目录中)
wget https://oss.jaronnie.com/yolov4.weights
#或者直接在浏览器中输入https://oss.jaronnie.com/yolov4.weights
测试程序是否成功
./darknet detect cfg/yolov4.cfg yolov4.weights data/dog.jpg
训练自己的模型
准备好数据集(VOC格式)
创建四个文件夹(位置在darknet/scripts/VOCdevkit/VOC2020)
cd darknet/scripts
mkdir -p VOCdevkit/VOC2020
cd VOCdevkit/VOC2020
mkdir Annotations
mkdir -p ImageSets/Main
mkdir JPEGImages
mkdir labels
把原图片放在JPEGImages
标注后的文件放在Annotations
在同目录下创建test.py
在test.py中写下
import os
from os import listdir, getcwd
from os.path import join
if __name__ == '__main__':
source_folder='./JPEGImages/'
dest='./ImageSets/Main/train.txt'
dest2='./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<3000):
train_file.write(file_name+'\n')
else :
val_file.write(file_name+'\n')
train_file.close()
val_file.close()
执行python3 test.py
紧接着修改darknet/scripts目录下的voc_label.py
【注】修改classes即可
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=[('2020', 'train'), ('2020', 'val')]
classes = ["smoke"]
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('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
out_file = open('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('VOCdevkit/VOC%s/labels/'%(year)):
os.makedirs('VOCdevkit/VOC%s/labels/'%(year))
image_ids = open('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('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
convert_annotation(year, image_id)
list_file.close()
os.system("cat 2020_train.txt 2020_val.txt > train.txt")
修改yolov4配置文件
darknet/cfg/yolov4-voc.cfg
cd darknet/cfg
cp yolov4-customcfg yolov4-voc.cfg
修改头文件
vim yolov4-voc.cfg
# Testing
#batch=1
#subdivisions=1
# Training
batch=64 //每次迭代要进行训练的图片数量 ,在一定范围内,一般来说Batch_Size越大,其确定的下降方向越准,引起的训练震荡越小。
subdivisions=8 //源码中的图片数量int imgs = net.batch * net.subdivisions * ngpus,按subdivisions大小分批进行训练
height=416 //输入图片高度,必须能够被32整除
width=416 //输入图片宽度,必须能够被32整除
channels=3 //输入图片通道数
momentum=0.9 //冲量
decay=0.0005 //权值衰减
angle=0 //图片角度变化,单位为度,假如angle=5,就是生成新图片的时候随机旋转-5~5度
saturation = 1.5 //饱和度变化大小
exposure = 1.5 //曝光变化大小
hue=.1 //色调变化范围,tiny-yolo-voc.cfg中-0.1~0.1
learning_rate=0.001 //学习率
burn_in=1000
max_batches = 120200 //训练次数,建议设置为classes*2000,但是不要低于4000
policy=steps //调整学习率的策略
//根据batch_num调整学习率,若steps=100,25000,35000,则在迭代100次,25000次,35000次时学习率发生变化,该参数与policy中的steps对应
steps=40000,80000 // 一般设置为max_batch的80%与90%
scales=.1,.1 //相对于当前学习率的变化比率,累计相乘,与steps中的参数个数保持一致;
修改目标类别
修改三处classes
,分别位于970行、1058行与1146行,将其修改为自己数据集的目标数量;
classes=1 # 修改为自己需要检测的类别
修改filters
分别位于963行、1051行与1139行,将其修改为自己数据集的目标数量;
filters=18 #filters=(classes+5)*3
即18 = (1 + 5) * 3
filters = 18
修改cfg/voc.data
classes= 1 //修改为训练分类的个数
# 写darknet/scripts下2020_train.txt和2020_val.txt路径
train = /home/jay/darknet/scripts/2020_train.txt //修改为数据阶段生成的2020_train.txt文件路径
valid = /home/jay/darknet/scripts/2020_val.txt //修改为数据阶段生成的2020_val.txt文件路径
names = data/voc.names
backup = backup
修改data/voc.names
修改为自己类别的名称
smoke
开始训练
下载预训练模型
wget https://oss.jaronnie.com/yolov4.conv.137
训练模型命令
./darknet detector train cfg/voc.data cfg/yolov4-voc.cfg yolov4.conv.137