質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

OpenCV

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

Python

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

Q&A

0回答

365閲覧

移動物体検出のプログラムのVideoCapture部分を、カメラから取得する動画に差し替えたい。

ajgtwjj

総合スコア11

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

OpenCV

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

Python

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

0グッド

0クリップ

投稿2019/06/28 08:42

編集2019/07/01 01:28

大学生の初心者です。カメラから移動体を読み取り、QRやカラーコードなどで見分けるような実験をしています

前提・実現したいこと

『画像処理 アルゴリズム入門』西住 流 p164の移動物体の検出より、移動物体検出のプログラムにカメラから動画を取得して表示する
プログラムを組み込んで、リアルタイムでカメラから移動物体検出のプログラムを動かしたい。

発生している問題・エラーメッセージ

プログラムは起動するが、断続的にカメラの画角に動くものがあると、シャッターを切るようにして静止画が表示されます。

該当のソースコード

移動物体検出のプログラム

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) を中心とする幅 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(): # 動画のキャプチャ cap = cv2.VideoCapture("input1.mp4") ps = None while(cap.isOpened()): 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) # q キーが押されたら終了 if cv2.waitKey(25) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() if __name__ == "__main__": main()

カメラから動画を取得するプログラム

import

1 2# VideoCapture オブジェクトを取得します 3capture = cv2.VideoCapture(0) 4 5while(True): 6 ret, frame = capture.read() 7 cv2.imshow('frame',frame) 8 if cv2.waitKey(1) & 0xFF == ord('q'): 9 break 10 11capture.release() 12cv2.destroyAllWindows()

試したこと

 各プログラムはそれぞれ、問題なく動くのを確認済みです。

前者のプログラムの#動画のキャプチャ を後者のプログラムに差し替えました。

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) を中心とする幅 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(): # 動画のキャプチャ # VideoCapture オブジェクトを取得します import cv2 capture = cv2.VideoCapture(0) ret, frame = cv2.VideoCapture(0).read() cv2.imshow('frame',frame) if cv2.waitKey(1) & 0xFF == ord('q'): cv2.VideoCapture(0).release() cv2.destroyAllWindows() ps = None while(cv2.VideoCapture(0).isOpened()): ret, frame = cv2.VideoCapture(0).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) # q キーが押されたら終了 if cv2.waitKey(25) & 0xFF == ord('q'): break cv2.VideoCapture(0).release() cv2.destroyAllWindows() if __name__ == "__main__": main()

補足情報(FW/ツールのバージョンなど)

Windows10、spyder(python3.7)で実行しています。
カメラはUSBなら何でもよいのですが、使っているカメラはLOAS‐15BKです。

###添付ファイル
動体検出に使うinput.mp4 の動画が添付できませんでした。
先端が赤い振り子が揺れている動画でした。

###教えてほしいこと
移動物体検出のプログラムのファイルから動画をインポートする部分を、カメラから取得した動画データに変えて、リアルタイムで移動体検出をしたいです。

試したコードだと、断続的過ぎてしまいます、処理したい環境は自動車の交通の流れを上から見るようなものを、想定しており 現在は天井に設置したカメラからラジコンの車のような物を検出しようとしています。

なので、カメラからの映像がそのまま流れ、その中で移動体を常に検出し、追跡できるプログラムを目指しております。
このプログラムを改良すれば可能でしょうか? また、何かアドバイスはございませんか?
よろしくお願いします。。。

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

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

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

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

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

t_obara

2019/06/28 08:53

具体的にどのようにうまくいかないのかご提示ください。 現状だとただの丸投げに他なりません。
Q71

2019/06/28 09:24

「うまくいきません」ではなく、「こうなることを期待したところ、実際にはこうなった」という、現状がわかる様にしてください。 読み手が試す事を期待しないでください。読み手の経験と一致するかもしれない事を期待してください。
Ryupe

2019/06/28 11:30

エラー文はどのように出てきましたか?
1T2R3M4

2019/06/28 12:44 編集

自分の書いたコードの動作がわかってないのですか? 大学生になりたてなのかもしれないけれど、プログラミングはエキスパートなんでしょ。
ajgtwjj

2019/07/01 01:36

追記、修正の依頼 ありがとうございます。 確かに詳細が少なすぎて、目標の具体性もあまりなく丸投げになってしまっており深く反省しております。 内容を編集いたしましたので、もう一度目を通して頂けたら幸いです。申し訳ございませんでした。 よろしくお願いいたします。
Q71

2019/07/01 01:36

> 試したコードだと、断続的過ぎてしまいます、処理したい環境は自動車の交通の流れを上から見るようなものを、想定しており 現在は天井に設置したカメラからラジコンの車のような物を検出しようとしています。 使用しているハードウェアは? 動画にするには、1秒あたり20枚くらいは処理しなければなりません。ソフトウェアだけでは難しく、ハードウェアの更新が必要かもしれません。
yominet

2019/07/02 12:11

Whileループ内の動きが ①1フレーム取り出す ②パーティクル・フィルタ確認 ③フィルタがなければ”描画を更新すること無く”、①に戻る ④あれば赤枠を書く ⑤④の内容で描画する ⑥キー入力確認して①に戻る という動きになっていますが、これは想定通りですか?
ajgtwjj

2019/07/03 03:04

申し訳ございません。あまり理解してなくそのままのコードを書いていました 解説して頂きありがとうございます。 理想とする動きは、上記の移動物体検出のプログラムで動かしたように滑らかな動作をカメラからの映像にもリアルタイムで行って欲しく、1フレームずつ取り出して、ではなくより連続的にしたいです。
t_obara

2019/07/03 05:14

リアルタイム処理について、その理解から始めるべきかと思います。1フレームずつ取り出して処理するのが基本です。その上で、処理速度が不足した場合どのような工夫をするのかがリアルタイム処理の難しいところです。 そもそもプレビューをするか否かだけでも大きく処理速度に影響を及ぼします。手っ取り早くは、処理PCのスペックをあげる、処理をする画像サイズを縮小するでしょう。
ajgtwjj

2019/07/04 03:41

ありがとうございます。勉強不足でした。 より良いスペックのpcで一度試してみます。 高スペックであれば、コードの書き換えはなくても動かせばわかるものなのでしょうか?
yominet

2019/07/04 11:00

一つ気になった点 capture = cv2.VideoCapture(0) で、カメラに接続してるのに、その後captureを使わずに すべてcv2.VideoCapture(0)を通してカメラ処理をしています(readとか)。 これを、captureにしたらどうなりますでしょうか? 手元にカメラがなく試せてないのですが、 ことあるごとにオブジェクト取得、 つまり「カメラに接続(OPEN)」をしているかもしれません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問