Selective Searchを使った映像からの物体検出にチャレンジ

Selective Search

こんにちは。

AI coordinatorの清水秀樹です。

物体検出にチャレンジしている筆者としては、どうやって画像から物体らしき部分を効率よく抽出できるかを日々模索しています。

PepperではOpenCVのカスケードファイルを使用することで、手軽に人の顔や人物の抽出ができました。

R-CNNを「Tensorflow x Pepper」で実装する方法

 

また、動体の物体検出であればフレーム間差分でも取得出来るかと考えています。

カメラ映像から動く物体の輪郭検出が簡単にできた話

 

ただ静止画も含めた色々な物体を検出するとなると、もう少し工夫が必要になります。

そこで、物体検出方法について以前から試してみたかったSelective Searchという手法を今回試してみたので、その内容を紹介したいと思います。

簡単に試せるので、興味がある方はチャレンジしてみてください。

 

参考にさせて頂いたサイトの紹介

GitHubに紹介されていたソースを使いました。

詳しい説明は以下のサイトを参照ください。

 

環境準備

いつも環境準備で苦労するのですが、今回あっさりできました。

以下のコマンドでselectivesearchをインストールしましょうl

pip install selectivesearch

 

mac Python 3.5.2 |Anaconda で開発しています。

 

実行結果

サンプルのソースコードをそのまま使用すると、scikit-imageを使用するように指定されているので、宇宙服を着た女性の画像がいきなり出力されます。

import skimage.data
img = skimage.data.astronaut()

今回一番はまったところはこの画像部分ですね。

自分の好きな画像で試すにはどうすれば良いのかわからず、少し調べ回りました。

結局img=の指定を以下のようにすれば、自分で準備した画像を選択できます。

img = skimage.data.imread('1.jpg')

ただ、デジカメで撮った画像なんかだと、サイズがでかくてエラーとなります。

パラメーターの指定で解決するとは思いますが、よくわからなかったので、読み込ませる画像を適当に縮小して使用しました。

 

以下ソースコード(参考元サイトをほぼそのまま流用)と使用した画像の結果です。

# -*- coding: utf-8 -*-
import skimage.data
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import selectivesearch


def main():

    # loading astronaut image
    #img = skimage.data.astronaut()
    img = skimage.data.imread('1.jpg')

    # perform selective search
    img_lbl, regions = selectivesearch.selective_search(
        img, scale=500, sigma=0.9, min_size=10)

    candidates = set()
    for r in regions:
        # excluding same rectangle (with different segments)
        if r['rect'] in candidates:
            continue
        # excluding regions smaller than 2000 pixels
        if r['size'] < 2000:
            continue
        # distorted rects
        x, y, w, h = r['rect']
        if w / h > 1.2 or h / w > 1.2:
            continue
        candidates.add(r['rect'])

    # draw rectangles on the original image
    fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
    ax.imshow(img)
    for x, y, w, h in candidates:
        print(x, y, w, h)
        rect = mpatches.Rectangle(
            (x, y), w, h, fill=False, edgecolor='red', linewidth=1)
        ax.add_patch(rect)

    plt.show()

if __name__ == "__main__":
    main()

 

なるほどなるほど。

あえて複雑な画像を入力してみましたが、色々な箇所を検出してくれるみたいです。

 

ただし、画像サイズが大きすぎたせいか、結果が出力されるまでに時間がかかりました。

だいたい30秒ぐらいですね。

一般的かどうかわかりませんが、今ままでの経験上、画像認識は画像サイズを縮小して学習モデルを作成することが多いです。

また、認識させたい画像の入力もリサイズ(縮小)して使用することが多いので、さすがに横2000ピクセルは大きすぎるみたいですね。

 

というわけで、横300ピクセルで試してみました。

すると、約1秒で結果が出力されました。

結果が出力されるまで、かなり早くなりましたが、物体検出される箇所も変わるようです。

物体検出領域が随分減り、少し雑?になった感じですね。

 

まあ、当然といえば当然の結果なんだと思います。

より詳細により多くの物体を検出したければ、大きいサイズの画像の方が精度が出るのでしょう。

ただ、処理速度を失う感じになるので、そこはマシンパワーとの相談になるかと思います。

 

映像からの物体検出にチャレンジ

さて、事前準備が完了したので、OpenCVとselectivesearchを使って映像からの物体検出にチャレンジしたいと思います。

以下のソースコードで実装しました。

# -*- coding: UTF-8 -*-
import cv2
import selectivesearch

cap = cv2.VideoCapture(0)
height = 180
width  = 320

def main():
    while(True):

        # 動画ストリームからフレームを取得
        ret, frame = cap.read()
        
        # カメラ画像をリサイズ
        img = cv2.resize(frame,(width,height))

        # perform selective search
        img_lbl, regions = selectivesearch.selective_search(
            img, scale=500, sigma=0.9, min_size=10)

        candidates = set()
        for r in regions:
            # excluding same rectangle (with different segments)
            if r['rect'] in candidates:
                continue
            # excluding regions smaller than 2000 pixels
            if r['size'] < 2000:
                continue
            # distorted rects
            x, y, w, h = r['rect']
            if w / h > 1.2 or h / w > 1.2:
                continue
            candidates.add(r['rect'])
        
        #画像への枠作成
        for region in candidates:
            x,y,w,h = region
            color = (100, 200, 100)
            cv2.rectangle(img, (x,y), (x+w, y+h), color, thickness=2)
            
        cv2.imshow("camera window", img) 

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

if __name__ == '__main__':
    main()

PCからのwebカメラで実装しています。

画像サイズを小さくしているので、処理速度も中々良い感じです。

実際の出力映像を掲載したいのですが、自宅の部屋の中で実施したので割愛します。

 

興味がある方はぜひお試しあれ。

 

この物体検出領域の抽出については、これからも色々と模索していきたいと思います。

 


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

 

それではまた。

あなたにオススメの記事

コメント

  1. この記事へのコメントはありません。

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

PAGE TOP