LoginSignup
15
15

More than 1 year has passed since last update.

Detectron2ではじめる画像の物体検出とセグメンテーション

Last updated at Posted at 2022-02-12

はじめに

最近, Detectron2を用いて画像の物体検出とセグメンテーションを行ったのですが, 日本語の記事が少なく実装に苦労した部分があったため, 今回は物体検出とセグメンテーションに関して基本的な操作をまとめておきたいと思います.

補足 今回は実装に焦点を当てるため画像処理やニューラルネットワークの専門的な話は盛り込んでいません

Detectron2とは?


Detectron2とは,FacebookAIが開発したPyTorchベースの物体検出ライブラリで,物体検出・セグメンテーション・その他の視覚認識タスクのためのプラットフォームです. 現在はオープンソースとして公開されています. 詳細はこちらで確認できます.

記事概要

・Google Colaboratoryの立ち上げ
・Detectron2の設定
・画像の物体検出とセグメントの実装

必要事項

・Googleアカウント
・Pythonの基礎知識
・PyTorch,Numpy,CV2の基礎知識
・対象の画像ファイル

GoogleColaboratoryの立ち上げ

GoogleColaboratory (以下Colab) とは

Googleが提供しているGoogleドライブ上でのpythonの実行環境 (JupyterNotebook仕様) で,時間制限はあるものの高性能なTeslaのGPUを無料で使うことができます. Colabの詳細はこちらで確認できます.

GoogleDriveとの接続

image_processing.ipynbのセル1
from google.colab import drive
drive.mount("/content/drive")
  1. 上記セル実行後表示されるURLにアクセス
  2. アカウントを選択しドライブの接続を許可
  3. ドライブが実行環境にマウント

以上の手順を踏むことでドライブ上のファイルやフォルダーをColab上で操作できるようになります.

注意 以降のコードはランタイムにGPUを使用します

Detectron2の設定

Detectron2のインストール

コードはDetectron2のチュートリアルを参照します

image_processing.ipynbのセル2
!pip install pyyaml==5.1
import torch
# Install detectron2 that matches the above pytorch version
!pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/$CUDA_VERSION/torch$TORCH_VERSION/index.html

Detectron2のモジュールをインストール

image_processing.ipynbのセル3
import detectron2
from detectron2.utils.logger import setup_logger
setup_logger()

# 訓練済みモデル選択モジュールModelZoo(https://github.com/facebookresearch/detectron2/blob/main/MODEL_ZOO.md)
from detectron2 import model_zoo
from detectron2.engine import DefaultPredictor
from detectron2.config import get_cfg
from detectron2.utils.visualizer import Visualizer
from detectron2.data import MetadataCatalog, DatasetCatalog

続いて画像を扱うモジュールをインストール

image_processing.ipynbのセル4
# import some common libraries
import numpy as np
import os, json, cv2, random
# colab上ではcv2オブジェクトの表示に特にcv2_imshowを用いる
from google.colab.patches import cv2_imshow

学習器の作成(model)

image_processing.ipynbのセル5
# 学習モデルの読み込み(モデルはCOCOフォーマット)
cfg = get_cfg()
cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
# threshold:閾値
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")

# 学習器を作成(model)
predictor = DefaultPredictor(cfg)

今回の目的は物体検出とセグメントなので, モデルは訓練時間が比較的早く, 精度も割に高めのmask_rcnnのR_50FPNを用いる設定になっています. その他のモデルについてはこちらで確認できます.

画像の物体検出とセグメントの実装

それでは実装していきます. 今回使用する画像はこちらです
宇宙猫withブロッコリー.jpg
この画像からcv2オブジェクトを作成し, 学習器を通してみましょう.

image_processing.ipynbのセル6
file_dir = "/content/drive/MyDrive/Detectron2_test/宇宙猫withブロッコリー.jpg"
img = cv2.imread(file_dir)
# 学習器で推定する
output = predictor(img)

outputについて出力してみます.
2022-02-12_22h17_42.png

出力結果の詳細を確認する

ここから, outputの中身を覗いていきます.
まず, outputの構造は辞書形式でその中にInstanceオブジェクトが入っています. ( Instanceオブジェクトの詳細はこちら) そして, Instanceオブジェクトの中にはnum_instance, image_height, image_width, fieldsが確認できます. また, fieldsにおいて次の要素が確認できます.

名前 構造 内容
pred_box tensor( list ) 推定した物体のBoundig Box
scores tensor( list ) 推定した物体の類似度
pred_classes tensor( list ) 推定された物体名のカテゴリーID
fields tensor( list ) 推定した物体のBitmap

推定された物体名を確認

この要素をもとに, 推定された物体名を確認してみましょう.
物体名はリストで保存されています. これらはdetectron2のdataにおけるMetadataCatalogで取得することができます.

image_processing.ipynbのセル7
# このclasses_listのindexと物体のカテゴリーIDが対応しています
classes_list= MetadataCatalog.get(cfg.DATASETS.TRAIN[0]).thing_classes

objects = []
for id in output["instances"]._fields["pred_classes"].tensor.cpu().numpy():
  obj = classes_list[id]
  objects.append(obj)
# 推定した物体名のリスト
object_est = [(k,i) for k,i in zip(objects,output["instances"]._fields["scores"].tensor.cpu().numpy())]

出力結果( object_est )

物体名 類似度
0 broccoli 0.99425983
1 cat 0.99423665
2 broccoli 0.9931277
3 broccoli 0.99076086
4 broccoli 0.9890274
5 bird 0.9842605
6 bird 0.68304986
7 broccoli 0.4676876

セグメンテーションを行う

先ほど予測した物体が画像ではどこになるのか可視化してみましょう.

1. BoundingBoxでセグメント
image_processing.ipynbのセル9
# boundign boxの取得 -> 物体の[左上座標, 左下座標, 右上座標, 右下座標]
bounding_boxes = outputs["instances"]._fields["pred_boxes"].tensor.cpu().numpy()
# 上書き用に画像をコピー
img_copy = img
# 検出した物体数反復する
for i in range(len(bounding_boxes)):
  # 左上座標
  left_pt = tuple(bounding_boxes[i][0:2])
  # 右下座標
  right_pt = tuple(bounding_boxes[i][2:4])
  # cv2.putText(img_copy, f'{i}', left_pt, cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 5, cv2.LINE_AA)
  # 範囲を枠線で囲む
  cv2.rectangle(img_copy,left_pt,right_pt,(0,0,155),1)

cv2_imshow(img_copy)

出力
neko_bounding_box.jpg
ここで, 物体名の際に作成した表と, 位置を比べてみると5,6が鳥と誤認されていますね. 予測した物体名が必ずしも正しいとは言えないでしょう.
[ 再掲 ]

物体名 類似度
0 broccoli 0.99425983
1 cat 0.99423665
2 broccoli 0.9931277
3 broccoli 0.99076086
4 broccoli 0.9890274
5 bird 0.9842605
6 bird 0.68304986
7 broccoli 0.4676876

より特定の物体を正しく推定するためにファインチューニングを行うといった方法がありますが, 今回は触れません. 興味のある方はこちらの記事を参考にするとよいかもしれません.

2. BitMapでセグメント
image_processing.ipynbのセル10
object_estimation = object_est
dct = {file_dir:object_estimation}
# ビットマップの抽出
bool_array = output["instances"]._fields["pred_masks"]

for j,b_array in enumerate(bool_array):
  try:
    # tensorをnumpy配列に変換
    array = b_array.cpu().numpy()
    # 論理値の反転
    inv_bool_array = []
    for l in array:
      inv_b = []
      for b in l:
        if b == False:
          inv_b.append(True)
        else:
          inv_b.append(False)
      inv_bool_array.append(inv_b)
    # cv2オブジェクトはnumpy配列なので,正(true)を灰色に変換
    copy_img = img.copy()
    copy_img[inv_bool_array] = [128,128,128]

出力( 左上から右に出力順 )
2022-02-13_00h30_44.png

3. Visulizerモジュールでセグメント( Bounding box + Bitmap)
image_processing.ipynbのセル8
# We can use `Visualizer` to draw the predictions on the image.
v = Visualizer(img[:, :, ::-1], MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=1.0)
out = v.draw_instance_predictions(output["instances"].to("cpu"))
# image[:, :, ::-1]はRGBをBGRへ変換している
cv2_imshow(out.get_image()[:, :, ::-1])

出力結果
neko.jpg
ここまで出来たらいろいろな画像処理ができそうですね.

さいごに

今回は画像の物体検出とセグメンテ―ションをDetectron2を用いて実装していきました. 画像処理やニューラルネットワークの専門的な知識がなくても手軽に実装でき, 画像処理の技術は誰でも使える時代になりつつあるなと感じました. 技術者でなくとも画像処理の活用を積極的に検討していきたいですね.

参考URL

15
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
15