Ubuntu16.04下Cuda安装 为了让tensorflow在GPU下运行,需要安装cuda和cudnn。(太懒了,不想写)
参考网页 Ubuntu 16.04 上安装 CUDA 9.0 详细教程
DeepLab的准备、训练、测试 参考网页 [1] Deeplab v3 Github
[2] 图像语义分割 DeepLab v3+ 训练自己的数据集
[3] 使用TensorFlow DeepLab进行语义分割
[4] Github: Running DeepLab on Cityscapes Semantic Segmentation Dataset
第2、3篇文章都是对voc数据集进行训练,大概参考这两篇文章,然后根据第4篇github上的instruction稍加修改,就可以训练了。
准备 1 测试本地环境 首先添加slim路径,每次打开terminal都要加载路径
1 2 # From tensorflow/models/research/ export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
Quick test by running model_test.py:
1 2 # From tensorflow/models/research/ python deeplab/model_test.py
Quick running the whole code on the PASCAL VOC 2012 dataset:
1 2 # From tensorflow/models/research/deeplab sh local_test.sh
如果都运行成功,说明本地环境已经可以了,接下来训练自己的数据集。
2 生成tfrecord格式的数据 首先在The Cityscapes Dataset Github 下载Cityscapesscripts
,按照convert_cityscapes.sh
文件中提到的文件放置顺序放到models/research/deeplab/datasets
文件路径下。
1 2 3 4 5 6 7 8 # The folder structure is assumed to be: # + datasets # - build_cityscapes_data.py # - convert_cityscapes.sh # + cityscapes # + cityscapesscripts (downloaded scripts) # + gtFine # + leftImg8bit
运行如下语句
1 2 # From the ./models/research/deeplab/datasets directory. sh convert_cityscapes.sh
转换后的dataset会存储在 ./deeplab/datasets/cityscapes/tfrecord
。
训练 训练与测试部分主要参考文章 使用TensorFlow DeepLab进行语义分割
0 文件结构 文件结构参考 PASCAL VOC 2012 官方推荐的文件结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 deeplab/datasets/pascal_voc_seg ├── exp │ └── train_on_train_set │ ├── eval │ │ └── events.out.tfevents.... │ ├── export │ │ └── frozen_inference_graph.pb │ ├── train │ │ ├── checkpoint │ │ ├── events.out.tfevents.... │ │ ├── graph.pbtxt │ │ ├── model.ckpt-0.data-00000-of-00001 │ │ ├── model.ckpt-0.index │ │ ├── model.ckpt-0.meta │ │ └── ... │ └── vis │ ├── graph.pbtxt │ ├── raw_segmentation_results │ └── segmentation_results ├── init_models │ └── deeplabv3_pascal_train_aug │ ├── frozen_inference_graph.pb │ ├── model.ckpt.data-00000-of-00001 │ └── model.ckpt.index ├── tfrecord │ ├── ....tfrecord │ └── ... └── VOCdevkit └── VOC2012 ├── Annotations ├── ImageSets │ ├── Action │ ├── Layout │ ├── Main │ └── Segmentation ├── JPEGImages ├── SegmentationClass ├── SegmentationClassRaw └── SegmentationObject
Cityscapes 的文件结构如下,需要结合一下VOC的结构。
1 2 3 4 5 6 7 8 9 10 + datasets + cityscapes + leftImg8bit + gtFine + tfrecord + exp + train_on_train_set + train + eval + vis
1 下载模型 官方提供了不少预训练模型
https://github.com/tensorflow/models/blob/master/research/deeplab/g3doc/model_zoo.md
这里以 deeplabv3_pascal_train_aug_2018_01_04
为例。
1 2 3 4 5 # From deeplab/datasets/cityscapes/ mkdir init_models cd init_models wget http://download.tensorflow.org/models/deeplabv3_cityscapes_train_2018_02_06.tar.gz tar zxf deeplabv3_cityscapes_train_2018_02_06.tar.gz
由于我是应用在cityscapes,下载的是cityscapes部分的xception_65
。
2 训练 新建 deeplab/datasets/cityscapes/exp/train_on_train_set/train.sh
,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 mkdir -p logs/ export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim now=$(date +"%Y%m%d_%H%M%S") python ../../../../train.py \ --logtostderr \ --training_number_of_steps=90000 \ --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=769 \ --train_crop_size=769 \ --train_batch_size=2 \ --num_clones=2 \ --dataset="cityscapes" \ --fine_tune_batch_norm=false \ --tf_initial_checkpoint="../../init_models/deeplabv3_cityscapes_train/model.ckpt" \ --train_logdir="train/" \ --dataset_dir="../../tfrecord/" 2>&1 | tee logs/train_$now.txt &
进入 deeplab/datasets/cityscapes/exp/train_on_train_set/
,
运行 sh train.sh
即可训练。
3 验证 可一边训练一边验证,注意使用其它的GPU或合理分配显存。
新建 deeplab/datasets/cityscapes/exp/train_on_train_set/eval.sh
,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 python ../../../../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=1025 \ --eval_crop_size=2049 \ --dataset="cityscapes" \ --checkpoint_dir="train/" \ --eval_logdir="eval/" \ --dataset_dir="../../tfrecord/" & # --max_number_of_evaluations=1 &
进入 deeplab/datasets/cityscapes/exp/train_on_train_set/
,
运行 CUDA_VISIBLE_DEVICES="1" sh eval.sh
即可验证(这里指定了第二个 GPU)。
4 可视化 log 可一边训练一边可视化训练的 log,访问 http://localhost:6006/ 即可看到 loss 等的变化。
1 2 # From deeplab/datasets/cityscapes/exp/train_on_train_set tensorboard --logdir train/
可视化验证的 log,可看到 miou_1.0 的变化,这里指定了另一个端口。
1 2 # From deeplab/datasets/cityscapes/exp/train_on_train_set tensorboard --logdir eval/ --port 6007
或同时可视化训练与验证的log:
1 2 # From deeplab/datasets/cityscapes/exp/train_on_train_set tensorboard --logdir .
5 可视化分割结果 可一边训练一边可视化分割结果。
新建 deeplab/datasets/cityscapes/exp/train_on_train_set/vis.sh
,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 python ../../../../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=1025 \ --vis_crop_size=2049 \ --dataset="cityscapes" \ --colormap_type="cityscapes" \ --checkpoint_dir="train/" \ --vis_logdir="vis/" \ --dataset_dir="../../tfrecord/" &
进入 deeplab/datasets/cityscapes/exp/train_on_train_set/
,
运行 sh vis.sh
即可生成分割结果,vis/segmentation_results/
里有彩色化的分割结果,vis/raw_segmentation_results/
里有原始的分割结果。
测试 1 导出模型 训练完成后得到一些 checkpoint 文件在 deeplab/datasets/cityscapes/exp/train_on_train_set/train/
中,如:
1 2 3 4 graph.pbtxt model.ckpt-1000.data-00000-of-00001 model.ckpt-1000.info model.ckpt-1000.meta
其中 meta 文件保存了 graph 和 metadata,ckpt 文件保存了网络的 weights。
而进行预测时只需模型和权重,不需要 metadata,故可使用官方提供的脚本生成推导图。
新建 deeplab/datasets/cityscapes/exp/train_on_train_set/export_model.sh
,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 python ../../../../export_model.py \ --logtostderr \ --checkpoint_path="train/model.ckpt-$1" \ --export_path="export/frozen_inference_graph-$1.pb" \ --model_variant="xception_65" \ --atrous_rates=6 \ --atrous_rates=12 \ --atrous_rates=18 \ --output_stride=16 \ --decoder_output_stride=4 \ --num_classes=19 \ --crop_size=769 \ --crop_size=769 \ --inference_scales=1.0
进入 deeplab/datasets/pascal_voc_seg/exp/train_on_train_set/
,
运行 sh export_model.sh 1000
即可导出模型 export/frozen_inference_graph-1000.pb
。
2 测试图片 运行 deeplab_demo.ipynb
并修改其中的各种路径即可。
或自写 inference
脚本,如 deeplab/datasets/cityscapes/exp/train_on_train_set/infer.py
。(不太确定label 0是不是background,待更)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 import sys sys.path.append('../../../../utils/') from matplotlib import pyplot as plt import numpy as np from PIL import Image import tensorflow as tf import get_dataset_colormap LABEL_NAMES = np.asarray([ 'unlabeled', 'road', 'sidewalk', 'building', 'wall', 'fence', 'pole', 'traffic light', 'traffic sign', 'vegetation', 'terrain', 'person', 'rider', 'car', 'truck', 'bus', 'train', 'motorcycle', 'bicycle' ]) FULL_LABEL_MAP = np.arange(len(LABEL_NAMES)).reshape(len(LABEL_NAMES), 1) FULL_COLOR_MAP = get_dataset_colormap.label_to_color_image(FULL_LABEL_MAP) class DeepLabModel(object): """Class to load deeplab model and run inference.""" INPUT_TENSOR_NAME = 'ImageTensor:0' OUTPUT_TENSOR_NAME = 'SemanticPredictions:0' INPUT_SIZE = 769 def __init__(self, model_path): """Creates and loads pretrained deeplab model.""" self.graph = tf.Graph() with open(model_path) as fd: graph_def = tf.GraphDef.FromString(fd.read()) with self.graph.as_default(): tf.import_graph_def(graph_def, name='') self.sess = tf.Session(graph=self.graph) def run(self, image): """Runs inference on a single image. Args: image: A PIL.Image object, raw input image. Returns: resized_image: RGB image resized from original input image. seg_map: Segmentation map of `resized_image`. """ width, height = image.size resize_ratio = 1.0 * self.INPUT_SIZE / max(width, height) target_size = (int(resize_ratio * width), int(resize_ratio * height)) resized_image = image.convert('RGB').resize(target_size, Image.ANTIALIAS) batch_seg_map = self.sess.run( self.OUTPUT_TENSOR_NAME, feed_dict={ self.INPUT_TENSOR_NAME: [np.asarray(resized_image)] }) seg_map = batch_seg_map[0] return resized_image, seg_map def vis_segmentation(image, seg_map): plt.figure() plt.subplot(221) plt.imshow(image) plt.axis('off') plt.title('input image') plt.subplot(222) seg_image = get_dataset_colormap.label_to_color_image( seg_map, get_dataset_colormap.get_pascal_name()).astype(np.uint8) plt.imshow(seg_image) plt.axis('off') plt.title('segmentation map') plt.subplot(223) plt.imshow(image) plt.imshow(seg_image, alpha=0.7) plt.axis('off') plt.title('segmentation overlay') unique_labels = np.unique(seg_map) ax = plt.subplot(224) plt.imshow( FULL_COLOR_MAP[unique_labels].astype(np.uint8), interpolation='nearest') ax.yaxis.tick_right() plt.yticks(range(len(unique_labels)), LABEL_NAMES[unique_labels]) plt.xticks([], []) ax.tick_params(width=0) plt.show() if __name__ == '__main__': if len(sys.argv) < 3: print('Usage: python {} image_path model_path'.format(sys.argv[0])) exit() image_path = sys.argv[1] model_path = sys.argv[2] model = DeepLabModel(model_path) orignal_im = Image.open(image_path) resized_im, seg_map = model.run(orignal_im) vis_segmentation(resized_im, seg_map)
运行以下命令即可:
1 2 3 4 # From deeplab/datasets/cityscapes/exp/train_on_train_set/ python infer.py \ ../../../../g3doc/img/image1.jpg \ export/frozen_inference_graph.pb
遇到的问题 小白入门deeplab,遇到好多傻问题,记录一下。
1 Import error 1 ImportError: No module named deeplab
在models/research/
路径下输入
1 export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
2 InvalidArgumentError 1 InvalidArgumentError (see above for traceback): Assign requires shapes of both tensors to match. lhs shape= [21] rhs shape= [19]
这是因为最后的num_classes
和 init model
的num_classes
不一致导致的。我这里是因为忘记把dataset改成cityscapes了。因为在segmenation_dataset.py
里面voc的num_classes
是21,我的init model
的num_classes
是cityscapes的,是19,所以会不match。
在写train.sh
文件的时候,加入下面这一行就解决了。
1 --dataset="cityscapes" \
3 Linux终止脚本进程 当ctrl+C
没有用时,可以用ps -ef | grep 进程名
查出进程,然后kill该进程。
kill 的用法:kill[信号代码]进程ID
注:信号代码可以省略;我们常用的信号代码是 -9 ,表示强制终止;
参考网页 linux停止正在执行脚本