本文主要介绍如何使用自己的数据集训练DeepLabv3+分割算法,代码使用的是官方源码。
1、代码简介
当前使用TensorFlow版本的官方源码,选择它的原因是因为代码中的内容比较全面,除了代码实现以外,还提供了许多文档帮助理解与使用,同时还提供了模型转换的代码实现。
代码地址:
【github】models/research/deeplab at master · tensorflow/models
接下来,先对这个代码仓库进行一下简单的介绍,因为自己在使用该代码仓库的时候只关心训练代码的实现,而忽略的其他的内容,走了不少弯路,到后面才发现我想要的内容,仓库里面早有(==)。
在当前的实现中,我们支持采用以下网络主干:
MobileNetv2
和MobileNetv3
:一个为移动设备设计的快速网络结构Xception
:用于服务器端部署的强大网络结构ResNet-v1-{50, 101}
:我们提供原始的ResNet-v1
及其“ beta”
变体,其中对“ stem”
进行了修改以进行语义分割。PNASNet
: 一个通过神经体系结构搜索发现的强大网络结构。Auto-Deeplab
(代码中叫做HNASNet
):通过神经体系结构搜索找到的特定于细分的网络主干。
该目录包含TensorFlow 实现。我们提供的代码使用户可以训练模型,根据mIOU
(平均交叉点求和)评估结果以及可视化细分结果。我们以PASCAL VOC 2012
和Cityscapes
语义分割基准为例。
代码中几个重要文件:
datasets/
:该文件夹下包含对于训练数据集的处理代码,主要针对PASCAL VOC 2012
和Cityscapes
数据集的处理。g3doc/
:该文件夹下包含多个Markdown
文件,非常有用,如何安装,常见问题FAQ等。deeplab_demo.ipynb
:该文件中给出了如果对一张图像进行语义分割并显示结果的Demo。export_model.py
:该文件提供了将训练的checkpoint
模型转为.pb
文件的代码实现。train.py
:训练代码文件,训练时,需要指定提供的训练参数。eval.py
:验证代码,输出mIOU,用来评估模型的好坏。vis.py
:可视化代码。
2、安装
Deeplab
依赖的库有:
- Numpy
- Pillow 1.0
- tf Slim (which is included in the “tensorflow/models/research/” checkout)
- Jupyter notebook
- Matplotlib
- Tensorflow
2.1 添加库到PYTHONPATH
本地运行的时候,tensorflow/models/research/
目录应该追加到PYTHONPATH
中,如下:
# From tensorflow/models/research/
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
# [Optional] for panoptic evaluation, you might need panopticapi:
# https://github.com/cocodataset/panopticapi
# Please clone it to a local directory ${PANOPTICAPI_DIR}
touch ${
PANOPTICAPI_DIR}/panopticapi/__init__.py
export PYTHONPATH=$PYTHONPATH:${
PANOPTICAPI_DIR}/panopticapi
注意:此命令需要在您启动的每个新终端上运行。如果希望避免手动运行此命令,可以将它作为新行添加到
〜/ .bashrc
文件的末尾。
2.2 测试是否安装成功
通过运行model_test.py
快速测试:
# From tensorflow/models/research/
python deeplab/model_test.py
在PASCAL VOC 2012
数据集上快速运行所有代码:
# From tensorflow/models/research/deeplab
sh local_test.sh
3、数据集准备
最终目标: 生成TFRecord
格式的数据
数据集目录结构如下:
+dataset #数据集名称
+image
+mask
+index
- train.txt
- trainval.txt
- val.txt
+tfrecord
- image: 原图图像,RGB彩色图像
- mask:像素值为类别标签的mask图像,单通道,与原图的名称一致,后缀为
.jpg
和.png
都可以,只要在代码中读取一致即可。VOC数据集默认原图是.jpg
,mask图像为.png
。 - index:存放图像文件名的
txt
文件(不加后缀) - tfrecord:存放转为
tfrecord
格式的图像数据
数据集制作流程:
- 标注数据,制作符合要求的
mask
图像 - 将数据集分割为训练集、验证集和测试集
- 生成
TFRecord
格式的数据集
3.1 标注数据
训练集数据包含两部分,一是原图,二是对应分类的标注值(本文中称为mask
图像)。
mask图像的值是如何设置的?
根据图像分割的分类个数来制作原图对应的mask图像。假如一共有N个类别(背景作为一类),则mask图像的值的范围是[0~N)
。0
值作为背景值,其他分割类别的值依次设置为1, 2, ..., N-1
。
注意:
ignore_label
:从字面意思来讲是忽略的标签,即ignore_label
是指没有做标注的像素,即不需进行预测的像素值,因此,它不参与loss
值的计算,在mask
图像中将其值记为255
。mask
图像是单通道的灰度图像。mask
图像的格式没有限定,但所有的mask图像采用同一种图像格式,方便数据读取。
小总结
mask
图像的值分为三类:
- 背景:用
0
表示 - 分类类别:使用
1, 2, ....., N-1
表示 ignore_label
值:用255
表示
如果分割的类别较少,则生成的
mask
图像看上去是一片黑,因为分类的值都较小,在0~255
的范围内不容易显示出来。
3.2 分割数据集
这部分就是将准备的数据集进行分割,分为训练集、验证集、测试集。
无需将具体的图像文件分到三个文件夹中,只需要建立图像的索引文件即可,通过添加相应的路径+文件名即可获取到具体的图像。
假设原图像和mask图像的存放路径如下:
- 原图:
./dataset/images
mask
图像:./dataset/mask
:此处存放的是2.1小节要求格式
原图与
mask
图像是一一对应的,包括图像尺寸,图像名(后缀可以不同)
索引文件存放路径:./dataset/index
,该路径下生成:
train.txt
trainval.txt
val.txt
索引文件中,只需记录文件名(不加后缀),这取决于代码中数据集加载的方式。
目前为止,数据集目录结构如下:
#./dataset
+image
+mask
+index
- train.txt
- trainval.txt
- val.txt
3.3 将数据打包为TFRecord
格式
TFRecord
是谷歌推荐的一种二进制文件格式,理论上它可以保存任何格式的信息。
TFRecord
内部使用了“Protocol Buffer”
二进制数据编码方案,它只占用一个内存块,只需要一次性加载一个二进制文件的方式即可,简单,快速,尤其对大型训练数据很友好。而且当我们的训练数据量比较大的时候,可以将数据分成多个TFRecord文件,来提高处理效率。
那么,如何将数据生成TFRecord
格式呢?
在此,我们可以借助 项目代码中./datasets/build_voc2012_data.py
文件来实现。给文件是VOC2012数据集处理的代码,我们只需修改一下输入参数即可。
参数:
image_folder
:原图文件夹名称,./dataset/image
semantic_segmentation_folder
:分割文件夹名称,./dataset/mask
list_folder
:索引文件夹名称,./dataset/index
output_dir
:输出路径,即生成的tfrecord
文件所在位置,./dataset/tfrecord
运行命令:
python ./datasets/build_voc2012_data.py --image_folder=./dataset/image
--semantic_segmentation_folder=./dataset/mask
--list_folder=./dataset/index
--output_dir=./dataset/tfrecord
生成的文件如下:
注意: 可在代码中调节参数_NUM_SHARDS
(默认为4
),