MMDetectionで独自のCOCOデータセットを利用する

# はじめに

MMDetectionを利用するとほとんどコードを書かずに物体検出が出来そうだったので試してみました。

結果、独自のCOCOデータセットを利用するとかなり苦労し、独自のCOCOデータセットを使う場合の注意点をまとめた日本語情報もなさそうでしたので、備忘録をかねてここでまとめて見ようと思います。

MMDetectionの利用方法については、↓を参照しました。

https://qiita.com/iwatake2222/items/6a2bd0b599102502720a

また、COCOフォーマットの作成については、以下を参照ください。

https://qiita.com/harmegiddo/items/da131ae5bcddbbbde41f

# mmcv-fullのインストール

mmcvをインストールしただけではエラーになるようですのですので、以下のようにmmcv-fullをインストールする必要がるようです。
（公式のチュートリアルにも記載されていました。）

```python:
!pip install mmcv-full
```

公式サイト
https://mmdetection.readthedocs.io/en/latest/index.html

# cocoデータセットの配置

作成したcocoデータセットのアノテーションを以下の「annotations」フォルダに
イメージファイルを用途に応じて、train,bal、testフォルダに配置する。

mmdetection
├── data
│   ├── coco
│   │   ├── annotations
│   │   ├── train2017
│   │   ├── val2017
│   │   ├── test2017
│   │   ├── stuffthingmaps


# cocoデータセット設定の編集

デフォルトでは、公式のcocoデータセットの80クラス分類となるため、用意したデータのカテゴリ数が異なる場合は、以下のエラーとなります。

```python:
ValueError: need at least one array to concatenate
```

「faster_rcnn_r50_fpn_1x_coco.py」を利用する時を例に対処方を記載します。


mmdet/core/evaluation/class_names.pyに以下を追記
（'husky',''chihuahua','alaska'というラベルを使う場合の例）

```python:
def toby_classes():
    return ['husky',''chihuahua','alaska']

dataset_aliases = {
    'voc': ['voc', 'pascal_voc', 'voc07', 'voc12'],
    'imagenet_det': ['det', 'imagenet_det', 'ilsvrc_det'],
    'imagenet_vid': ['vid', 'imagenet_vid', 'ilsvrc_vid'],
    'coco': ['coco', 'mscoco', 'ms_coco'],
    'wider_face': ['WIDERFaceDataset', 'wider_face', 'WDIERFace'],
    'cityscapes': ['cityscapes'],
    'toby': ['toby']
}
```

mmdet/datasete/coco.pyのCocoDataset Classを対象のラベルに変更


```python:

class CocoDataset(CustomDataset):

   CLASSES = ('husky',''chihuahua','alaska')
```


mmdet/core/evaluation/__intit__.pyを以下のように「toby_classes」を追加

```python:
from .class_names import (cityscapes_classes, coco_classes, dataset_aliases,
                          get_classes, imagenet_det_classes,
                          imagenet_vid_classes, voc_classes, toby_classes)
from .eval_hooks import DistEvalHook, EvalHook
from .mean_ap import average_precision, eval_map, print_map_summary
from .recall import (eval_recalls, plot_iou_recall, plot_num_recall,
                     print_recall_summary)

__all__ = [
    'voc_classes', 'imagenet_det_classes', 'imagenet_vid_classes',
    'coco_classes', 'cityscapes_classes', 'dataset_aliases', 'get_classes',
    'DistEvalHook', 'EvalHook', 'average_precision', 'eval_map',
    'print_map_summary', 'eval_recalls', 'print_recall_summary',
    'plot_num_recall', 'plot_iou_recall', 'toby_classes'
]
```

mmdet/core/evaluation/mean_ap.py の436行目に以下のように「dataset = 'toby'を追記

```python:
 if dataset is None:
        label_names = [str(i) for i in range(num_classes)]
    elif mmcv.is_str(dataset):
        dataset = 'toby'    # this line
        label_names = get_classes(dataset)
    else:
        label_names = dataset

```

configs/_base_/models/faster_rcnn_r50_fpn.py　の46行目のnum_classesを80から出力するラベル数に変更

```python:
        bbox_head=dict(
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=3,

```

# 終わりに

これでカスタムのCOCOデータセットを使ってトレーニングができるようになりました。

よく読むとチュートリアルにカスタムデータセットの定義方法が記載されているようですが、出力数のみの変更であればこちらの方が楽でしょうか。

とりあえず、物体検出に初挑戦してみてみました。