主要参考:
https://www.cnblogs.com/monologuesmw/p/13035442.html
多加了些制作数据集步骤、和必要的注释。只为自己记录使用。
1、
git clone https://github.com/AlexeyAB/darknet.git
解压后,如果硬件设备包含GPU加速,需要对makefile文件进行修改,修改后如下图所示。
cd到darknet文件夹下:
make # 或make -j8
下载权重
yolov4.weights: https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights
yolov4.conv.137: https://drive.google.com/open?id=1JKF-bdIklxOOVy-2Cr5qdvjgGpmGfcbp
使用与训练的权重进行测试:
./darknet detect cfg/yolov4.cfg yolov4.weights data/dog.jpg
好了。
2、数据集的制作。
参考:https://blog.csdn.net/gaohuazhao/article/details/60871886
首先,在
VOCdevkit\VOC2007
下创建者Annotations、ImageSets、JPEGImages这三个文件夹。
Annotations存放xml文件
ImageSets用于生成相关txt文件
JPEGImages存放图片
然后,准备好你的图片(注意图片的宽高要能被32整除),一般是按照数字顺序命名
使用labelImg对图片进行处理,生成相应的xml文件。
这里推荐python安装:https://github.com/tzutalin/labelImg
pip3 install labelImg
labelImg #启动
labelImg [IMAGE_PATH] [PRE-DEFINED CLASS FILE]
打开图片或者图片文件夹,
对目标物体进行画框
输入物体名称
点击保存就可以生成相应名字的xml数据
这是xml数据格式。
所有图片生成完成xml后,XML文件全部放入Annotations,图片全部放入JPEGImages
把整个VOCdevkit文件夹复制到linux下darknet目录下。(也就是之前的步骤是在windows上完成的,之后要在linux上)
linux下,在VOC2007目录新建test.py,写入:
import os
import random
trainval_percent = 0.1
train_percent = 0.9
xmlfilepath = 'Annotations'
txtsavepath = 'ImageSets\Main'
total_xml = os.listdir(xmlfilepath)
num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)
ftrainval = open('ImageSets/Main/trainval.txt', 'w')
ftest = open('ImageSets/Main/test.txt', 'w')
ftrain = open('ImageSets/Main/train.txt', 'w')
fval = open('ImageSets/Main/val.txt', 'w')
for i in list:
name = total_xml[i][:-4] + '\n'
if i in trainval:
ftrainval.write(name)
if i in train:
ftest.write(name)
else:
fval.write(name)
else:
ftrain.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
可能需要手动在ImageSets下,建立Main文件夹;执行test.py后,生成如下
train.txt中内容是所有图片的名字,如果有强迫症,可以起名字的时候用0补全:
在VOC2007目录下新建train_val_data.py,写入:
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=['train', 'val']#
classes = ['test'] # 这里是你自己的数据的类别
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)
def convert_annotation(image_id):
in_file = open(wd + '/Annotations/%s.xml'%(image_id))
out_file = open( wd + '/labels/%s.txt'%(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)
print(type(tree))
print('1111111111111111111')
print(w,h)
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))
print(b)
bb = convert((w,h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
if __name__=='__main__':
wd = getcwd()
wd = wd.replace('\\', '/')
for image_set in sets:
if not os.path.exists(wd + '/labels/'):
os.makedirs(wd + '/labels/')
image_ids = open(wd +'/ImageSets/Main/%s.txt' % image_set).read().strip().split()
list_file = open('%s.txt' % image_set, 'w')
for image_id in image_ids:
list_file.write(wd + '/JPEGImages/%s.jpg\n' % image_id)
convert_annotation(image_id)
list_file.close()
注意修改自己的类别,classes = ['test'] # 这里是你自己的数据的类别
然后会生成labels文件夹,和train.txt、val.txt三个。
labels是图片名字的txt文件,数据类似如下:
train.txt、val.txt,里面是图片的绝对路径:
其实最后训练用到的只有train.txt、val.txt、JPEGImages文件夹、labels文件夹。确保文件有数据,图片路径对就ok了。
制作完毕。
3、进阶接着:https://www.cnblogs.com/monologuesmw/p/13035442.html
这个博客的修改voc.data、yolov4-custom.cfg、voc.names三个文件步骤。
文件这几个参数的含义
Set batch size to 64 - batch size is the number of images per iteration
Set subdivisions to 12 - subdivisions are the number of pieces your batch is broken into for GPU memory.
max_batches to 2000 * number of classes
steps to 80% and 90% of max batches
change num_classes in all of the YOLO layers
change filters in all of the YOLO layers
开始训练
./darknet detector train cfg/voc.data cfg/yolov4-custom.cfg yolov4.conv.137 -gpus 0
内存不足时会被kill,所以需要修改batch/subdivisions数据
一批训练样本的样本数量,每batch个样本更新一次参数
batch/subdivisions作为一次性送入训练器的样本数量
如果内存不够大,将batch分割为subdivisions个子batch
上面这两个参数如果电脑内存小,则把batch改小一点,batch越大,训练效果越好
subdivisions越大,可以减轻显卡压力
修改batch=64,修改subdivisions=32(如果显卡是1050TI的,可以把batch设置为96,如果报内存不足,将batch改回64将,或者subdivisions设置为32)
可以增加虚拟内存。
查看磁盘空间
如果足够,参考博客增加虚拟内存:https://blog.csdn.net/zt1091574181/article/details/88910188
训练过程如下
完成后会在backup生成训练后权重:
选着一个进行测试就可以了。