MS COCO datasetのフォーマットまとめ

# 概要
- MicrosoftのCommon Objects in Contextデータセット（通称MS COCO dataset）のフォーマットに準拠したオリジナルのデータセットを作成したい場合に、どの要素に何の情報を記述して、どういう形式で出力するのが適切なのかがわかりづらかったため、実例を交えつつ各要素の内容を網羅的にまとめました。

# 背景
- 例えば、GitHubで公開されている特定のプログラムでオリジナルのデータセットを読み込むと問題は無いのに、別のプログラムやpycocotools、その他のアノテーションツール等で読み込むと特定の要素が無かったり、データ型が異なったりしてエラーが出る問題がしばしばあるので、「このルールでデータセットを作成しておけば間違いない」という基準のようなものを整理しておきたかった というのが本記事を作成した動機です。

# はじめに
- [COCO dataset](https://cocodataset.org/#download)からダウンロードできる"2017 Train/Val annotations"のファイルに含まれる*person_keypoints_val2017.json*より、以下の画像（id=153669）とアノテーションを基準に解説していく。<br/>
<img width=640 alt="000000153669.jpg" src="http://images.cocodataset.org/val2017/000000153669.jpg">
<br/>
<img width=640 alt="アノテーション描画結果" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/88b7607d-9631-80c5-b463-6ade2eac7ca5.jpeg">

# COCO datasetのJSONフォーマット
- 全体としては以下のような構造になっており、以降の項目でこの5つの要素の内容を説明していく。

```python:
{
	"info": {...},
	"licenses": [
		{...},{...}
	],
	"images": [
		{...},{...},{...},{...}
	],
	"annotations": [
		{...},{...},{...},{...},{...},{...},{...},{...},{...}
	],
	"categories": [
		{...},{...},{...}
	]
}
```

## 1. "info"
- **info**ではデータセット全体の情報（メタデータ）を記述する。

```python:
"info": {
	"description": "COCO 2017 Dataset"
	"url": "http://cocodataset.org",
	"version": "1.0",
	"year": 2017,
	"contributor": "COCO Consortium",
	"date_created": "2017/09/01"
},
```

:::note warn
この"info"の要素だけリスト型ではないので注意
:::

##### `"description"`
- データセットの説明

##### `"url"`
- データセットの掲載されているWebサイトのURL

##### `"version"`
- データセットのバージョン

##### `"year"`
- データセットの公開年

##### `"contributor"`
- データセットの作成者

##### `"date_created"`
- データセットの作成年月日


## 2. "licenses"
- **licenses**ではデータセットに含まれる画像のライセンス情報をリスト内に列挙する。

```python:
"licenses": [
	{
		"url": "http://creativecommons.org/licenses/by-nc-sa/2.0/",
		"id": 1,
		"name": "Attribution-NonCommercial-ShareAlike License"
	},
	...
],
```
##### `"url"`
- ライセンスの内容が記載されているWebページのURL

##### `"id"`
- データセット内で定義するライセンスID

##### `"name"`
- ライセンス名

:::note info
例えば、person_keypoints_val2017.jsonには、以下の8つのライセンスが記述されている
:::

| id | name | url |
|:---|:-----|:----|
|1|Attribution-NonCommercial-ShareAlike License|http://creativecommons.org/licenses/by-nc-sa/2.0/|
|2|Attribution-NonCommercial License|http://creativecommons.org/licenses/by-nc/2.0/|
|3|Attribution-NonCommercial-NoDerivs License|http://creativecommons.org/licenses/by-nc-nd/2.0/|
|4|Attribution License|http://creativecommons.org/licenses/by/2.0/|
|5|Attribution-ShareAlike License|http://creativecommons.org/licenses/by-sa/2.0/|
|6|Attribution-NoDerivs License|http://creativecommons.org/licenses/by-nd/2.0/|
|7|No known copyright restrictions|http://flickr.com/commons/usage/|
|8|United States Government Work|http://www.usa.gov/copyright.shtml|


## 3. "images"
- **images**ではデータセットに含まれる画像の情報をリスト内に列挙する。

```python:
"images": [
	{
		"license": 6,
		"file_name": "000000153669.jpg",
		"coco_url": "http://images.cocodataset.org/val2017/000000153669.jpg",
		"height": 427,
		"width": 640,
		"date_captured": "2013-11-19 19:44:15",
		"flickr_url": "http://farm5.staticflickr.com/4023/4659511777_06fdc54df9_z.jpg",
		"id": 153669
	},
	...
],
```

##### `"license"`
- 画像のライセンスID（**licenses**の`"id"`と紐付く）

##### `"file_name"`
- 画像のファイル名（ゼロ埋めの数値をファイル名にしておくと問題が生じにくい）

##### `"coco_url"`
- 実際に扱う画像のURL

##### `"height"`, `"width"`
- 実際に扱う画像の縦横ピクセル値（これは`"coco_url"`側のサイズであり、`"flickr_url"`側(=オリジナル画像）のサイズではないので注意）

##### `"date_captured"`
- 画像を撮影または取得した日時

##### `"flickr_url"`
- オリジナル画像のURL

##### `"id"`
- 画像を一意に特定するID（`"file_name"`から拡張子を削除してint型の数値にしたものにしておくと問題が生じにくい）


## 4. "annotations"
- **annotations**ではデータセットに含まれるアノテーションの情報をリスト内に列挙する。

```python:
"annotations": [
	{
		"segmentation": [
			[..................]
		],
		"num_keypoints": 14,
		"area": 27981.57385,
		"iscrowd": 0,
		"keypoints": [.........],
		"image_id": 153669,
		"bbox": [341.76, 55.14, 216.05, 348.74],
		"category_id": 1,
		"id": 1271401,
		"caption": "a batter after he has hit a pitched ball before he is going to run"
	},
	...
],
```

##### `"segmentation"`
- 対象のオブジェクトをセグメンテーションした際の頂点座標x,yを結んで列挙する形（ポリゴンの形式）で記述したもの
- 具体的には[x1, y1, x2, y2, ...]といった形でx,y座標群が並ぶ。
- 次の画像のように、対象の1つのオブジェクトの部位が遮蔽物などで2つ以上に分断される場合は、以下のように別のリストにして追加する形で記述する。<br/>
<img width="640" alt="分断されたオブジェクトの例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/10d3cf4c-a368-5b5f-2c50-e216586ce03e.jpeg">

```python:
		"segmentation": [
			[a_x1, a_y1, a_x2, a_y2, ...], #部位aの領域
			[b_x1, b_y1, b_x2, b_y2, ...]  #部位bの領域
		],
```

- なお、後述する`"iscrowd"`が1の場合は、以下のように"counts"と"size"の2要素で記述する。

```python:
		"segmentation": {
			"counts": [x1, y1, x2, y2, ...],
			"size": [427, 640]
		},
```

:::note warn
上記の"counts"はポリゴンではなく非圧縮RLE(Run Length Encoding)※で記述することが正しいらしいが、person_keypoints_val2017.jsonではポリゴンで記述されているので、扱うプログラムによって注意が必要
:::

（参考）このあたりで議論されている
　・https://github.com/cocodataset/cocoapi/issues/135
　・https://github.com/facebookresearch/Detectron/issues/100

:::note info
※非圧縮RLEの記法は以下の動画を参照
（この点以外もMS COCO datasetの構造について詳しく解説されている）
https://www.youtube.com/watch?v=h6s61a_pqfM&t=934s

具体的には、画像の左上から1行ずつ右方向に走査していったときに、例えば、非オブジェクトのピクセルが147回連続して登場し、次にオブジェクト（crowdに該当する領域）のピクセルが3回連続して登場し、再び非オブジェクトのピクセルが1回登場し、…といった場合に [147, 3, 1, ...] と記述するような方式
:::

- ちなみに、1つの`"image_id"`に対して、複数のアノテーションが紐付いているため、例えばimage_id=153669に紐付く14のセグメンテーション領域を全て描画すると以下のようになる。<br/>
<img width="640" alt="全セグメンテーション領域描画結果" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/3029dc85-5800-da80-8f70-1eda3c27c921.png">



##### `"num_keypoints"`
- 有効な`"keypoints"`の数（位置が不明な`"keypoints"`を除外した数）

##### `"area"`
- セグメンテーション領域内の合計ピクセル数

##### `"iscrowd"`
- アノテーション対象のオブジェクトが複数(1)か否(0)かを示すフラグ（通常は0）
 - iscrowd=1となっているアノテーションの具体例（セグメンテーション領域の描画結果）を以下に示す。<br/>
<img width=640 alt="群衆アノテーションの例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/b6c2ac33-74b6-71f9-5002-704dc5d4c452.png">

##### `"keypoints"`
- 主に人物の関節を表し、関節の位置する座標x,yと状態v（0:不明, 1:不可視(遮蔽), 2:可視）のセットが17点並ぶ（COCO datasetの場合）
- 関節位置が不明(v=0)の場合は(x,y)=(0,0)で記述される。
- 登場する各点がどの関節を表すかは、後述する**categories**の中で定義する。
 - 参考までにpycocotoolsのshowAnns()を使って、1つのアノテーションにおける実際の関節の座標を、セグメンテーションの領域とともに描画した結果を以下に示す。<br/>
<img width=640 alt="キーポイント描画結果" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17245/759cf4a7-59ee-ae61-a58c-97fd0750bda2.png">

##### `"image_id"`
- アノテーション対象の画像ID（**images**の`"id"`と紐付く）
- 画像1枚につき1つ以上のアノテーションが存在するため、**annotations**内では`"image_id"`は重複する。

##### `"bbox"`
- 対象のオブジェクトを囲むバウンディングボックスの左上の頂点座標とサイズ（x, y, width, heightの順番）

##### `"category_id"`
- 対象のオブジェクトが何であるかを示すカテゴリID
- category_id=1はpersonを意味する。詳細は後述する**categories**の内容を参照。

##### `"id"`
- アノテーションを一意に特定するためのID
- **images**の`"id"`と被ると扱いがややこしくなるので、なるべく`"image_id"`と被らない数値や文字列にした方が良い。

##### `"caption"`
- 画像の内容を説明するキャプション（ *captions_val2017.json* などで記述されている要素）


## 5. "categories"
- **categories**ではデータセットに含まれるカテゴリの情報をリスト内に列挙する。

```python:
"categories": [
	{
		"supercategory": "person",
		"id": 1,
		"name": "person",
		"keypoints": [
			"nose","left_eye","right_eye","left_ear","right_ear",
			"left_shoulder","right_shoulder",
			"left_elbow","right_elbow","left_wrist","right_wrist",
			"left_hip","right_hip",
			"left_knee","right_knee","left_ankle","right_ankle"
		],
		"skeleton": [
			[16,14],[14,12],[17,15],[15,13],[12,13],[6,12],[7,13],[6,7],
			[6,8],[7,9],[8,10],[9,11],[2,3],[1,2],[1,3],[2,4],[3,5],[4,6],[5,7]
		]
	},
	...
]
```

##### `"supercategory"`
- カテゴリ名の上位のカテゴリ
- 例えば、カテゴリが"bicycle"や"car"の場合、上位カテゴリは"vehicle"という風になる。

##### `"id"`
- カテゴリID

:::note info
person_keypoints_val2017.jsonにおいては、カテゴリIDはid=1の"person"しか登場しないが、COCO datasetとしては以下の91種類のカテゴリが定義されている
:::

###### COCO dataset カテゴリ 91種類一覧

|id| supercategory |　name　|
|:-|:--------------|:----|
1 |person    |person        |
2 |vehicle   |bicycle       |
3 |vehicle   |car           |
4 |vehicle   |motorcycle    |
5 |vehicle   |airplane      |
6 |vehicle   |bus           |
7 |vehicle   |train         |
8 |vehicle   |truck         |
9 |vehicle   |boat          |
10|outdoor   |traffic light |
11|outdoor   |fire hydrant  |
12|outdoor   |street sign*  |
13|outdoor   |stop sign     |
14|outdoor   |parking meter |
15|outdoor   |bench         |
16|animal    |bird          |
17|animal    |cat           |
18|animal    |dog           |
19|animal    |horse         |
20|animal    |sheep         |
21|animal    |cow           |
22|animal    |elephant      |
23|animal    |bear          |
24|animal    |zebra         |
25|animal    |giraffe       |
26|animal    |hat*          |
27|accessory |backpack      |
28|accessory |umbrella      |
29|accessory |shoe*         |
30|accessory |eye glasses*  |
31|accessory |handbag       |
32|accessory |tie           |
33|accessory |suitcase      |
34|sports    |frisbee       |
35|sports    |skis          |
36|sports    |snowboard     |
37|sports    |sports ball   |
38|sports    |kite          |
39|sports    |baseball bat  |
40|sports    |baseball glove|
41|sports    |skateboard    |
42|sports    |surfboard     |
43|sports    |tennis racket |
44|kitchen   |bottle        |
45|kitchen   |plate*        |
46|kitchen   |wine glass    |
47|kitchen   |cup           |
48|kitchen   |fork          |
49|kitchen   |knife         |
50|kitchen   |spoon         |
51|kitchen   |bowl          |
52|food      |banana        |
53|food      |apple         |
54|food      |sandwich      |
55|food      |orange        |
56|food      |broccoli      |
57|food      |carrot        |
58|food      |hot dog       |
59|food      |pizza         |
60|food      |donut         |
61|food      |cake          |
62|furniture |chair         |
63|furniture |couch         |
64|furniture |potted plant  |
65|furniture |bed           |
66|furniture |mirror*       |
67|furniture |dining table  |
68|furniture |window*       |
69|furniture |desk*         |
70|furniture |toilet        |
71|furniture |door*         |
72|electronic|tv            |
73|electronic|laptop        |
74|electronic|mouse         |
75|electronic|remote        |
76|electronic|keyboard      |
77|electronic|cell phone    |
78|appliance |microwave     |
79|appliance |oven          |
80|appliance |toaster       |
81|appliance |sink          |
82|appliance |refrigerator  |
83|appliance |blender*      |
84|indoor    |book          |
85|indoor    |clock         |
86|indoor    |vase          |
87|indoor    |scissors      |
88|indoor    |teddy bear    |
89|indoor    |hair drier    |
90|indoor    |toothbrush    |
91|indoor    |hair brush*   |

- *印は、論文では定義されているがJSONでは記載されていないカテゴリ

##### `"name"`
- カテゴリ名

##### `"keypoints"`
- キーポイントの順番（=ID）と名称

:::note info
COCO datasetにおけるキーポイントは17点だが、その他のデータセットではキーポイントの位置と数、IDが異なるため、参考までにその対応関係を記載しておく
:::

###### COCO dataset キーポイント 対応表

|  | MS COCO<br/>dataset | MPII Human Pose<br/>Dataset | Leeds Sports Pose<br/>Dataset | VGG Human<br/>Pose Estimation<br/>datasets |
|:-|:--------------------|:----------------------------|:------------------------------|:----|
|head top       |- |9 |14|○|
|nose           |1 |- |- |-|
|left_eye       |2 |- |- |-|
|right_eye      |3 |- |- |-|
|left_ear       |4 |- |- |-|
|right_ear      |5 |- |- |-|
|(upper) neck   |- |8 |13|-|
|thorax         |- |7 |- |-|
|left_shoulder  |6 |13|10|○|
|right_shoulder |7 |12|9 |○|
|left_elbow     |8 |14|11|○|
|right_elbow    |9 |11|8 |○|
|left_wrist     |10|15|12|○|
|right_wrist    |11|10|7 |○|
|pelvis         |- |6 |- |-|
|left_hip       |12|3 |4 |-|
|right_hip      |13|2 |3 |-|
|left_knee      |14|4 |5 |-|
|right_knee     |15|1 |2 |-|
|left_ankle     |16|5 |6 |-|
|right_ankle    |17|0 |1 |-|

</div></details>

##### `"skeleton"`
- 描画のためのキーポイントの連結関係
- `"keypoints"`での記述順番がIDと対応するため、例えば[16,14]は"left_ankle"と"left_knee"を繋ぐことを意味する。

<br/>