先贴一下源码的地址,这是tensorflow1.0版本下的,作者还提供了2.0的,需要的自行下载。
https://github.com/YunYang1994/tensorflow-yolov3
作者的readme写的很清楚,这里补充一下细节,作为自己的一个笔记。
1.运行官方demo
- 下载训练好的模型,这个是百度云的https://pan.baidu.com/s/11mwiUy8KotjUVQXqkGGPFQ&shfl=sharepset
我也会把模型数据放到资源里,自行下载。 - 将上述下载的内容放到checkpoint文件夹下
- 运行convert_weight.py
- 运行freeze_graph.py
- 运行image_demo.py,这里如果是tensorflow-gpu可能会出现与cudnn相关的错误,将下面的代码添加到代码中,即可解决。
# TensorFlow session: grow memory when needed. TF, DO NOT USE ALL MY GPU MEMORY!!!
gpu_options = tf.GPUOptions(allow_growth=True)
config = tf.ConfigProto(log_device_placement=False, gpu_options=gpu_options)
isess = tf.InteractiveSession(config=config)
如果上面顺利运行,则demo运行成功,下面介绍从头训练自己的数据集步骤。
2.训练自己的数据集-制作VOC2007数据集
这个网上教程很多,如果不会,网上搜索一下,一定要划分训练集和测试集。
划分的代码如下:
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 20 17:55:13 2020
@author: Administrator
"""
import os
import random
trainval_percent = 0.8
train_percent = 0.8
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:
ftrain.write(name)
else:
fval.write(name)
else:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
3.按照要求划分训练和测试文件夹
将上述制作好的数据集放到dataset文件夹下,如下图所示,并创建generateTestandTrain.py将文件夹分开,代码如下。
import os
from shutil import copyfile
#根据tarin.txt和test.txt将数据集分为标准数据集
train_text_path = './VOC2007/ImageSets/Main/train.txt'
test_text_path = './VOC2007/ImageSets/Main/val.txt'
#图片存放地址
image_path = './VOC2007/JPEGImages'
#xml文件存放地址
xml_path = './VOC2007/Annotations'
#输出的目录
outdir = './dateset'
#创建各级文件夹
test_xml_out = os.path.join(outdir,'./test/VOCdevkit/VOC2007/Annotations')
os.makedirs(test_xml_out)
os.makedirs(os.path.join(outdir,'./test/VOCdevkit/VOC2007/ImageSets/Layout'))
os.makedirs(os.path.join(outdir,'./test/VOCdevkit/VOC2007/ImageSets/Main'))
os.makedirs(os.path.join(outdir,'./test/VOCdevkit/VOC2007/ImageSets/Segmentation'))
test_img_out = os.path.join(outdir,'./test/VOCdevkit/VOC2007/JPEGImages')
os.makedirs(test_img_out)
os.makedirs(os.path.join(outdir,'./test/VOCdevkit/VOC2007/SegmentationClass'))
os.makedirs(os.path.join(outdir,'./test/VOCdevkit/VOC2007/SegmentationObject'))
train_xml_out = os.path.join(outdir,'./train/VOCdevkit/VOC2007/Annotations')
os.makedirs(train_xml_out)
os.makedirs(os.path.join(outdir,'./train/VOCdevkit/VOC2007/ImageSets/Layout'))
os.makedirs(os.path.join(outdir,'./train/VOCdevkit/VOC2007/ImageSets/Main'))
os.makedirs(os.path.join(outdir,'./train/VOCdevkit/VOC2007/ImageSets/Segmentation'))
train_img_out = os.path.join(outdir,'./train/VOCdevkit/VOC2007/JPEGImages')
os.makedirs(train_img_out)
os.makedirs(os.path.join(outdir,'./train/VOCdevkit/VOC2007/SegmentationClass'))
os.makedirs(os.path.join(outdir,'./train/VOCdevkit/VOC2007/SegmentationObject'))
with open(train_text_path) as f:
lines = f.readlines()
for i in lines:
img_save_path = os.path.join(train_img_out,i.rstrip('\n')+'.jpg')
xml_save_path = os.path.join(train_xml_out, i.rstrip('\n') + '.xml')
copyfile(os.path.join(image_path,i.rstrip('\n')+'.jpg'),img_save_path)
copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path)
print(i)
with open(test_text_path) as f:
lines = f.readlines()
for i in lines:
img_save_path = os.path.join(test_img_out, i.rstrip('\n') + '.jpg')
xml_save_path = os.path.join(test_xml_out, i.rstrip('\n') + '.xml')
copyfile(os.path.join(image_path, i.rstrip('\n') + '.jpg'), img_save_path)
copyfile(os.path.join(xml_path, i.rstrip('\n') + '.xml'), xml_save_path)
print(i)
程序运行之后,会在dataset(1)文件夹下重新生成一个dataset(2)文件,在dataset(1)中创建VOC文件夹,将其中的test和train文件夹挪到里面即可。
4.生成程序运行的文件
- 将步骤3中的python代码,复制到train文件夹下的VOC2007中,然后运行一遍。
- 将步骤3中的python代码,复制到test文件夹下的VOC2007中,修改
trainval_percent = 0.0 train_percent = 1.0
- 生成训练时用的文件,运行scripts中的voc_annotation.py,将num2那行代码删除,修改data_path为自己的数据集路径,修改train_annotation和test_annotation的路径,这两个生成的文件都放在dataset路径下,修改num1和num3的路径信息,一定是train文件夹,我的修改之后为下图所示
运行,会在dataset下生成两个文件voc_train.txt和voc_test.txt。 - 更改voc.names的类别,在data文件下的classes文件下,修改voc.names为自己的类别。
5.修改config文件内容
修改./core/config.py中的一些必要的配置
__C.YOLO.CLASSES = "./data/classes/voc.names"
__C.TRAIN.ANNOT_PATH = "./data/dataset/voc_train.txt"
__C.TEST.ANNOT_PATH = "./data/dataset/voc_test.txt"
6.运行train.py
我的版本是tensorflow-gpu总是提示我内存不够,找了很多办法都不能解决,最终使用cpu进行训练,速度很慢。在代码中添加,
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '1'
因为我的gpu只有GPU0 ,所以添加这个,就直接变成CPU运行了。
经过漫长的等待,训练结束。
7.评估阶段
- 生成评估需要的测试集,修改voc_annotation,如下图所示
- 修改config文件内容
__C.TEST.ANNOT_PATH = "./data/dataset/voc_test_test.txt"
__C.TEST.WEIGHT_FILE = "./checkpoint/yolov3_test_loss=5.7702.ckpt-30" #按照自己的名称修改
- 运行evaluate.py
- 运行mAP文件夹下的main.py,评估完成
总结
上次训练Keras框架下的yolov3,感觉不好移植,然后找到了这个tensorflow框架下的,目前训练效果很好,离成功又近了一步,加油自己!!!