🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

1回答

1841閲覧

【Python】カスケード分類器で物体検出し、パーティクルフィルタ(粒子フィルタ)で物体追跡するプログラム

amos

総合スコア5

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/01/18 06:49

Python初心者です。
カスケード分類器を利用してリアルタイムでカメラで検出したい物体が写った場合、
その物体を赤い枠で囲み、パーティクルフィルタでその物体を粒子で追跡するプログラムを
作成をしたいと考えております。
現在、
① カスケード分類器を利用してカメラで検出したい物体が写った場合検出するプログラム
② パーティクルフィルタを利用してカメラで赤い物体を追跡するプログラム
この2つのプログラムを作成しました。

① カスケード分類器を利用してカメラで検出したい物体が写った場合検出するプログラム

import cv2 if __name__ == '__main__': # 定数定義 ESC_KEY = 27 INTERVAL = 33 FRAME_RATE = 30 ORG_WINDOW_NAME = "org" DEVICE_ID = 0 # 分類器の指定 custom_cascade = cv2.CascadeClassifier('cascade.xml') # カメラ映像取得 cap = cv2.VideoCapture(DEVICE_ID) # 初期フレームの読込 end_flag, c_frame = cap.read() height, width, channels = c_frame.shape # ウィンドウの準備 cv2.namedWindow(ORG_WINDOW_NAME) # 変換処理ループ while end_flag == True: # 画像の取得と顔の検出 img = c_frame graying = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) custom_rect = custom_cascade.detectMultiScale(graying, scaleFactor = 1.07, minNeighbors = 2, minSize = (1, 1)) # 物体検出が成功した場合、物体を長方形の赤い枠で囲む if len (custom_rect) > 0: for rect in custom_rect: cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness = 3) # フレーム表示 cv2.imshow(ORG_WINDOW_NAME, c_frame) # Escキーで終了 key = cv2.waitKey(INTERVAL) if key == ESC_KEY: break # 次のフレーム読み込み end_flag, c_frame = cap.read() # 終了処理 cv2.destroyAllWindows() cap.release()

② パーティクルフィルタを利用してカメラで赤い物体を追跡するプログラム

import cv2 import numpy as np # 追跡対象の色範囲(Hueの値域) def is_target(roi): return (roi <= 30) | (roi >= 150) # マスクから面積最大ブロブの中心座標を算出 def max_moment_point(mask): # ラベリング処理 label = cv2.connectedComponentsWithStats(mask) data = np.delete(label[2], 0, 0) # ブロブのデータ center = np.delete(label[3], 0, 0) # 各ブロブの中心座標 moment = data[:, 4] # 各ブロブの面積 max_index = np.argmax(moment) # 面積最大のインデックス return center[max_index] # 面積最大のブロブの中心座標 # パーティクルの初期化 def initialize(img, N): mask = img.copy() # 画像のコピー mask[is_target(mask) == False] = 0 # マスク画像の作成(追跡対象外の色なら画素値0) x, y = max_moment_point(mask) # マスクから面積最大ブロブの中心座標を算出 w = calc_likelihood(x, y, img) # 尤度の算出 ps = np.ndarray((N, 3), dtype=np.float32) # パーティクル格納用の配列を生成 ps[:] = [x, y, w] # パーティクル用配列に中心座標と尤度をセット return ps # 1.リサンプリング(前状態の重みに応じてパーティクルを再選定) def resampling(ps): # 累積重みの計算 ws = ps[:, 2].cumsum() last_w = ws[ws.shape[0] - 1] # 新しいパーティクル用の空配列を生成 new_ps = np.empty(ps.shape) # 前状態の重みに応じてパーティクルをリサンプリング(重みは1.0) for i in range(ps.shape[0]): w = np.random.rand() * last_w new_ps[i] = ps[(ws > w).argmax()] new_ps[i, 2] = 1.0 return new_ps # 2.推定(パーティクルの位置) def predict_position(ps, var=13.0): # 分散に従ってランダムに少し位置をずらす ps[:, 0] += np.random.randn((ps.shape[0])) * var ps[:, 1] += np.random.randn((ps.shape[0])) * var # 尤度の算出 def calc_likelihood(x, y, img, w=30, h=30): # 画像から座標(x,y)を中心とする幅w, 高さhの矩形領域の全画素を取得 x1, y1 = max(0, x-w/2), max(0, y-h/2) x2, y2 = min(img.shape[1], x+w/2), min(img.shape[0], y+h/2) x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) roi = img[y1:y2, x1:x2] # 矩形領域中に含まれる追跡対象(色)の存在率を尤度として計算 count = roi[is_target(roi)].size return (float(count) / img.size) if count > 0 else 0.0001 # パーティクルの重み付け def calc_weight(ps, img): # 尤度に従ってパーティクルの重み付け for i in range(ps.shape[0]): ps[i][2] = calc_likelihood(ps[i, 0], ps[i, 1], img) # 重みの正規化 ps[:, 2] *= ps.shape[0] / ps[:, 2].sum() # 3.観測(全パーティクルの重み付き平均を取得) def observer(ps, img): # パーティクルの重み付け calc_weight(ps, img) # 重み和の計算 x = (ps[:, 0] * ps[:, 2]).sum() y = (ps[:, 1] * ps[:, 2]).sum() # 重み付き平均を返す return (x, y) / ps[:, 2].sum() # パーティクルフィルタ def particle_filter(ps, img, N=300): # パーティクルが無い場合 if ps is None: ps = initialize(img, N) # パーティクルを初期化 ps = resampling(ps) # 1.リサンプリング predict_position(ps) # 2.推定 x, y = observer(ps, img) # 3.観測 return ps, int(x), int(y) def main(): # パーティクル格納用の変数 ps = None DEVICE_ID = 0 # 動画ファイルのキャプチャ cap = cv2.VideoCapture(DEVICE_ID) while cv2.waitKey(30) < 0: ret, frame = cap.read() hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV_FULL) h = hsv[:, :, 0] # S, Vを2値化(大津の手法) ret, s = cv2.threshold(hsv[:, :, 1], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) ret, v = cv2.threshold(hsv[:, :, 2], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) h[(s == 0) | (v == 0)] = 100 # パーティクルフィルタ ps, x, y = particle_filter(ps, h, 300) if ps is None: continue # 画像の範囲内にあるパーティクルのみ取り出し ps1 = ps[(ps[:, 0] >= 0) & (ps[:, 0] < frame.shape[1]) & (ps[:, 1] >= 0) & (ps[:, 1] < frame.shape[0])] # パーティクルを赤色で塗りつぶす for i in range(ps1.shape[0]): frame[int(ps1[i, 1]), int(ps1[i, 0])] = [0, 0, 200] # パーティクルの集中部分を赤い矩形で囲む cv2.rectangle(frame, (x-20, y-20), (x+20, y+20), (0, 0, 200), 5) cv2.imshow('Result', frame) cap.release() cv2.destroyAllWindows() if __name__ == "__main__": main()

この2つのプログラムを実行したときにエラーが出ないように合成したいのですが、自分の力では合成することができません。どうしてもどこかでエラーが出てしまいます。自分本位な質問であることは十分承知です。恐れ入りますが、どなたかお力添えしていただくと幸いです。よろしくお願い申し上げます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbpb0

2021/01/18 07:34 編集

> カスケード分類器を利用してリアルタイムでカメラで検出したい物体が写った場合、 その物体を赤い枠で囲み の時点で「検出したい物体」の座標は分かってるわけですよね 「赤い枠」で囲めるのだから そしてそれは、カメラで撮影した動画の各フレームでできるのですよね つまり、動画上での「検出したい物体」の座標は追跡できているわけですよね それなのに、何でわざわざ > パーティクルフィルタでその物体を粒子で追跡する なんて回りくどいことをするのですか? すでに物体は追跡できている(動画の各フレームでの座標が分かっている)のに
fana

2021/01/18 08:08

(対象が複数存在し得る前提なのかな)
amos

2021/01/18 12:44

もしかしたら私の勉強不足で間違えた知識かもしれませんが、カスケード分類器だけ使用する場合と、カスケード分類器とパーティクルフィルタを併用する場合では、後者の方が1フレームにおける平均処理時間が短いという理由で、この2つのプログラムを合成したいと考えました。誠に身勝手ではございますが、お力添えの方よろしくお願い申し上げます。
jbpb0

2021/01/18 14:15

> カスケード分類器とパーティクルフィルタを併用する場合では、後者の方が1フレームにおける平均処理時間が短い と考える理由は何でしょうか?
jbpb0

2021/01/19 00:13 編集

論文読みました 人物の検出精度を上げるために、全身と部分(顔と足元)の複数のHOG検出器を同時に走らせると、計算負荷が高いので、粒子フィルターで人物の移動の予測をして、画像内の予測された箇所付近を画像から切り出して、そこだけでHOG検出を行う、と理解しました ご質問のコードで言うと、①の処理を、動画から切り出した各フレームの画像全体で行うのではなく、②の処理結果(移動予測)を使って次のフレームから必要な画像部分のみ切り出して、それを入力にして①処理を行う、ということになると思いますが、ご質問の文面からは、そのようには読み取れませんでした (論文の内容及び質問文を読み違えていたら、ごめんなさい)
jbpb0

2021/01/19 00:33 編集

質問者さんのケースでは、画像全体での①処理が重たく、②処理を行って画像切り出しをしてから①処理を行った方がトータルでの処理が軽くなる場合は有効ですが、もし画像全体での①処理が②処理と同等あるいは②処理よりも軽ければ、意味がありません また、画像全体での①処理が②処理よりも重たくても、ちょっとしか違わなければ、画像切り出しによる①処理の節約分よりも②処理追加の方が負荷が増えて、トータルで損するかもしれません なので、まずは①処理と②処理の計算時間の比を測ることをお勧めします その結果と、②処理結果を用いて画像を切り出したら①処理がどれくらい削減できそうか、の予想を組み合わせて、①+②を行う価値があるか、を見積もったらいかがでしょうか? 苦労して①と②を合体させて走らせたら、①よりも重くなった(あるいは変わらなかった)となると、意味無いですよね そういうことを既に行った上で、①+②の方が負荷が軽くなる見積りをして、この質問に至ったのでしたら、ごめんなさい
guest

回答1

0

論文読みました
視覚障害者歩行支援のための単眼カメラを用いた歩行者検出システム
人物の検出精度を上げるために、全身と部分(顔と足元)の複数のHOG検出器を同時に走らせると、計算負荷が高いので、粒子フィルターで人物の移動の予測をして、画像内の予測された箇所付近を画像から切り出して、そこだけでHOG検出を行う、と理解しました

ご質問のコードで言うと、①の処理を、動画から切り出した各フレームの画像全体で行うのではなく、②の処理結果(移動予測)を使って次のフレームから必要な画像部分のみ切り出して、それを入力にして①処理を行う、ということになると思います

画像全体での①処理が重たく、②処理を行って画像切り出しをしてから①処理を行った方がトータルでの処理が軽くなる場合は有効ですが、もし画像全体での①処理が②処理と同等あるいは②処理よりも軽ければ、意味がありません
また、画像全体での①処理が②処理よりも重たくても、ちょっとしか違わなければ、画像切り出しによる①処理の節約分よりも②処理追加の方が負荷が増えて、トータルで損するかもしれません

なので、まずは①処理と②処理の計算時間の比を測ることをお勧めします
その結果と、②処理結果を用いて画像を切り出したら①処理がどれくらい削減できそうか、の予想を組み合わせて、①+②を行う価値があるか、を見積もったらいかがでしょうか?
苦労して①と②を合体させて走らせたら、①よりも重くなった(あるいは変わらなかった)となると、意味無いですよね

投稿2021/02/28 14:25

jbpb0

総合スコア7653

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問