Mask R-CNNを簡単にカメラ映像から試す方法

Mask R-CNNを実際に動かしてみよう

こんにちは。

AI coordinatorの清水秀樹です。

現時点でおそらく最新最強の物体検出であるMask R-CNNを簡単に試せる方法を紹介します。

難しい論文なんぞ読まなくても、ここで紹介している手順通りに実行するだけでMask R-CNNを動かすことができるようになります。

Mask R-CNNの仕組みについては他のサイトに任せるとして、ここでは一切触れていません。

単純に動かすことだけに特化した記事となります。

また、すでに公開済みのGitHubからただ動かすだけでは面白くないので、webカメラからでも動くようにカスタマイズしたソースコードも合わせて紹介します。

興味がある方は試してみてください。

 

成功すれば以下の画像のように、物体の輪郭にそった物体検出ができるようになります。

いよいよ映画のターミネーターばりの画像処理が現実的になってきました。

開発環境

なんでもそうですが、この開発環境の準備が一番苦労します。

筆者もここが一番苦労します。

ただし、開発環境さえ揃えてしまえば、後はソースを動かすだけで試すことができますので頑張ってみましょう。

以下に、筆者の開発環境をゴチャゴチャと記載しておきます。

  • Mac (27-inch, Late 2012)
  • プロセッサ 2.9 GHz intel Core i5
  • macOS Sierra バージョン 10.12.4
  • conda 4.3.29
  • python 3.5.2
  • keras 2.0.8
  • tensorflow
  • Jupyter Notebook
  • Numpy, skimage, scipy, Pillow, cython, h5py 1.3.0

GitHubからMask R-CNNのソースコードをダウンロード

まずはMask R-CNNを紹介しているGitHubからソースコードをダウンロードしましょう。

ダウンロードしたフォルダ内に、「demo.ipynb」があるので、何も考えずにjupyter notebookで実行してみましょう。

まずは動かしてみるという気持ちが、何をやるにも重要な姿勢かと思います。

実行すると以下のようなエラーが出ます。

No module named 'pycocotools'

このエラーを解消するにはCOCOAPIのインストールが必要になりますので、GitHubからダウンロードしてインストールしましょう。

GitHubからダウンロードが完了したら、

cocoapi-master>PythonAPI>setup.py

のsetup.pyを実行してインストールしましょう。

以下のコマンドのみで作業は完了します。

$ python setup.py install

これで先ほどのエラーが解消されるはずです。

 

では再度、「demo.ipynb」を起動しましょう。

続いて以下のようなエラーが出た方は、kerasのバージョンが古い可能性があります。

No module named 'keras.initializers'

というか古いから出力されるエラーです。

kerasを2.0.8にバージョンアップしましょう。

筆者は何も考えず、以下のコマンドでkerasのバージョンアップを実施しました。

conda install keras

 

続いてtensorflowのバージョンアップも必要です。

以下のコマンドでtensorflowもバージョンアップしましょう。

conda install -c conda-forge tensorflow=1.3

 

さて、この状態で再度「demo.ipynb」を実行しても、以下のエラーが発生します。

URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)>

なんじゃこりゃっ!て感じのエラーですが、エラーメッセージをよく確認すると”mask_rcnn_coco.h5″のダウンロードができなかったよ!というようなエラーメッセージがあることが分かるかと思います。

ということで、”mask_rcnn_coco.h5″を手動でダウンロードしましょう。

ちなみに、”mask_rcnn_coco.h5とは学習モデルのことを指します。

“mask_rcnn_coco.h5″もGitHubで公開されています。

GitHubにアクセスし、上記画像の赤枠で囲ってあるh5ファイルをダウンロードしましょう。

ダウンロードしたら、「demo.ipynb」を同じディレクトリに保存します。

これで環境準備が整いました。

実行結果

3度目の正直で「demo.ipynb」を起動してみましょう。

今度はうまく行くはずです。

無事処理が終了すると、以下のようが画像がjupyter notebook上に表示されます。(画像はランダムに選ばれて表示されます)

すげー!!

感動です。

今までは、矩形で囲んだだけの物体検出でしたが、Mask R-CNNでは輪郭まで検出できています。

この分野はみるみる進化するので、追っていて楽しいですね。

 

映像からのMask R-CNN

続いてカメラ映像からのMask R-CNNを試してみましょう。

PC内蔵カメラからでも動画からでも実行できます。

ソースコードを適当に作成してみました。

とりあえず動けばなんでも良い感じで作成しています。

import os
import sys
import random
import math
import numpy as np
import skimage.io
import matplotlib
import matplotlib.pyplot as plt

import coco
import utils
import model as modellib

import cv2
import colorsys

ROOT_DIR = os.getcwd()
MODEL_DIR = os.path.join(ROOT_DIR, "logs")

COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5")
if not os.path.exists(COCO_MODEL_PATH):
    utils.download_trained_weights(COCO_MODEL_PATH)

class InferenceConfig(coco.CocoConfig):
    GPU_COUNT = 1
    IMAGES_PER_GPU = 1

config = InferenceConfig()

model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
model.load_weights(COCO_MODEL_PATH, by_name=True)

class_names = ['BG', 'person', 'bicycle', 'car', 'motorcycle', 'airplane',
               'bus', 'train', 'truck', 'boat', 'traffic light',
               'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird',
               'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear',
               'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie',
               'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball',
               'kite', 'baseball bat', 'baseball glove', 'skateboard',
               'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup',
               'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
               'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza',
               'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed',
               'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote',
               'keyboard', 'cell phone', 'microwave', 'oven', 'toaster',
               'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors',
               'teddy bear', 'hair drier', 'toothbrush']
 
#cap = cv2.VideoCapture("1.mp4")
cap = cv2.VideoCapture(0)

height = 720
width  = 1280

def random_colors(N, bright=True):
    brightness = 1.0 if bright else 0.7
    hsv = [(i / N, 1, brightness) for i in range(N)]
    colors = list(map(lambda c: colorsys.hsv_to_rgb(*c), hsv))
    random.shuffle(colors)
    return colors

def apply_mask(image, mask, color, alpha=0.5):
    for c in range(3):
        image[:, :, c] = np.where(mask == 1,
                                  image[:, :, c] *
                                  (1 - alpha) + alpha * color * 255,
                                  image[:, :, c])
    return image

def display_instances(image, boxes, masks, class_ids, class_names,
                      scores=None, title="",
                      figsize=(16, 16), ax=None):
    N = boxes.shape[0]
    if not N:
        print("\n*** No instances to display *** \n")
    else:
        assert boxes.shape[0] == masks.shape[-1] == class_ids.shape[0]

    colors = random_colors(N)

    masked_image = image.copy()
    for i in range(N):
        color = colors[i]

        # Bounding box
        if not np.any(boxes[i]):
            continue
        y1, x1, y2, x2 = boxes[i]
        camera_color = (color[0] * 255, color[1] * 255, color[2] * 255)
        cv2.rectangle(masked_image, (x1, y1), (x2, y2), camera_color , 1)

        # Label
        class_id = class_ids[i]
        score = scores[i] if scores is not None else None
        label = class_names[class_id]
        x = random.randint(x1, (x1 + x2) // 2)
        caption = "{} {:.3f}".format(label, score) if score else label
        camera_font = cv2.FONT_HERSHEY_PLAIN
        cv2.putText(masked_image,caption,(x1, y1),camera_font, 1, camera_color)

        # Mask
        mask = masks[:, :, i]
        masked_image = apply_mask(masked_image, mask, color)

    return masked_image.astype(np.uint8)

def main():
    while(True):
 
        # 動画ストリームからフレームを取得
        ret, frame = cap.read()
        
        # カメラ画像をリサイズ
        image_cv2 = cv2.resize(frame,(width,height))
        
        results = model.detect([image_cv2])

        r = results[0]
        camera = display_instances(image_cv2, r['rois'], r['masks'], r['class_ids'], 
                            class_names, r['scores'])

        cv2.imshow("camera window", camera) 
 
        # escを押したら終了。
        if cv2.waitKey(1) == 27:
            break
    
    #終了
    cap.release()
    cv2.destroyAllWindows()
 
 
if __name__ == '__main__':
    main()

cap = cv2.VideoCapture(0)を指定していますので、PC内臓のwebカメラが起動するはずです。

動画にしたい場合は、cap = cv2.VideoCapture(‘move.mp4’)といった指定をすれば、動画でもMask R-CNNを試せます。

興味がある方はぜひ挑戦してみてください。

 

それではまた。

 


その他の物体検出記事はこちらから

あなたにオススメの記事

コメント

    • 豊田計時
    • 2019年 4月 28日

    【開発環境】Windows10,Python3.6.8
          NEC NS150/D

    映像からのMask R-CNNを行うために、貴殿サイト
    http://ai-coordinator.jp/mask-r-cnn
    に掲載されているプログラムを実行しました。
    当初いくつかのエラーが出てそれはつぶしたので
    ですが、まだ以下のエラーが発生します。

    【発生エラー】AttributeError
    module ‘coco’ has no attribute ‘CocoConfig’

    なぜ’coco’が’CocoConfig’の属性を持たないのか
    意味がわかりません。理由はともかく、修正法に
    ついてご教示いただけますと幸いです。

    ソースを以下に示します。

    import os
    import sys
    import random
    import math
    import numpy as np
    import skimage.io
    import matplotlib
    import matplotlib.pyplot as plt
    #sys.path.insert(0, ‘/path/to/samples/coco’)
    #from pycocotools.coco import coco
    import pycocotools.coco
    import coco
    import utils
    import mrcnn.model as modellib
    import cv2
    import colorsys

    ROOT_DIR = os.getcwd()
    MODEL_DIR = os.path.join(ROOT_DIR, “logs”)

    COCO_MODEL_PATH = os.path.join(ROOT_DIR, “mask_rcnn_coco.h5″)
    if not os.path.exists(COCO_MODEL_PATH):
    utils.download_trained_weights(COCO_MODEL_PATH)

    class InferenceConfig(coco.CocoConfig):
    GPU_COUNT = 1
    IMAGES_PER_GPU = 1

    config = InferenceConfig()
    config.display()
    model = modellib.MaskRCNN(mode=”inference”, model_dir=MODEL_DIR, config=config)
    model.load_weights(COCO_MODEL_PATH, by_name=True)

    class_names = [‘BG’, ‘person’, ‘bicycle’, ‘car’, ‘motorcycle’, ‘airplane’,
    ‘bus’, ‘train’, ‘truck’, ‘boat’, ‘traffic light’,
    ‘fire hydrant’, ‘stop sign’, ‘parking meter’, ‘bench’, ‘bird’,
    ‘cat’, ‘dog’, ‘horse’, ‘sheep’, ‘cow’, ‘elephant’, ‘bear’,
    ‘zebra’, ‘giraffe’, ‘backpack’, ‘umbrella’, ‘handbag’, ‘tie’,
    ‘suitcase’, ‘frisbee’, ‘skis’, ‘snowboard’, ‘sports ball’,
    ‘kite’, ‘baseball bat’, ‘baseball glove’, ‘skateboard’,
    ‘surfboard’, ‘tennis racket’, ‘bottle’, ‘wine glass’, ‘cup’,
    ‘fork’, ‘knife’, ‘spoon’, ‘bowl’, ‘banana’, ‘apple’,
    ‘sandwich’, ‘orange’, ‘broccoli’, ‘carrot’, ‘hot dog’, ‘pizza’,
    ‘donut’, ‘cake’, ‘chair’, ‘couch’, ‘potted plant’, ‘bed’,
    ‘dining table’, ‘toilet’, ‘tv’, ‘laptop’, ‘mouse’, ‘remote’,
    ‘keyboard’, ‘cell phone’, ‘microwave’, ‘oven’, ‘toaster’,
    ‘sink’, ‘refrigerator’, ‘book’, ‘clock’, ‘vase’, ‘scissors’,
    ‘teddy bear’, ‘hair drier’, ‘toothbrush’]

    #cap = cv2.VideoCapture(“1.mp4”)
    cap = cv2.VideoCapture(0)

    height = 720
    width = 1280

    def random_colors(N, bright=True):
    brightness = 1.0 if bright else 0.7
    hsv = [(i / N, 1, brightness) for i in range(N)]
    colors = list(map(lambda c: colorsys.hsv_to_rgb(*c), hsv))
    random.shuffle(colors)
    return colors

    def apply_mask(image, mask, color, alpha=0.5):
    for c in range(3):
    image[:, :, c] = np.where(mask == 1,
    image[:, :, c] *
    (1 – alpha) + alpha * color[c] * 255,
    image[:, :, c])
    return image

    def display_instances(image, boxes, masks, class_ids, class_names,
    scores=None, title=””,
    figsize=(16, 16), ax=None):
    N = boxes.shape[0]
    if not N:
    print(“\n*** No instances to display *** \n”)
    else:
    assert boxes.shape[0] == masks.shape[-1] == class_ids.shape[0]

    colors = random_colors(N)

    masked_image = image.copy()
    for i in range(N):
    color = colors[i]

    # Bounding box
    if not np.any(boxes[i]):
    continue
    y1, x1, y2, x2 = boxes[i]
    camera_color = (color[0] * 255, color[1] * 255, color[2] * 255)
    cv2.rectangle(masked_image, (x1, y1), (x2, y2), camera_color , 1)

    # Label
    class_id = class_ids[i]
    score = scores[i] if scores is not None else None
    label = class_names[class_id]
    x = random.randint(x1, (x1 + x2) // 2)
    caption = “{} {:.3f}”.format(label, score) if score else label
    camera_font = cv2.FONT_HERSHEY_PLAIN
    cv2.putText(masked_image,caption,(x1, y1),camera_font, 1, camera_color)

    # Mask
    mask = masks[:, :, i]
    masked_image = apply_mask(masked_image, mask, color)

    return masked_image.astype(np.uint8)

    def main():
    while(True):

    # 動画ストリームからフレームを取得
    ret, frame = cap.read()

    # カメラ画像をリサイズ
    image_cv2 = cv2.resize(frame,(width,height))

    results = model.detect([image_cv2])

    r = results[0]
    camera = display_instances(image_cv2, r[‘rois’], r[‘masks’], r[‘class_ids’],
    class_names, r[‘scores’])

    cv2.imshow(“camera window”, camera)

    # escを押したら終了。
    if cv2.waitKey(1) == 27:
    break

    #終了
    cap.release()
    cv2.destroyAllWindows()

    if __name__ == ‘__main__’:
    main()

    お手数ですが、宜しくお願い致します。
    【引用】http://ai-coordinator.jp/mask-r-cnn

  1. この記事へのトラックバックはありません。

PAGE TOP