ITや趣味など気軽に投稿しています。

【python】OpenCVで物体検知 – Mask R-CNN

今回は推論モデルを用いた物体検知をやってみる。

推論モデル?

学習済みモデルのことだな。今回は物体検知なので、自動車とか人とかの特徴を学習したモデルのことを言う。

それを使って自動車とかを検知するってことですね!
早速やってみましょう。

Mask R-CNN

物体検出・クラス識別

Mask-RCNNとは深層学習のモデルの1つで、入力された画像に対して決められた(予め指定した)種類の物体を認識し、画像中のどこに何の物体が写っているかを特定するものだ。
「どこに映っているか?」が物体検出、「何が映っているか?」がクラス識別となる。

車とか人とかを検出できるあれですね。これってどうやって検出してるんですか?

細かい原理には触れないが、厳密には物体を認識しているというより、画像から物体らしき領域を検出している。

処理としては、画像を特定の領域に区切り、すべての領域で物体らしきものかを評価していく
クラスについても同様で、学習データに含まれるすべてのクラスをそれぞれ評価し、何の物体かを特定していく。

意外と肉弾戦なんですね。。

肉弾戦ができることがコンピュータのいいところだからな。このとき物体らしい領域は大量に検出されるが、「物体らしさ」が指定の閾値を超える領域のみに絞ることで、精度の高い検出結果を得ることができる

物体検出とクラス識別

セグメンテーション

先ほどの物体検出はある領域ごとだったが、セグメンテーションではピクセルごとにクラス検出を実施する

さらに細かい単位でも検出できるんですか(驚)

うむ。ただし、先ほどの物体検出の結果物体と認められた領域にのみ実施することで、効率化を図っている。

セグメンテーション

物体として検出された四角のなかで、さらに車のピクセルには色が塗りつぶされているだろう。これがセグメンテーションの結果だ。

Pythonで実装する

学習済みモデルとサンプルコードのダウンロード

Mask-RCNNの学習モデルを作成するのはなかなかハードルが高いが、便利なことに学習済みモデルが提供されている。特別な要件がある場合等を除けば、ある程度の精度で検出できる学習済みモデルも十分利用可能だろう。

モデルが用意されているなんて、ありがたいですね。

今回はlearnopencvというサイトがGithub上で提供するモデルと、サンプルコードを利用する。

https://github.com/spmallick/learnopencv

ダウンロードしたzipファイルを解凍すると、様々な画像解析プログラムが含まれている。今回はMask-RCNNフォルダのものを使用する。

実行前の準備

プログラムを実行する前に、以下をダウンロードして同フォルダに展開しておく必要がある。

http://download.tensorflow.org/models/object_detection/mask_rcnn_inception_v2_coco_2018_01_28.tar.gz

tar.gz形式なので、Windowsの場合は7-Zipなどツールが必要ですね。

画像の物体検知

まずは画像の物体検知からやってみよう。インプットになるのは以下のような画像だ。

cars.jpg

プログラムの実行はコマンドプロンプトで行う。Mask-RCNNフォルダへ移動し、以下コマンドを実行する。
実行結果はcars_mask_rcnn_out_py.jpgというファイルで保存される。

python mask_rcnn.py --image=cars.jpg
cars_mask_rcnn_out_py.jpg

動画の物体検知

続いては動画で物体検知をやってみる。インプットの動画は以下だ。

画像の場合と同様にコマンドプロンプトで以下コマンドを実行する。

python mask_rcnn.py --video=cars.mp4

学習済みモデルでも、かなりの精度が出ていますね~~

動画の物体検知(MP4で出力したい場合)

動画の処理結果はAVI形式で出力されるが、MP4で出力したい場合はmask_rcnn.pyの130行目、144行目及び151行目の.aviを.mp4に変更すればよい。

#mask_rcnn.pyの130行目~
outputFile = "mask_rcnn_out_py.mp4"
if (args.image):
    # Open the image file
    if not os.path.isfile(args.image):
        print("Input image file ", args.image, " doesn't exist")
        sys.exit(1)
    cap = cv.VideoCapture(args.image)
    outputFile = args.image[:-4]+'_mask_rcnn_out_py.jpg'
elif (args.video):
    # Open the video file
    if not os.path.isfile(args.video):
        print("Input video file ", args.video, " doesn't exist")
        sys.exit(1)
    cap = cv.VideoCapture(args.video)
    outputFile = args.video[:-4]+'_mask_rcnn_out_py.mp4'
else:
    # Webcam input
    cap = cv.VideoCapture(0)
#151行目部分
# Get the video writer initialized to save the output video
if (not args.image):
    vid_writer = cv.VideoWriter(outputFile, cv.VideoWriter_fourcc('m', 'p', '4', 'v'), 49, (round(cap.get(cv.CAP_PROP_FRAME_WIDTH)),round(cap.get(cv.CAP_PROP_FRAME_HEIGHT))))

まとめ

Mask-RCNNとPythonでのプログラム実行について紹介したが、Mask-Rcnnのポイントは以下の通りだ。

・Mask-RCNNでは物体検出及びクラス識別を行い、その後セグメンテーションを実施する。
・「どこに映っているか?」が物体検出、「何が映っているか?」がクラス識別となる。
・物体検出及びクラス識別画像を特定の領域に区切り、すべての領域で物体らしきものかを評価していく。
・「物体らしさ」が指定の閾値を超える領域のみに絞ることで、精度の高い検出結果を得ることができる。
・セグメンテーションではピクセルごとにクラス検出を実施する。
・物体検出の結果物体と認められた領域にのみ実施することで、効率化を図っている。

肉弾戦で物体検出はするけれど、効率的にセグメンテーションを行っている印象です。

そうだな。Pythonでの実装サンプルも提供されているので、取り掛かりやすい題材でもあると思う。インプットに使用する映像次第で精度に影響が出る可能性がある。必要に応じて前処理等実施してほしい。

今回はここまでにしよう。

ありがとうございました~~♪