win10+keras+yolo4训练自己的数据集
**
一、下载准备
1、(1)yolo4的github代码:https://github.com/Ma-Dan/keras-yolo4
(2)所准备数据集::Safety-Helmet-Wearing-Dataset;
github链接::https://github.com/njvisionpower/Safety-Helmet-Wearing-Dataset
(3)yolov4权重文件yolov4.weights(包含已转换完成的yolov4.h5文件,如果想偷懒可以直接将yolov4.h5文件放入keras-yolo4-master\model_data下,不需conver.py转换这一过程):
下载链接:链接:https://pan.baidu.com/s/1_HFT8f_K0LMQNiURMNA4kQ
提取码:nnz4
2、本人电脑试验环境:
python 3.7.4
tensorflow 1.14
keras 2.2.5
CUDA 10.0
cuDNN 7.5.x
二、数据集准备及处理
数据集格式为VOC2028,可参考链接文章对自己数据集进行修改,已有很多博文解析了制作VOC格式数据集的方法,参考如下:目标检测数据集制作流程
身为小白的自己,在此列出各位大哥们需要注意的地方,防止后续运行报错
1、路径问题
keras-yolo4-master文件夹内 VOCdevkit用于存放你自己记的VOC数据集

2. VOC2028中,Annotation文件夹下xml,是Labelimage运行后生成的xml文件,需要包含正确的path,filename,且不得包含非法字符(比如汉字)
!!!若path,filename有误,可以参考如下代码进行修改(注意写入自己的路径)
该代码引用自博主Jack_0601 ,在此表示感谢,原文链接如下:python批量修改xml文件path与filenames
'''
修改xml中的路径path
'''
import xml.dom.minidom
import os
path = r'E:\models\VOCdevkit\VOC2028\Annotations' # xml文件存放路径
sv_path = r'E:\models\VOCdevkit\VOC2028\Annotations' # 修改后的xml文件存放路径
files = os.listdir(path)
cnt = 1
for xmlFile in files:
dom = xml.dom.minidom.parse(os.path.join(path, xmlFile)) # 打开xml文件,送到dom解析
root = dom.documentElement # 得到文档元素对象
item = root.getElementsByTagName('path') # 获取path这一node名字及相关属性值
for i in item:
i.firstChild.data = 'E:\\models\\keras-yolo3-helmet\\VOCdevkit\\VOC2028\\JPEGImages' + str(cnt).zfill(6) + '.jpg' # xml文件对应的图片路径
3、(1)若Main文件夹下为空,
则在VOC2028文件夹里新建test.py,运行代码将会在Main文件夹里生成train.txt,val.txt,test.txt和trainval.txt四个文件。代码如下:
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()
(2)VOC2028\ImageSets\Main中包含以下4个文件,其中,test.txt不是必要,但最好要有

三、准备工作
1、权重转换convert.py
keras所用权重为.h5文件,因此需要转化yolov4.weights格式。利用convert.py代码将yolov4.weights权重转化为keras所需yolov4.h5权重文件,代码位于keras-yolo4-master/convert.py,具体流程如下
1、下载本文开头所发链接中yolov4.weights权重文件
2、yolov4.weights移动至keras-yolo4-master文件目录下
3、运行python convert.py即可

4、将keras-yolo4-master文件目录下生成的yolov4.h5移动至keras-yolo4-master\model_data
2、voc_annotation
1、(1)修改voc_annotation.py,将sets修改为自己数据集的名称,classes修改为自己的类别。
我的数据集路径为:E:\models\keras-yolo4-master\VOCdevkit\VOC2028,且voc_annotation.py文件位于E:\models\keras-yolo4-master下。
(2)可能会报错路径错误,原voc_annotation.py文件代码中路径与我的不一致,我修改了in_file=open(xxx);image_ids=open(xxx) ;list_file=open(xxx) 这几行代码,修改为自己的路径。在此贴出自己的代码,以作参考
import xml.etree.ElementTree as ET
# xml.etree.ElementTree 实现了解析和创建xml数据的简单高效API
from os import getcwd
sets=[('2028', 'train'), ('2028', 'val'), ('2028', 'test')]
classes = ["person", "hat"]
def convert_annotation(year, image_id, list_file):
in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
# 从文件读取数据
tree=ET.parse(in_file)
root = tree.getroot()
'''
从字符串读取数据
root=ET.fromstring(xml_data_as_string)
'''
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 = (int(xmlbox.find('xmin').text), int(xmlbox.find('ymin').text), int(xmlbox.find('xmax').text), int(xmlbox.find('ymax').text))
list_file.write(" " + ",".join([str(a) for a in b]) + ',' + str(cls_id))
wd = getcwd()
for year, image_set in sets:
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'%(wd, year, image_id))
convert_annotation(year, image_id, list_file)
list_file.write('\n')
list_file.close()
2、运行voc_annotation.py 生成三个txt文件在keras-yolo4-master/目录下,如下图所示
3、分别重命名 2028_test为 test。2028_train为 train。2028_val 为 val。
这一步别忘了,否则后面报错文件不存在,它其实一直都在,只不过你忘了重命名而已
3、训练的准备工作
(1)、k-means维度聚类
维度聚类的目的是 根据你自己的数据集生成合适的先验框,为了有更好的训练效果,建议大家不要忘了运行k-means.py文件,步骤如下
1、修改k-means.py文件文件内代码 “2012_train.txt” 为 “train.txt”,注意共有两处修改
2、运行k-means.py
3、将主目录keras-yolo4-master下生成的yolo_anchors.txt移动至keras-yolo4-master\model_data文件夹下

(2)修改CFG文件
打开主目录keras-yolo4-master下yolov4.cfg文件,ctrl+h搜索yolo,会出现三个[yolo],(位于cfg文件后半部分)。每个[yolo]需要修改三处,共计9处要修改,修改它们!!!下图仅展示第一个[yolo]的修改
每一个[yolo]的三处修改都是一样的
第一处:filters=3*(5+类别数),比如我的是2类,filters=3*(5+2)=21
第二处:anchors为刚才生成yolo_anchors文本的内容
第三处:classes有几类就写几
切记不要擅自修改其他地方(大神请自动屏蔽这句话)
(3)新建my_classes.txt
在主目录keras-yolo4-master\model_data下新建txt文件,命名为my_classes.txt,注意文件内不要有多余的空格或空行,以免训练时候读取出错

四、开始训练吧!
1、修改keras-yolo4-master/train.py
若使用GPU,我加了一行代码位于第24行,GOU编号为0
若电脑配置较低,注意修改batchsize,防止内存不足CUDA_memory_out

2、注意修改4处文件名称,
2012_train.txt修改为train.txt 共计修改1处
2012_val.txt修改为val.txt 共计修改2处
epoch由50000改为50轮 共计1处,(50000轮迭代太久,等换了好的GPU再试试)
此处粘贴出train.py代码,代码来源于本文开头yolov4的github文件,感谢keras-yolo4-master的创作,也希望大家能提出优化修改意见,一起学习进步
"""
Retrain the YOLO model for your own dataset.
"""
import math
import random
import os
import cv2
import numpy as np
import keras.backend as K
from keras.layers import Input, Lambda
from keras.models import Model
from keras.optimizers import Adam
from keras.callbacks import TensorBoard, ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
import keras.layers as layers
from yolo4.model import preprocess_true_boxes, yolo4_body, yolo_loss
from yolo4.utils import get_random_data
from callback_eval import Evaluate
import keras.backend.tensorflow_backend as KTF
import tensorflow as tf
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
def _main():
annotation_train_path = 'train.txt'
annotation_val_path = 'val.txt'
log_dir = 'logs/000/'
classes_path = 'model_data/my_classes.txt'
anchors_path = 'model_data/yolo4_anchors.txt'
class_names = get_classes(classes_path)
num_classes = len(class_names)
class_index = ['{}'.format(i) for i in range(num_classes)]
anchors = get_anchors(anchors_path)
max_bbox_per_scale = 150
anchors_stride_base = np.array([
[[12, 16], [19, 36], [40, 28]],
[[36, 75], [76, 55], [72, 146]],
[[142, 110], [192, 243], [459, 401]]
])
# 一些预处理
anchors_stride_base = anchors_stride_base.astype(np.float32)
anchors_stride_base[0] /= 8
anchors_stride_base[1] /= 16
anchors_stride_base[2] /= 32
input_shape = (608, 608) # multiple of 32, hw
#不全部占满显存, 按需分配
config = tf.ConfigProto()
config.gpu_options.allow_growth=True #不全部占满显存, 按需分配
sess = tf.Session(config=config)
KTF.set_session(sess)
model, model_body = create_model(input_shape, anchors_stride_base, num_classes, load_pretrained=False, freeze_body=2, weights_path='yolo4_weight.h5')
logging = TensorBoard(log_dir=log_dir)
checkpoint = ModelCheckpoint(log_dir + 'ep{epoch:03d}-loss{loss:.3f}.h5',
monitor='loss', save_weights_only=True, save_best_only=True, period=1)
reduce_lr = ReduceLROnPlateau(monitor='loss', factor=0.1, patience=3, verbose=1)
early_stopping = EarlyStopping(monitor='loss', min_delta=0, patience=10, verbose=1)
evaluation = Evaluate(model_body=model_body, anchors=anchors, class_names=class_index, score_threshold=0.05, tensorboard=logging, weighted_average=True, eval_file='val.txt', log_dir=log_dir)
with open(annotation_train_path)

最低0.47元/天 解锁文章
3811

被折叠的 条评论
为什么被折叠?



