1.安装环境 一定要注意版本问题
因为版本对不上,花了好多时间猜正确的版本。
系统:Ubantu16.04
nvidia驱动版本 410.78
驱动更新参考:https://blog.csdn.net/pertain99/article/details/102848725
python 版本 3.5.2
tensorflow-gpu版本 1.14.0
CUDA : 10.0
cudnn: 7.6.5
labelme 3.9
2.安装deeplabV3+项目
官方链接: https://github.com/tensorflow/models
下载后解压 下载解压的文件夹名字叫 /models-master,为了方便,我改了名字为 /models
以下地址中的所有 /models 就是 /models-master
测试安装是否成功 打开终端进入 models/research 执行:
export PYTHONPATH=$PYTHONPATH:/path-to/models/research/slim
这个代码每次打开终端都需要执行一次 或者 直接写在 ~/.bashrc里,并 source ~/.bashrc
然后测试安装是否成功 在 models/research 目录下执行
python deeplab/model_test.py
如果成功会显示
失败的话可能是相关包没装齐全,根据提示装相关包就好。一般是ImportError :no modual name "XXX",其他的错误我没遇到。 如果是tensorflow的包没有,那基本是tensorflow版本问题,不是太新就是太旧,按照第一步版本重装就好。
3.制作数据集
3.1 labelme
用的labelme 版本是3.9.0
labelme 版本不对 会出现
attributeerror: module 'labelme.utils' has no attribute 'draw_label'
labelme对图片进行多变形标注后,会出现 图片以及相关的json文件
而deeplabV3+的数据集需要这些json文件 将这些json 文件放在一起。我放在 testdata 文件夹
3.2 json_to_mask
然后是将这些json换成deeplab所需要的mask_label.
用到的代码在:https://blog.csdn.net/u014513323/article/details/81166997
这里需要根据自己的需求改代码,代码不难,容易看懂
这是根据自己需求改的:https://github.com/xixixijie/tensorflow/blob/master/labelme_to_mask.py
会直接生成image和mask文件夹
image放的原图格式 .jpg,mask放的是label图 格式 .png 。
或者参考以下 :https://blog.csdn.net/xjtdw/article/details/94741984
需要的是第一张原图和第二张黑的label图,第三张图是label的可视化,因为第二张全黑不容易知道是否有标签值在里面。
判断label是否正确,可用:https://github.com/xixixijie/tensorflow/blob/master/pilShowMask.py
如图,鼠标在图片对应位置滑动,右下角显示label的id[2,2,2] ,说明这个图片不是全黑,是有label值的,标号错了可以自己修改前面的labelme_to_mask.py。
3.3构建数据集目录
自己创建,官方不自带
放在这个路径下#models/research/deeplab/datasets
-testdata
+ image
+ mask
+ index
- train.txt
- trainval.txt
- val.txt
+ tfrecord
image里放所有原图 ,mask里放label所有标签。 注意,原图名字和label名字要一一对应
index里放的是train.txt val.txt train.txt,靠这些txt文件区分训练集和测试集,可以用这个文件制作:
https://github.com/xixixijie/tensorflow/blob/master/saveFilenameToTxt.py
制作完成后,train.txt里放的是训练集图片的名,不包括路径和扩展名,其他以此类推,vis是测试集。trainval我没用上。
tfrecord文件夹里放的是tfrecord,
打开终端进入/models/research ,在该路径下执行
python deeplab/datasets/build_voc2012_data.py \
--image_folder="models/research/deeplab/datasets/testdata/image" \
--semantic_segmentation_folder="/models/research/deeplab/datasets/testdata/mask" \
--list_folder="/models/research/deeplab/datasets/testdata/index" \
--image_format="jpg" \
--label_format="png" \
--output_dir="models/research/deeplab/datasets/testdata/tfrecord"
build_voc2012_data.py 是官方程序自带的。
--image_folder 上一步的image文件夹路径
--semantic_segmentation_folder 上一步的mask路径
--list_folder index路径
--image_format 原图图片格式,我的是jpg 应该可以是别的格式
--label_format 标签图片格式
--output_dir tfrecord路径
数据集制作完毕
4.训练前代码改动
注册数据集
在/models/research/deeplab/datasets 路径的data_generator.py 第93行:
_MYDATA_INFORMATION = DatasetDescriptor(
splits_to_sizes={
'train':44, # num of samples in images/training train.txt的行数
'val':27, # num of samples in images/validation val.txt的行数
},
num_classes=6, # 我的标签是5类(包括background),加上ignore_label总共六类
ignore_label=255,
)
然后找到 _DATASETS_INFORMATION ,加上mydata....一行
_DATASETS_INFORMATION = {
'cityscapes': _CITYSCAPES_INFORMATION,
'pascal_voc_seg': _PASCAL_VOC_SEG_INFORMATION,
'ade20k': _ADE20K_INFORMATION,
'mydata': _MYDATA_INFORMATION, #注册上面的数据集 加粗部分一致,前面的mydata随意取
}
同样在models/research/deeplab/deprecated下的segmentation_dataset.py文件进行同样的操作
train_utils.py
在models/research/deeplab/utils/train_utils.py的213行左右
exclude_list = ['global_step','logits'] #本来只有global_step ,现在加上 logits,表示不加载逻辑层的参数
if not initialize_last_layer:
exclude_list.extend(last_layers)
train.py
在models/research/deeplab/train.py里 156行左右
# Set to False if one does not want to re-use the trained classifier weights.
flags.DEFINE_boolean('initialize_last_layer', False, 'Initialize the last layer.') #这个本来是True设置为False
flags.DEFINE_boolean('last_layers_contain_logits_only', True, 'Only consider logits as last layers or not.')#这个设置为True
解释:
input_preprocess.py
models/research/deeplab/input_preprocess.py 128行左右
# Randomly crop the image and label.
if is_trainingand labelis not None:
processed_image, label = preprocess_utils.random_crop([processed_image, label], crop_height, crop_width)
为这个if加一个else,下面的代码显示得不好,不过在链接里也有
参考链接:https://github.com/tensorflow/models/issues/3695
else:
rr = tf.minimum(tf.cast(crop_height, tf.float32) / tf.cast(image_height, tf.float32), \
tf.cast(crop_width, tf.float32) / tf.cast(image_width, tf.float32))
newh = tf.cast(tf.cast(image_height, tf.float32) * rr, tf.int32)
neww = tf.cast((tf.cast(image_width, tf.float32) * rr), tf.int32)
processed_image = tf.image.resize_images(processed_image, (newh, neww), method=tf.image.ResizeMethod.BILINEAR, align_corners=True)
processed_image = preprocess_utils.pad_to_bounding_box(processed_image, 0, 0, crop_height, crop_width, mean_pixel)
不加这一段在运行vis.py和eval的时候会报错
类似
InvalidArgumentError (see above for traceback): padded_shape[1]=128 is not divisible by block_shape[1]=12
Invalid argument: padded_shape[1]=69 is not divisible by block_shape[1]=2
这种错基本都是这样解决
5.train vis eval
打开终端 ,进入 models/research路径
5.1 train.py
执行
python deeplab/train.py \
--logtostderr \
--training_number_of_steps=200 \
--train_split="train" \
--model_variant="xception_65" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--train_crop_size=317,385 \
--train_batch_size=2 \
--dataset="mydata" \
--tf_initial_checkpoint='models/research/deeplab/backbone/deeplabv3_cityscapes_train/model.ckpt' \
--train_logdir='models/research/deeplab/exp/train_on_train_set/train' \
--dataset_dir='models/research/deeplab/datasets/testdata/tfrecord'
--training_number_of_steps=200 这里是训练步数,自己设置训练多少次
--model_variant="xception_65" 选择backbone 有别的,但我没看。
--train_crop_size=317,385 设置图片裁剪大小,( height,width)这里尽可能大可以提高准度
这里要说的是我的训练集图片大小不一,没有进行统一尺寸修改。图片最小的尺寸是316×384 我都加了1,因为别的博客里说是要
(height/width - 1)/ 4 要是整数。
--train_batch_size=2 内存不够可以将这个调小。
--dataset="mydata" 这个mydata是上面注册数据集时取的名字
--tf_initial_checkpoint 初始权重,就是官方预训练过的权重 路径
在这里下载,选择xception_65_imagenet:https://github.com/tensorflow/models/blob/master/research/deeplab/g3doc/model_zoo.md
解压在任意位置,路径对的上就行。
--train_logdir 训练出来的文件的保存路径,自己创建,/exp/train_on_train_set/train 这三个文件夹都是我参考别人博客创建的。
--dataset_dir 这个就是上面tfrecord的路径
其他没解释的
不出错的话是
错误记录:
Invalid argument: Nan in summary histogram for: image_pooling/BatchNorm/moving_variance_1
这个问题出现在我把batch_size设置成1,解决方案为设置为2,参考链接:
https://blog.csdn.net/qq_41046851/article/details/90552364
解释在:
https://blog.csdn.net/v1_vivian/article/details/77991894
官方解决方法是增加loss的范围,可是没说怎么加
https://github.com/tensorflow/models/issues/5050
5.2 vis.py
这个用于查看训练结果
python deeplab/vis.py \
--logtostderr \
--vis_split="val" \
--model_variant="xception_65" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--vis_crop_size=317,384 \
--dataset="mydata" \
--checkpoint_dir='models/research/deeplab/exp/train_on_train_set/train' \
--vis_logdir="models/research/deeplab/exp/train_on_train_set/vis" \
--dataset_dir="models/research/deeplab/datasets/testdata/tfrecord"
--vis_crop_size 这里决定输出的label预测图大小,可以设置为数据库里最大的图片。
--checkpoint_dir 这个路径就是上面训练指令的--train_logdir 表示你要用训练好的权重
--vis_logdir 训练结果图片要存的位置,自己创建。
如果不出错,会显示
在--vis_logdir 路径下会看到分割结果的图片。
5.3 eval.py
python deeplab/eval.py \
--logtostderr \
--eval_split="val" \
--model_variant="xception_65" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--eval_crop_size=317,365 \
--dataset="mydata" \
--checkpoint_dir="models/research/deeplab/exp/train_on_train_set/train" \
--eval_logdir="models/research/deeplab/exp/train_on_train_set/eval" \
--dataset_dir="models/research/deeplab/datasets/testdata/tfrecord" \
--eval_crop_size 一样
--eval_logdir 输出文件路径,自己创建
正常输出 官方版本版本不一样可能有些差距。
我暂时就做到这里了,剩下的步骤可以参考别的博客。
参考链接:
deeplab_v3 实现 制作并训练自己的数据集——个人采坑
(超详细很完整)tensorflow下利用deeplabv3+对自己的数据进行训练
Deeplab V3+训练自己数据集全过程
官方讨论区
推荐网课 白勇老师的教程
最后这个不是打广告,只是有很多没有遇到的bug要是真的没法解决,不如买个网课,去问一下老师,老师很快就回复我了,还给了qq交流。
80不贵解君愁。