天天看點

ckpt下載下傳 deeplabv3_TensorFlow DeepLabV3 訓練自己的資料分割模型

DeepLabV3+

deeplab v3+ 算是目前來說最先進的語義分割算法,盡管現在有精确到頭發絲的分割方法:Soft Semantic Segmentation. 但谷歌開源了deeplabv3+,我們可以直接使用不同的backbone和資料集來訓練我們自己的分割模型。如果你想做一個分割的應用,那這個方法再合适不過。

在開始之前,讓我們看看我們能做到的分割效果:

ckpt下載下傳 deeplabv3_TensorFlow DeepLabV3 訓練自己的資料分割模型
ckpt下載下傳 deeplabv3_TensorFlow DeepLabV3 訓練自己的資料分割模型

當然出來cityspcapes資料集之外你也可以放許多其他的資料集。包括我自己的車道線資料集,分割效果也還不錯,連左右車道線都能分割出來。接下來就教大家如何制作資料集吧。

資料集制作

首先這個資料集制作有個巨大的問題。假設你用labelme或者其他工具标注了你的資料,你的儲存标注可能是polygon的點,也可能是mask。這裡我推薦儲存polygon,因為deeplab中使用的label是單通道以你的類别的id為像素值的标簽,這也非常好了解。這裡貼一個核心代碼:

1import cv2

2import os

3import numpy as np

4import cv2

5import matplotlib.pyplot as plt

6

7cls_label_map = {

8    'background': 0,

9    'a': 1,

10    's': 2,

11    'f': 3,

12    'd': 4,

13    'j': 5,

14    'k': 6,

15    'l': 7,

16    'g': 8,

17    'p': 9,

18    'q': 10,

19    'o': 11,

20    'w': 12,

21    'h': 13,

22    '3': 14,

23}

24

25

26def gen_mask(polygons, img):

27    mask = np.zeros([img.shape[0], img.shape[1]], np.int32)

28    for p in polygons:

29        # cv2.polylines(img, p, 1, 255)

30        # fill polygon

31        pts = np.array(p[:-1])

32        cv2.fillPoly(mask, pts, cls_label_map[p[-1]])

33    return mask

這樣傳回就是label的mask。這個mask實際上是黑色的。咋一看like this:

ckpt下載下傳 deeplabv3_TensorFlow DeepLabV3 訓練自己的資料分割模型

仔細看是可以隐約看到車道線的。并且其實這裡的車道先不止一種類别。

關于label

關于label有幾點需要注意的,像素值就是label的index,從我的map也能看的出來。

除此之外沒了。另外,如果你的類别裡面沒有ignore_label, 那就直接是idx和0,0就是背景。如果有ignore_label就是255,相應的類别寫進去,顔色值為255就是ignore了。

這隻是第一步,接下來你的生成相應的tfrecords。這裡我也提供一個核心代碼,大家可以相應的進行一些更改。1import math

2import os.path

3import sys

4import build_data

5import tensorflow as tf

6

7FLAGS = tf.app.flags.FLAGS

8

9tf.app.flags.DEFINE_string('image_folder',

10                           './VOCdevkit/VOC2012/JPEGImages',

11                           'Folder containing images.')

12

13tf.app.flags.DEFINE_string(

14    'semantic_segmentation_folder',

15    './VOCdevkit/VOC2012/SegmentationClassRaw',

16    'Folder containing semantic segmentation annotations.')

17

18tf.app.flags.DEFINE_string(

19    'list_folder',

20    './VOCdevkit/VOC2012/ImageSets/Segmentation',

21    'Folder containing lists for training and validation')

22

23tf.app.flags.DEFINE_string(

24    'output_dir',

25    './tfrecord',

26    'Path to save converted SSTable of TensorFlow examples.')

27

28

29_NUM_SHARDS = 4

30

31def load_images_and_labels(d):

32    all_dirs = [i for i in os.listdir(d) if i.startswith('lane_2018')]

33    all_images = []

34    all_labels = []

35    for d in all_dirs:

36        img_dir = os.path.join(d, 'images')

37        label_dir = os.path.join(d, 'masks')

38        all_images.extend([os.path.join(img_dir, i) for i in os.listdir(os.path.join(d, 'images')) if i.endswith('jpg') or i.endswith('jpeg')])

39        all_labels.extend([os.path.join(img_dir, i) for i in os.listdir(os.path.join(d, 'masks')) if i.endswith('png')])

40    return all_images, all_labels

41

42

43def _convert_dataset(d):

44    '''Converts the specified dataset split to TFRecord format.

45

46    Args:

47      dataset_split: The dataset split (e.g., train, test).

48

49    Raises:

50      RuntimeError: If loaded image and label have different shape.

51    '''

52    sys.stdout.write('Processing...')

53

54    all_image_files, all_label_files = load_images_and_labels(d)

55

56    num_images = len(all_image_files)

57    num_per_shard = int(math.ceil(num_images / float(_NUM_SHARDS)))

58

59    image_reader = build_data.ImageReader('jpeg', channels=3)

60    label_reader = build_data.ImageReader('png', channels=1)

61

62    dataset = 'train'

63    for shard_id in range(_NUM_SHARDS):

64        output_filename = os.path.join(

65            FLAGS.output_dir,

66            '%s-%05d-of-%05d.tfrecord' % (dataset, shard_id, _NUM_SHARDS))

67        with tf.python_io.TFRecordWriter(output_filename) as tfrecord_writer:

68            start_idx = shard_id * num_per_shard

69            end_idx = min((shard_id + 1) * num_per_shard, num_images)

70            for i in range(start_idx, end_idx):

71                sys.stdout.write('\r>> Converting image %d/%d shard %d' % (

72                    i + 1, len(filenames), shard_id))

73                sys.stdout.flush()

74                # Read the image.

75                # image_filename = os.path.join(

76                #     FLAGS.image_folder, filenames[i] + '.' + FLAGS.image_format)

77                image_data = tf.gfile.FastGFile(all_image_files[i], 'rb').read()

78                height, width = image_reader.read_image_dims(image_data)

79                # Read the semantic segmentation annotation.

80                # seg_filename = os.path.join(

81                #     FLAGS.semantic_segmentation_folder,

82                #     filenames[i] + '.' + FLAGS.label_format)

83                seg_data = tf.gfile.FastGFile(all_label_files[i], 'rb').read()

84                seg_height, seg_width = label_reader.read_image_dims(seg_data)

85                if height != seg_height or width != seg_width:

86                    raise RuntimeError(

87                        'Shape mismatched between image and label.')

88                # Convert to tf example.

89                file_name = os.path.basename(all_image_files[i]).split('.')[0]

90                example = build_data.image_seg_to_tfexample(

91                    image_data, file_name, height, width, seg_data)

92                tfrecord_writer.write(example.SerializeToString())

93        sys.stdout.write('\n')

94        sys.stdout.flush()

95

96

97def main(unused_argv):

98    d = './'

99    _convert_dataset(d)

100

101if __name__ == '__main__':

102    tf.app.run()

這個代碼十分重要,直接将images和masks生成了相應的tfrecord。這個代碼中有一些關于路徑處理需要根據大家的實際需求修改,再次不敖訴。

deeplab搭建

clone一下models的代碼,然後把slim添加到PYTHON 裡面:

1export PYTHONPATH=$PYTHONPATH:/home/models/research/slim

在models/research下執行:1python3 deeplab/model_test.py

沒有問題的話就ok了。接下來要修改兩個檔案:segmentation_dataset.py

train_utils.py

修改segmentation_dataset.py的110行,添加對應的關于_CAMVID資料集的描述設定:

CamVid描述配置

1# segmentation_dataset.py line 110

2_CAMVID_INFORMATION = DatasetDescriptor(

3    splits_to_sizes={

4        'train': 367,  # num of samples in images/training

5        'val': 101,  # num of samples in images/validation

6    },

7    num_classes=12,

8    ignore_label=255,

9)

這裡我以CamVid資料集作為示範。這裡的類别是你的分割的類别,但是得加上ignore_label.

CamVid的列别是11類,加上ignore就是12類。

另外在加上:1DATASETS_INFORMATION = {

2    'cityscapes': _CITYSCAPES_INFORMATION,

3    'pascal_voc_seg': _PASCAL_VOC_SEG_INFORMATION,

4    'ade20k': _ADE20K_INFORMATION,

5    'mydata':_MYDATA_INFORMATION, #我自己的資料集

6    'camvid':_CAMVID_INFORMATION, #camvid示例

7}

注冊一下自己的資料集。更改就這兩處,大家代開檔案之後會看到。

更改一下train_utils.py:

1exclude_list = ['global_step','logits']

2if not initialize_last_layer:

3    exclude_list.extend(last_layers)

目的是在加載與訓練的模型的時候不需要top,這個最好更改一下,因為你的類别跟cityscapes不同。

Train

萬事具備隻欠東風了。直接開始訓練,訓練的執行路徑在 models/research下面,我們運作:1python3 deeplab/train.py \

2    --logtostderr \

3    --training_number_of_steps=300 \

4    --train_split='train' \

5    --model_variant='xception_65' \

6    --atrous_rates=6 \

7    --atrous_rates=12 \

8    --atrous_rates=18 \

9    --output_stride=16 \

10    --decoder_output_stride=4 \

11    --train_crop_size=513 \

12    --train_crop_size=513 \

13    --train_batch_size=2 \

14    --dataset='minieye_lane' \

15    --tf_initial_checkpoint='deeplab/checkpoints/deeplabv3_cityscapes_train/model.ckpt'\

16    --train_logdir='./deeplab/log' \

17    --dataset_dir='./deeplab/tfrecord'

相應的與訓練模型下載下傳位址為:https://github.com/tensorflow/models/blob/master/research/deeplab/g3doc/model_zoo.md

然後傳入tfrecord路徑即可開始訓練。。