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を試せます。
興味がある方はぜひ挑戦してみてください。
それではまた。
その他の物体検出記事はこちらから
【開発環境】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