参考:https://github.com/qqwweee/keras-yolo3
本文使用anaconda创建虚拟环境,达到与其它环境隔离的目的,前提是装好anaconda,如果有不清楚的,查一下其它教程
在github教程中,推荐的环境是
Python 3.5.2
Keras 2.1.5
tensorflow 1.6.0
除此之外,本文使用的是keras版本的yolo3,不是直接利用darknet进行训练,两者的区别后续有空研究一下
1 创建yolo环境
conda creat -n yolo python=3.6
更换conda源,下载软件的时候会快些
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes
创建后进入yolo环境,并安装Keras和tensorflow,我这块安装的是gpu版本的tensorflow
source activate yolo
pip install keras2.1.5
pip install tensorflow-gpu1.6.0 #如果是gpu版本
pip install tensorflow==1.6.0 #如果是cpu版本
2 安装依赖
在训练的过程中,会有很多依赖,所以提前安装一遍
pip install Pillow
pip install matplotlib
conda install ffmpeg
pip install opencv-contrib-python
注意opencv要安装contrib版本的,否则直接用conda install -c menpo opencv3安装后,在打开MP4文件时会报如下的错误
Unable to stop the stream: Invalid argument
3 制作数据集
首先把github上的代码克隆下来,我们在home目录下新建一个yolov3的文件夹,然后复制
mkdir yolov3
cd yolov3
git clone https://github.com/qqwweee/keras-yolo3
cd keras-yolov3
首先利用lableImg工具标注自己的图片,生成对应的xml文件,具体标注方法这里不再赘述,然后按照以下的格式创建VOC数据集
#在keras-yolo3下创建
VOCdevkit
└── VOC2007
├── Annotations
├── ImageSets
│ ├── Layout
│ ├── Main
│ └── Segmentation
├── JPEGImages
└── labels
其中,把刚才标注好的JPG图片放入JPEGImages文件夹中,将xml标注文件放在Annotations文件夹中
接下来要在Main中生成4个txt文件,其中test.txt是测试集,train.txt是训练集,val.txt是验证集,trainval.txt是训练和验证集。为了操作方便,我们直接在VOC2007下新建一个create_ImageSets.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)
if not os.path.exists(txtsavepath):
print(‘not exist…{}’.format(txtsavepath))
os.makedirs(txtsavepath)
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()
接下来修改yolov3文件夹下的voc_annotation.py文件,将classes修改为自己的类别,然后运行生成yolo格式的标注文件
python voc_annotation.py
这样在主目录下生成以下三个文件
2007_test.txt
2007_train.txt
2007_val.txt
至此,训练数据准备完毕
4 修改配置文件
4.1 下载预训练模型
wget https://pjreddie.com/media/files/darknet53.conv.74
下载完毕后,重命名为darknet53.weights,
4.2 生成h5文件
然后运行convert.py文件,将模型转化为keras框架的h5文件(不需要修改darknet53.cfg,采用默认值即可)
python convert.py -w darknet53.cfg darknet53.weights model_data/yolo_weights.h5
第一次运行时可能会报错
ImportError: save_weights
requires h5py.
解决方法如下
pip install h5py
然后再运行上边的指令,运行成功后会显示生成并保存Keras weights文件到model_data/yolo_weights.h5
4.3 修改类别文件
找到model_data/voc_classes.txt文件,将里边的类别修改为自己的类别
4.4 修改anchor文件
我们知道yolo是利用9个anchor来检测目标的位置,因此这9个anchor设置的好坏,会直接影响到训练与检测效果。
我们使用kmeans方法来聚类得到与我们数据集接近的anchors,在keras-yolov3下边有一个kmeans.py文件,打开后将filename改为2007_train.txt(2处),保存运行该脚本,会得到9个anchors的坐标值以及准确率。记下这9个坐标值,然后打开model_data中的yolo_anchors.txt,按照文本中的格式,将9个anchors值依次写入即可。
4.5 修改yolov3.cfg
关于配置文件的参数介绍,可参考《yolo3 配置文件yolo3_voc.cfg参数学习》,其中有几个关键地方要修改
最开始几行,注释掉Testing的设置,打开Training的设置,并根据自己显卡的情况合理设置batch大小
修改classes类别数,总共有三处地方,改为自己对应的类别数
修改[yolo]上边对应的filters值,也是有三处地方要修改,修改为3*(类别数+5),原来是80类,对应的值是255,假如自己有2类,则应改为21
5 开始训练
首先将train.py中的annotation_path修改一下,原文是train.txt,我们改为2007_train.txt
训练时,直接运行python train.py文件即可,由于我的服务器有多块显卡,且有多人使用,因此,我再train.py文件开头增加显卡设置的代码,这样不影响别人使用
import os
os.environ[“CUDA_VISIBLE_DEVICES”] = “2, 3”
然后运行python train.py就可以开始训练了,在训练时,如果报如下的错
Hint: If you want to see a list of allocated tensors when OOM happens, add report_tensor_allocations_upon_oom to RunOptions for current allocation info.
则是因为显存不足,将train.py中的batch_size大小改小,默认是32,可改为16或8或4试试,当然可设置的越大越好
6 测试模型
训练完成时,在logs/000/文件夹下,会生成trained_weights_final.h5,我们将其拷贝出来,复制到model_data文件夹下,并重命名为yolo.h5,新建一个文件夹video,存放我们的测试视频,如test.mp4,将结果保存为result.mp4
首先将yolo.py的第25行classes_path路径改为voc_classes.txt,否则会报ValueError: Dimension 0 in both shapes must be equal, 的错误
由于编码器的原因,我们在yolo.py文件中将第177行,将
video_FourCC = int(vid.get(cv2.CAP_PROP_FOURCC))
改为
video_FourCC = cv2.VideoWriter_fourcc(*“mp4v”)
然后运行如下指令
python yolo_video.py --input=test.mp4 --output=result.mp4 --classes=model_data/voc_classes.txt
即可以显示出测试视频,并保存运行结果