Help us understand the problem. What is going on with this article?

Opencv: meanshift&CamShiftで遊んでみた♬

More than 1 year has passed since last update.

ちょっとしたことから、すごく使えそうな気がしてきて、今更ながらmeanshiftで遊んでみた。

つまり、構想はこれでターゲット物体捕捉して、物体認識もして表示すれば単品だけど、使えるかなということ。
まずは、Roiできるかがポイント。
【参考】
とりあえず、まんまかもだけど、インスピレーションをもらえた
1.Raspberry Pi サーボモーターとOpen CVで物体追跡カメラ(Meanshift)
ソースは以下の記事を参考にさせていただきました。
2.Python3 OpenCV3を使って物体検出

コードは以下に置きました

Video-Stream / meanshift.py
現行版なので、本文と一部異なります。

環境

構築は、参考2のようにやればいいのね。
---以下参考2引用
pipでインストールしたモジュール一覧

gnureadline==6.3.3
ipython==3.1.0
matplotlib==1.4.3
nose==1.3.7
numpy==1.9.2
Pillow==2.9.0
pyparsing==2.0.3
python-dateutil==2.4.2
pytz==2015.4
scipy==0.16.0
six==1.9.0
sympy==0.7.6

requirements.txtに上記の一覧を記述して、

$ pip install -r requirements.txt

とすればOpenCV以外の同じ環境が構築できる。
---ここまで引用

とはいえ、今回はいじらずに行けました。

>pip list
Package                            Version
---------------------------------- -----------
ipython                            5.1.0
matplotlib                         2.2.2
nose                               1.3.7
numpy                              1.14.2
Pillow                             3.3.1
pycparser                          2.14
python-dateutil                    2.5.3
pytz                               2016.6.1
scipy                              0.18.1
six                                1.10.0
sympy                              1.0

コードと工夫したこと

参考2のオリジナルコード.py
# -*- coding: utf-8 -*-
import numpy as np
import cv2
if __name__ == '__main__':
    cap = cv2.VideoCapture(0)
    # 追跡する枠の座標とサイズ
    x = 600
    y = 200
    w = 200
    h = 200
    track_window = (x, y, w, h)
    # フレームの取得
    ret,frame = cap.read()
    # 追跡する枠を決定
    roi = frame[y:y+h, x:x+w]
    # 追跡する枠の内部を切り抜いてHSV変換
    hsv_roi =  cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
    ## マスク画像の生成
    img_mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
    ## 正規化するためのヒストグラムの生成 
    roi_hist = cv2.calcHist([hsv_roi], [0], img_mask, [180], [0,180])
    ## ノルム正規化
    cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
    term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
    while(True):
        ret, frame = cap.read()
        if ret == True:
            # フレームをHSV変換する
            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            # 上で計算したヒストグラムを特徴量として、画像の類似度を求める
            dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180], 1)
            # 物体検出する
            ret, track_window = cv2.meanShift(dst, track_window, term_crit)
            #ret, track_window = cv2.CamShift(dst, track_window, term_crit)

            # 物体検出で取得した座標を元のフレームで囲う
            x,y,w,h = track_window
            img_dst = cv2.rectangle(frame, (x,y), (x+w, y+h), 255, 2)
            cv2.imshow('SHOW MEANSHIFT IMAGE', img_dst)
            # qを押したら終了。
            k = cv2.waitKey(1)
            if k == ord('q'):
                break
        else:
            break

#ret, track_window = cv2.CamShift(dst, track_window, term_crit)
はウワンが追記
【参考】
Meanshift と Camshift

これでも動くと思うが、ウワンのカメラだと初期動作が遅くて動いてくれなかった。
また、ターゲットを捕捉するのが難しくて、何度も失敗。
ということで、ターゲットを捕捉できるように以下の変更を加えた。

    # 追跡する枠の座標とサイズ
    x = 600
    y = 200
    w = 200
    h = 200
    track_window = (x, y, w, h)
    # フレームの取得
    ret,frame = cap.read()
    # 追跡する枠を決定
    roi = frame[y:y+h, x:x+w]

の部分を以下とした。

   # 追跡する枠の座標とサイズ
    x = 200
    y = 200
    w = 200
    h = 200
    track_window = (x, y, w, h)
    # フレームの取得
    ret,frame = cap.read()
    cv2.waitKey(2) 
    # 追跡する枠を決定
    while True:
        ret,frame = cap.read()
        cv2.imshow("org",frame)
        roi = frame[y:y+h, x:x+w]
        cv2.imshow("roi",roi)
        if cv2.waitKey(20)>0:
            break

つまり、一度初期起動させ、その後取得する。しかも動画を直接見ながらWhileでターゲットを確実に補足できたところで、何かキーを押すとroiが取得できるように変更した。これで、やると失敗はなくなった。

結果

例は青い物体でのものであったが、赤いリンゴのお菓子袋でためしてみた。
以前の記事から青の範囲との比較
OpenCV / read_save_doga.py

47     # define range of blue color in HSV 
48     lower_blue = np.array([110,50,50]) 
49     upper_blue = np.array([130,255,255]) 

#上記のコード
img_mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))

上記はほぼ全色入っている

ということで見事に捕捉してくれた。実は顔なんかも捕捉できているので、ほぼなんでも捕捉できるものと思わわれる。
apple_meanshift.jpg

ちなみに、CamShiftはさらに捕捉するまで枠の大きさを変えた探索する。物体の見た目の大きさ(遠ざかったり、近づいたりで)が変わっても、その大きさに対応して捕捉する。
捕捉できなければ、撮影画像一面に広がる。。。
ただし、枠が横に長くなってしまったり、縦に長くなったりもして評価は難しいところです。

まとめ

・meanshift&CamShiftで物体捕捉して遊んでみた
・roiの使い方次第でいろいろ試せそう
   というか、SSPのRoiで物体認識が使えるような予感

MuAuan
2020年目標;いい記事を書く 記事350いいね1500フォロワー150 2019年の実績/目標 記事275/300いいね1035/1000フォロワー97/100 1/7/2019 記事219いいね784フォロワー76 2018年の実績/目標 記事140/200いいね423/500フォロワー48/50 7/8/2018 記事90いいね227フォロワー25
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした