目录
代码运行
代码分析
代码运行
同样分析tensorflow版的实现,代码地址:SSD-Tensorflow
1.预测
unzip ssd_300_vgg.ckpt.zip
jupyter notebook notebooks/ssd_notebook.ipynb
启动jupyter notebook后,我们运行里面的代码就可以进行预测了。
2.训练
准备数据
首先下载VOC数据,下载方式可以参考https://blog.csdn.net/stesha_chen/article/details/82965283
创建文件夹tfrecords,然后运行tf_convert_data.py,将VOC数据转成tfrecord方式存储,后面会细读这部分的代码。
python tf_convert_data.py \
--dataset_name=pascalvoc \
--dataset_dir=./VOCdevkit/VOC2007/ \
--output_name=voc_2007_train \
--output_dir=./tfrecords
基于pre-trained VGG
由于SSD网络的base network就是一个分类网络,所以就算是从头开始训练SSD,我们也会先用训练好的分类网络初始化SSD的前面层,这里以VGG为例。
先下载预先训练好的VGG权重文件,VGG下载地址
python train_ssd_network.py \
--train_dir=./log \
--dataset_dir=./tfrecords \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--checkpoint_path=./checkpoints/vgg_16.ckpt \
--checkpoint_model_scope=vgg_16 \
--checkpoint_exclude_scopes=ssd_300_vgg/conv6,ssd_300_vgg/conv7,ssd_300_vgg/block8,ssd_300_vgg/block9,ssd_300_vgg/block10,ssd_300_vgg/block11,ssd_300_vgg/block4_box,ssd_300_vgg/block7_box,ssd_300_vgg/block8_box,ssd_300_vgg/block9_box,ssd_300_vgg/block10_box,ssd_300_vgg/block11_box \
--trainable_scopes=ssd_300_vgg/conv6,ssd_300_vgg/conv7,ssd_300_vgg/block8,ssd_300_vgg/block9,ssd_300_vgg/block10,ssd_300_vgg/block11,ssd_300_vgg/block4_box,ssd_300_vgg/block7_box,ssd_300_vgg/block8_box,ssd_300_vgg/block9_box,ssd_300_vgg/block10_box,ssd_300_vgg/block11_box \
--save_summaries_secs=60 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.001 \
--learning_rate_decay_factor=0.94 \
--batch_size=32
--train_dir表示训练权重,tensorboard等信息保存的地址
--dataset_dir表示转出来的tfrecords保存的地址
--dataset_name表示我们现在训练哪个数据集,因为不同的数据集,在解析方式上是有些微差别的
--dataset_split_name表示我们现在是用pascalvoc_2007数据集的train数据还是test数据
--model_name表示我们模型的名字,检测模型是SSD,输入是300x300,base network是VGG
--checkpoint_path就是VGG pre-trained weights存放的地址
--checkpoint_exclude_scopes表示这些参数不需要从checkpoint中恢复
--trainable_scopes表示训练的时候只更新这些参数的值
基于pre-trained SSD
在用jupyter运行的时候我们已经将预先训练好的SSD权重文件下载了,运行下面的命令就可以继续训练了
python train_ssd_network.py \
--train_dir=./log/ \
--dataset_dir=./tfrecords \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--checkpoint_path=./checkpoints/ssd_300_vgg.ckpt \
--save_summaries_secs=60 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.001 \
--batch_size=32
3.评估
python eval_ssd_network.py \
--eval_dir=./log/eval \
--dataset_dir=./tfrecords \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=test \
--model_name=ssd_300_vgg \
--checkpoint_path=./checkpoints/ssd_300_vgg.ckpt \
--wait_for_checkpoints=True \
--batch_size=1 \
--max_num_batches=500
代码分析
数据准备
在tf_convert_data.py中主要是调用了pascalvoc_to_tfrecords.run,第一个参数dataset_dir是./VOCdevkit/VOC2007,第二个参数output_dir是./tfrecords,第三个参数是voc_2007_train
path = os.path.join(dataset_dir, DIRECTORY_ANNOTATIONS)
filenames = sorted(os.listdir(path))
path是./VOCdevkit/VOC2007/Annotations,列出里面的所有文件就是filenames,每个文件是对图片进行标记的xml文件。
然后遍历所有文件,将200个文件放入一条tfrecord记录中。
# 创建TFRecordWriter
with tf.python_io.TFRecordWriter(tf_filename) as tfrecord_writer:
j = 0
# 循环200次放入同一条tfrecord中
while i < len(filenames) and j < SAMPLES_PER_FILES:
filename = filenames[i]
img_name = filename[:-4]
# 将数据写入tfrecord中
_add_to_tfrecord(dataset_dir, img_name, tfrecord_writer)
在_add_to_tfrecord函数中先调用_process_image对数据进行解析,返回值如下:
image_data是通过tf.gfile.FastGFile(filename, 'r').read()读出来的图片buffer
filename = directory + DIRECTORY_IMAGES + name + '.jpg'
image_data = tf.gfile.FastGFile(filename, 'r').read()
shape是从xml中读出的size信息
shape = [int(size.find('height').text),
int(size.find('width').text),
int(size.find('depth').text)]
bboxes是从xml中读出的每个物体的位置框,如果图片中两个物体那么bboxes的长度为2,里面放着两个bbox信息
bbox = obj.find('bndbox')
bboxes.append((float(bbox.find('ymin').text) / shape[0],
float(bbox.find('xmin').text) / shape[1],
float(bbox.find('ymax').text) / shape[0]