MMSegmentationを使ってみた　Training編

## はじめに

https://qiita.com/ryosao/items/2e25eb93abb9b29ae3fa

からの続きで、今回はトレーニングの実行を行っていきたいと思います。

チュートリアルは、「Standord Background Dataset」というものを使っていましたが、今回はPascalVOCのデータセットを使って、「deeplabv2plus」を使ってみたいと思います。

次回は、オリジナルのデータセットを使って試してみようかと思います。

MMSegmentationのセットアップについては、前回の記事を参照してください。

## Pascal VOCの準備

今回は、Pascal VOC2012のデータセットを使ってみたいと思います。
概要やダウンロードについては、以下を参照してください。
https://lib-arts.hatenablog.com/entry/dataset_ml3　

Pascal VOC2012の場合、学習用のイメージは'JPEGImages'に、
アノテーションのイメージは、'SegmentationClass'に入っています。


```Python
import os.path as osp
import numpy as np
from PIL import Image
import mmcv
import matplotlib.pyplot as plt
# convert dataset annotation to semantic segmentation map
data_root = 'xxxxx' # Pascal VOCのフォルダを指定します。
img_dir = 'JPEGImages'
ann_dir = 'SegmentationClass'
```

## コンフィグの編集

今回は、Deeplabv3pulsを使い、PascalVOC2012を使うので以下のコンフィグを選択します。
'configs/deeplabv3plus/deeplabv3plus_r50-d8_512x512_20k_voc12aug.py'


VOC2012というものがなく、VOC2012augとなっていましたが、こちらは見つからなかったので
上記コンフィグを以下のように修正します。

```Python
_base_ = [
    '../_base_/models/deeplabv3plus_r50-d8.py',
    #'../_base_/datasets/pascal_voc12_aug.py', '../_base_/default_runtime.py',
    '../_base_/datasets/pascal_voc12.py', '../_base_/default_runtime.py',

    '../_base_/schedules/schedule_20k.py'
]
model = dict(
    decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21))
```

修正後、コンフィグを読み込みます。

```Python:
from mmcv import Config
cfg = Config.fromfile('configs/deeplabv3plus/deeplabv3plus_r50-d8_512x512_20k_voc12aug.py')
```

コンフィグの修正を行います。
チュートリアルに記載の項目を並べていますが、今回設定した箇所は、

dataset_typeを「PascalVOCDataset」、
data_root上で設定したPascalVOCをダウンロードしたパスに設定
image_dir、ann_dirも上設定したものに設定

学習済みデータから学習を始める場合は、
以下のMMSegmentationのコンフィグページから各モデルのページに移動した後、学習済みモデルへのリンクが貼られています。
https://github.com/open-mmlab/mmsegmentation/tree/master/configs 



```Python
from mmseg.apis import set_random_seed

# Since we use ony one GPU, BN is used instead of SyncBN
cfg.norm_cfg = dict(type='BN', requires_grad=True)
cfg.model.backbone.norm_cfg = cfg.norm_cfg
cfg.model.decode_head.norm_cfg = cfg.norm_cfg
cfg.model.auxiliary_head.norm_cfg = cfg.norm_cfg

# 分類するクラス数（独自に作成したカスタムデータセットの場合は変更してください。）
#cfg.model.decode_head.num_classes = 8
#cfg.model.auxiliary_head.num_classes = 8

# データセットの種類とパスを設定
cfg.dataset_type = 'PascalVOCDataset'
cfg.data_root = data_root

cfg.data.samples_per_gpu = 4
cfg.data.workers_per_gpu=4


cfg.data.train.type = cfg.dataset_type
cfg.data.train.data_root = cfg.data_root
cfg.data.train.img_dir = img_dir
cfg.data.train.ann_dir = ann_dir
cfg.data.train.pipeline = cfg.train_pipeline
#cfg.data.train.split = 'splits/train.txt'

cfg.data.val.type = cfg.dataset_type
cfg.data.val.data_root = cfg.data_root
cfg.data.val.img_dir = img_dir
cfg.data.val.ann_dir = ann_dir
cfg.data.val.pipeline = cfg.test_pipeline
#cfg.data.val.split = 'splits/val.txt'

cfg.data.test.type = cfg.dataset_type
cfg.data.test.data_root = cfg.data_root
cfg.data.test.img_dir = img_dir
cfg.data.test.ann_dir = ann_dir
cfg.data.test.pipeline = cfg.test_pipeline
#cfg.data.test.split = 'splits/val.txt'

# We can still use the pre-trained Mask RCNN model though we do not need to
# use the mask branch
cfg.load_from = 'https://download.openmmlab.com/mmsegmentation/v0.5/deeplabv3plus/deeplabv3plus_r50-d8_512x512_40k_voc12aug/deeplabv3plus_r50-d8_512x512_40k_voc12aug_20200613_161759-e1b43aa9.pth'

# Set up working dir to save files and logs.
cfg.work_dir = './work_dirs/tutorial'

#cfg.runner.max_iters = 200
#cfg.log_config.interval = 10
#cfg.evaluation.interval = 200
#cfg.checkpoint_config.interval = 200

# Set seed to facitate reproducing the result
cfg.seed = 0
set_random_seed(0, deterministic=False)
cfg.gpu_ids = range(1)

# Let's have a look at the final config used for training
print(f'Config:\n{cfg.pretty_text}')
```

## モデルの学習

定義したモデルを学習します。

```Python
from mmseg.datasets import build_dataset
from mmseg.models import build_segmentor
from mmseg.apis import train_segmentor


# Build the dataset
datasets = [build_dataset(cfg.data.train)]

# Build the detector
model = build_segmentor(
    cfg.model, train_cfg=cfg.get('train_cfg'), test_cfg=cfg.get('test_cfg'))
# Add an attribute for visualization convenience
model.CLASSES = datasets[0].CLASSES

# Create work_dir
mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))
train_segmentor(model, datasets, cfg, distributed=False, validate=True, 
                meta=dict())
```

以下のような結果となりました。
訓練済みモデルを使ったので、もうちょっと精度が出るはずなんですが、今回はとりあえず動かしてみるということで話を進めます。
修正点があれば、後ほど修正します。

2021-xx-xx 19:42:45,850 - mmseg - INFO - 
+-------------+-------+-------+
|    Class    |  IoU  |  Acc  |
+-------------+-------+-------+
|  background | 81.32 | 88.28 |
|  aeroplane  | 46.71 | 56.09 |
|   bicycle   |  0.07 |  0.07 |
|     bird    | 21.17 | 32.36 |
|     boat    | 27.94 | 43.89 |
|    bottle   | 11.81 | 15.67 |
|     bus     | 59.47 | 83.44 |
|     car     | 49.13 | 64.26 |
|     cat     | 34.55 | 72.64 |
|    chair    |  1.33 |  1.39 |
|     cow     | 20.61 | 26.24 |
| diningtable | 24.23 |  39.8 |
|     dog     |  7.93 |  9.43 |
|    horse    | 22.01 | 31.72 |
|  motorbike  |  35.9 |  73.1 |
|    person   | 49.87 | 70.56 |
| pottedplant |  4.75 | 13.69 |
|    sheep    | 30.99 | 74.26 |
|     sofa    | 17.27 | 26.65 |
|    train    | 45.96 | 61.44 |
|  tvmonitor  | 18.09 | 65.33 |
+-------------+-------+-------+
2021-xx-xx 19:42:45,851 - mmseg - INFO - Summary:
2021-xx-xx 19:42:45,856 - mmseg - INFO - 
+-------+------+-------+
|  aAcc | mIoU |  mAcc |
+-------+------+-------+
| 78.27 | 29.1 | 45.25 |

## 結果の確認

適当な訓練画像を使って、予測を行います。

```Python
from mmseg.apis import inference_segmentor, init_segmentor, show_result_pyplot
from mmseg.core.evaluation import get_palette

img = mmcv.imread('Path/JPEGImages/2007_000033.jpg') # 画像のパスを記載

model.cfg = cfg
result = inference_segmentor(model, img)
plt.figure(figsize=(8, 6))
show_result_pyplot(model, img, result, get_palette('pascal_voc'))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004109/43732a19-b1d4-e4d0-5c5e-82c058a0ee65.png)

対象の中では、精度がいい方である飛行機の画像を使ってみました。
他のものは、あまり認識できていなかったようです。。

https://qiita.com/ryosao/items/d753a7d2c01f4c3f520f