第一步:安装darknet
参考:Windows搭建Darknet框架环境-Yolov4-GPU_乐观的lishan的博客-CSDN博客
darknet的源码说明中也已经简单介绍了如何利用数据集训练网络
第二步:制作VOC格式数据集
网上搜集自己需要的数据集,或自己拍摄相关视频,然后提取帧图片
大部分的网络公开数据集已经附带有标注好的xml文件
推荐交通领域公开数据集(包含无人驾驶、交通标志、车辆检测三大类)链接如下:【智能交通数据集】一文道尽智能交通领域数据集合集(一) - 飞桨AI Studio - 人工智能学习与实训社区
也有一部分数据集没有xml格式的标注文件,此时需要使用其他方法将其转换为xml文件
例如BITVehicle数据集提供的就是一个mat格式的标注文件,需要编写程序读取数据并生成对应图片的xml文件
对于没有标签的数据集或者是自己拍摄的数据集,需要使用labelimg工具进行标定,生成xml文件,使用pip安装命令即可安装
pip install labelimg
打开labelimg命令
labelimg
新建一个VOCdevkit文件夹,参照VOC数据集的目录分布建立其他子文件夹(此时文件夹内还没有文件)
-
将数据集所有图片放到JPEGImages文件夹
-
将所有图片对应的xml标注文件放到Annotations
-
生成txt相关文件放在Main文件夹下(利用gen_files.py文件)
文件来源于博客:Yolov4训练自己的数据集_sinat_28371057的博客-CSDN博客_yolov4训练自己的数据集
#!/usr/bin/env python # -*- coding: utf-8 -*- # file: gen_files.py # 生成训练所需txt文件 import os import random root_path = './VOCdevkit/VOC2007' xmlfilepath = root_path + '/Annotations' txtsavepath = root_path + '/ImageSets/Main' if not os.path.exists(root_path): print("cannot find such directory: " + root_path) exit() if not os.path.exists(txtsavepath): os.makedirs(txtsavepath) trainval_percent = 0.9 # 训练验证集占比 train_percent = 0.8 # 训练集占比 total_xml = os.listdir(xmlfilepath) num = len(total_xml) tv = int(num * trainval_percent) tr = int(tv * train_percent) trainval = random.sample(range(num), tv) train = random.sample(trainval, tr) print("train and val size:", tv) print("train size:", tr) ftrainval = open(txtsavepath + '/trainval.txt', 'w') ftest = open(txtsavepath + '/test.txt', 'w') ftrain = open(txtsavepath + '/train.txt', 'w') fval = open(txtsavepath + '/val.txt', 'w') for i in range(num): name = total_xml[i][:-4] + '\n' if i in trainval: ftrainval.write(name) if i in train: ftrain.write(name) else: fval.write(name) else: ftest.write(name) ftrainval.close() ftrain.close() fval.close() ftest.close()
-
生成最终的txt文件和label文件夹(利用voc_label.py文件)
文件来源于darknet下的scripts文件夹
#!/usr/bin/env python # -*- coding: utf-8 -*- # file: voc_label.py # 生成最终的txt文件和label文件夹 import xml.etree.ElementTree as ET import pickle import os from os import listdir, getcwd from os.path import join import platform sets = [('2007', 'train'), ('2007', 'val'), ('2007', 'test')] classes = ["Bus", "Microbus", "Minivan", "Sedan", "SUV", "Truck"] 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)) print("Processing image: %s" % image_id) convert_annotation(year, image_id) list_file.close() # if platform.system().lower() == 'windows': # os.system("type 2007_train.txt 2007_val.txt > train.txt") # os.system("type 2007_train.txt 2007_val.txt 2007_test.txt > train.all.txt") # elif platform.system().lower() == 'linux': # os.system("cat 2007_train.txt 2007_val.txt > train.txt") # os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt > train.all.txt") print("done")
-
复制2007_test.txt、2007_train.txt、2007_val.txt到data文件夹,搜索并复制darknet下的voc.data、voc.names到data文件夹
-
训练yolov4时,搜索并复制darknet下的yolov4.conv.137、yolov4-custom.cfg到data文件夹,若找不到,从网上下载
训练yolov4-tiny时,搜索并复制darknet下的yolov4-tiny.conv.29、yolov4-tiny-custom.cfg到data文件夹,若找不到,从网上下载
-
for
yolov4.cfg
,yolov4-custom.cfg
(162 MB): yolov4.conv.137 (Google drive mirror yolov4.conv.137 ) -
for
yolov4-tiny.cfg
,yolov4-tiny-3l.cfg
,yolov4-tiny-custom.cfg
(19 MB): yolov4-tiny.conv.29
备注:关于文件放置的路径可以自己决定,只要知道对应的文件代表的意义,在后续的配置过程中,指定正确的路径即可
-
第三步:配置网络结构和训练参数
-
xxx..names文件
训练类别名称指定:voc.names
替换为自己数据集的类别名称,一行一个,不要出现空行
-
xxx.data文件
数据路径文件指定:voc.data
classes:指定类别个数
train:指定训练数据集图片路径读取txt
valid:指定验证数据集图片路径读取txt
test:指定测试数据集图片路径读取txt
names:指定了类别名称读取文件
backup:指定训练权重保存文件路径
例如:
classes= 6 train = D:\DataSet\data/2007_train.txt valid = D:\DataSet\data/2007_val.txt test = D:\DataSet\data/2007_test.txt names = D:\DataSet\data/voc.names backup = D:\DataSet\data/backup
-
yoloxxx.cfg
训练网络参数配置:yolov4-tiny-custom.cfg
注意主要修改的几处:
[net]:
batch:批处理大小,显卡越强,此值可以设置高一点, 否则使用默认值,或适当降低
subdivisions:每一批次分成多少等份
[yolo]:
classes:类别数
anchors:预选框大小
备注:yolov4有3个yolo层,需要改三处,yolov4-tiny有2个yolo层,需要改两处
[convolutional]
filters:每一yolo层之上对应有一个convolutional,此值为:(类别数classes+5)X 3,假如类别数为6,则该值为33
备注:yolov4有3个yolo层,对应convolutional需要改三处,yolov4-tiny有2个yolo层,对应convolutional需要改两处
-
yoloxxx.conv.xx
yolov4的预训练权重文件:yolov4.conv.137
yolov4-tiny的预训练权重文件:yolov4-tiny.conv.29
-
创建backup文件夹
指定网络训练权重保存位置
第四步:训练
1、修改先验框
使用K-means算法计算最优先验框大小
darknet.exe detector calc_anchors data/obj.data -num_of_clusters 9 -width 416 -height 416
命令中data/obj.data为指定的xxx.data文件路径,数字9表示类别数目,例如:
D:\darknet\build\darknet\x64\darknet.exe detector calc_anchors data/voc.data -num_of_clusters 6 -width 416 -height 416
运行后会生成anchors.txt文件,复制文件内容,修改yoloxxx.cfg文件中的[yolo]下的anchors
2、启动训练命令
darknet.exe detector train data/obj.data yolo-obj.cfg yolov4.conv.137
命令中data/obj.data为指定的xxx.data文件路径,yolo-obj.cfg为指定的网络结构文件参数,yolov4.conv.137为预训练权重文件,例如:
D:\darknet\build\darknet\x64\darknet.exe detector train data/voc.data data/yolov4-tiny-custom.cfg data/yolov4-tiny.conv.29 -map