MMDetectionでtools/test.py
を用いて得られたInstance segmentationの結果はhoge.bbox.json
とhoge.segm.json
に保存されます。(test.pyなどの詳しい使い方については公式documentを参考にしてください。)
$ python tools/test.py config/my_config.py checkpoints/my_config_weight.pth --options "jsonfile_prefix=results/hoge"
hoge.segm.json
からsegmentation領域の情報を取り出すのに手間取ったためまとめておきます。
inference_detector
を用いた場合も同様に取り出せます。
筆者環境
- WSL2 on windows11
- ubuntu 20.04
- docker
- pytorch 1.11.0+cu113
- MMDetection 2.23.0
- cuda 11.3
- GCC 7.3
Instance segmentationの結果について
MMDetectionではInstance segmentationの結果は、hoge.bbox.json
とhoge.segm.json
といったjson
形式で出力されます。
Instance segmentationのtaskでは、segmentationした領域のピクセル数(≒面積)やそのポリゴンの形に興味がある場合があります。
hoge.segm.json
にsegmentationした領域の情報が入っていることは明らかなので中身を見てみます。
{"image_id": 0,
"bbox": [587.4173583984375, 327.16925048828125, 326.24078369140625, 441.67816162109375],
"score": 0.9949996471405029,
"category_id": 0,
"segmentation":
{"size": [2048, 1323],
"counts": "f^nT1k1mm1c0@>D8H7I6I7J7I8H6J6K4L4L4L5K6J6J7I6I6K5J5L5K4L5K3N3L3N2M4M3M2N4L2N3M2N1O2M3N3M2M4M2M4M4L4L4L3M3M2O1N2N3M2N2N1O2N2O0O2N1O2O1N2N2O1N3M2O2M3N2M4M1N2O1O1N2O1O1N2O1O1N2O0O2N2O1N2N2N2O1N2N2O1N101N2O001N101O0O2O0O2O1O0O2O1O2N1N3N1O2N2N2M2O1O1O1N10001N10001O0O101O00001O00001O00010O00001O0000001O0O10001O00000O2O0001O01O000010O01O001O01O0001O0O100000000000000010O00001O001O001O001O00001O0O101O00001O000O2O00001N101O001N101O0O2O001N101O0O2O001O0O2O00001N101N101N2O0O2N101N2N101N2O0O2O1N101N2N101N2N2N2N2N3L3N2M4M2M4L4L3N2N2N2N2N101N1O2O1N2N101N2N102M2N2M4L4K6J6J5J7K5K3N3M2N2N3M2N2N3M2N3M3M4L4J7I6I6J6K5L4L4L5J5L5K7H8E:G8H9I6J8I7H8I8G8^Ob0F;Fg0VOY_ki0"}
}
{"image_id": 0,
"bbox": [509.74078369140625, 747.2927856445312, 271.965576171875, 288.40106201171875],
"score": 0.15585921704769135,
"category_id": 0,
"segmentation":
{"size": [2048, 1323],
"counts": "[k^Q16go1?A;E9D7J7M3M2M4N1N3L5L4K6J3K4M4M3N2O0O100O1O2O0O1O1O1N2O2M2O2M2O2M4L5L5K4L1O2O0O100O1O100O1O1O1N2N3M2N2N3N1O1O2N100O10000O10000O100O2O1N2N2M3M3N3L4M3L4N0O100O100O100O10000O3N1N2N101N101N100O2O0000000000000O1000001O0O2O001N101O1O00000O2O0000001O00001O1O100O1O1O1O2N1O000000000001O0O100000001O100O001O010O001O001O000O2O001O001N2O1N3M2N2N3M3L4M3L3N2O1O000O2O001O001O003L5K5L3L3N2M3N1N2SKWUNa4Uk1N2O0O100O2O0N2O2N1O2M3M3L5M2N3L3N3M3M3M2N2M3M3M3L4N2N2N2N2N2N1O2N2N2N1O2L3K6K5N2M4M6I9H9F^T[R1"}
},...
- image_id:画像を特定するためのid
- bbox:バウンディングボックスの形。 [中心のx座標, 中心のy座標, 幅, 高さ]の順
- score:バウンディングボックスが正しく判定されている確率
- category_id:検出した物体がどのカテゴリに属しているかを表すid
- segmentation:
RLE形式
で書かれたsegmentation領域の情報- size:segmentation領域の[幅,高さ]
- counts:
RLE形式
にencodeされたポリゴン座標
image_isからcategory_idまではobject detectionのtaskでも同様に出力されます(hoge.bbox.json
)。
今回興味があるのはsegmentationした領域なのでsegmentation
の内容を読み解く必要があります。
しかしこのままではRLE形式
にエンコードされていて読み解けません。そのためデータ形式の変換が必要です。
RLE形式からdecode
まず、pycocotools
をインストールします。
$ pip install cython
$ git clone https://github.com/cocodataset/cocoapi.git
$ cd cocoapi/PythonAPI/
$ make install
$ python setup.py install
上記のコマンドでpycocotools
をインストールできます。
次にhoge.segm.json
を読み込みます。
import json
json_open = open("hoge.segm.json")
json_load = json.load(json_open)
segm = json_load[0] #今回は1つだけ取り出します。
print(segm)
{"image_id": 0,
"bbox": [587.4173583984375, 327.16925048828125, 326.24078369140625, 441.67816162109375],
"score": 0.9949996471405029,
"category_id": 0,
"segmentation":
{"size": [2048, 1323],
"counts": "f^nT1k1mm1c0@>D8H7I6I7J7I8H6J6K4L4L4L5K6J6J7I6I6K5J5L5K4L5K3N3L3N2M4M3M2N4L2N3M2N1O2M3N3M2M4M2M4M4L4L4L3M3M2O1N2N3M2N2N1O2N2O0O2N1O2O1N2N2O1N3M2O2M3N2M4M1N2O1O1N2O1O1N2O1O1N2O0O2N2O1N2N2N2O1N2N2O1N101N2O001N101O0O2O0O2O1O0O2O1O2N1N3N1O2N2N2M2O1O1O1N10001N10001O0O101O00001O00001O00010O00001O0000001O0O10001O00000O2O0001O01O000010O01O001O01O0001O0O100000000000000010O00001O001O001O001O00001O0O101O00001O000O2O00001N101O001N101O0O2O001N101O0O2O001O0O2O00001N101N101N2O0O2N101N2N101N2O0O2O1N101N2N101N2N2N2N2N3L3N2M4M2M4L4L3N2N2N2N2N101N1O2O1N2N101N2N102M2N2M4L4K6J6J5J7K5K3N3M2N2N3M2N2N3M2N3M3M4L4J7I6I6J6K5L4L4L5J5L5K7H8E:G8H9I6J8I7H8I8G8^Ob0F;Fg0VOY_ki0"}
}
次にpycocotools
を使ってdecodeします。
import pycocotools.mask as mask
maskedArr = mask.decode(segm["segmentation"]) #segmentation部分のみがdecode対象のため
print(type(maskedArr))
print(maskedArr)
<class `numpy.ndarray`>
[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
pycocotools.mask.decode
によりRLE形式
をnumpy形式
に変換することができました。
maskedArr
にsegmentationした領域が描画された配列が格納されているので、あとはopencv
などを使って面積などの特徴量を取得することができます。
inference_detector
を用いた場合
# Use the detector to do inference
img = 'demo/demo.jpg'
result = inference_detector(model, img)
MMDetectionのチュートリアルノートブックでは上記のようにしてInstance segmentationを行います。result
に結果が入っている状態です。
result
はbboxとsegmの情報が格納されています。
bbox, segm = results
print(bbox[0])
print(segm[0])
array([[2.38843811e+02, 9.87134094e+01, 2.49885818e+02, 1.08494499e+02,
1.03378251e-01], dtype=float32)
[array([[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False],
...,
[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False],
[False, False, False, ..., False, False, False]])]
- bbox:バウンディングボックスの内容+確率[中心のx座標, 中心のy座標, 幅, 高さ, 確率]
- segm:
bool型
で領域を描写
ここからsegm
を一度RLE形式
にencodeします。
from mmdet.core import encode_mask_results
encode_result = (bbox, encode_mask_results(segm))
- encode_result[0]:bboxの配列
- encode_result[1]:
RLE形式
のsegmentation領域の情報
となるので、あとはencode_result[1]
を上記のpycocotools.mask.decode
を用いて変換してやれば終わりです。
さいごに
今回はMMDetectionでのInstance segmentationの結果を取り出す方法についてまとめました。
間違いなどあればご指摘いただけると幸いです。
ありがとうございました。
参考URL