検知動体を矩形で囲む。
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 3,371
OpenCVを用いて、フレーム差分で取得した動体を矩形で囲みたいのですが、自分の書いたコードでは何も表示されず解決方法がわからなかったので質問させていただきました。下記のコードでもプログラムは一応動くのですが人が矩形で囲まれることはなかったです。](1bf2f3f3988490d013258a688d4b194b.jpeg)
コード
import cv2
import numpy as np
# フレーム差分の計算
def frame_sub(img1, img2, img3, th):
# フレームの絶対差分
diff1 = cv2.absdiff(img1, img2)
diff2 = cv2.absdiff(img2, img3)
# 2つの差分画像の論理積
diff = cv2.bitwise_and(diff1, diff2)
# 二値化処理
diff[diff < th] = 0
diff[diff >= th] = 255
# メディアンフィルタ処理(ゴマ塩ノイズ除去)
mask = cv2.medianBlur(diff, 3)
return mask
def main():
# カメラのキャプチャ
cap = cv2.VideoCapture(r'C:\Users\Gen\Videos\VideoProc\WIN_20190215_11_24_25_Pro.mp4')
kernel = np.ones((50,50),np.float32)/2500
# フレームを3枚取得してグレースケール変換
frame1 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
frame2 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
while(cap.isOpened()):
# フレーム間差分を計算
mask = frame_sub(frame1, frame2, frame3, th=30)
closing=cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
opening=cv2.morphologyEx(closing, cv2.MORPH_CLOSE, kernel)
for rect in closing:
cv2.rectangle(frame2, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), (255, 255, 255), thickness=2)
# 結果を表示
cv2.imshow("Frame2", frame2)
cv2.imshow("Mask", closing)
# 3枚のフレームを更新
frame1 = frame2
frame2 = frame3
frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
# qキーが押されたら途中終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
cv2.namedWindow("Frame2", cv2.WINDOW_NORMAL)
cv2.namedWindow("Mask", cv2.WINDOW_NORMAL)
if __name__ == '__main__':
main()
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
変数 closing はただの2値画像でないですか?
print(closing.shape, closing)
として変数の中身を確認してみてください。
なのでfor rect in closing
としても rect
に矩形の情報は入らないです。
その左下の人を囲みたい場合は、
cv2.findContours() で輪郭抽出したあと、cv2.boundingRect() で輪郭の外接矩形を取得してください。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.33%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/02/19 23:55
改良し動かしてみたのですがうまくいきませんでした。
閾値などをいじるとよいのでしょうか?
import cv2
import numpy as np
# フレーム差分の計算
def frame_sub(img1, img2, img3, th):
# フレームの絶対差分
diff1 = cv2.absdiff(img1, img2)
diff2 = cv2.absdiff(img2, img3)
# 2つの差分画像の論理積
diff = cv2.bitwise_and(diff1, diff2)
# 二値化処理
diff[diff < th] = 0
diff[diff >= th] = 255
# メディアンフィルタ処理(ゴマ塩ノイズ除去)
mask = cv2.medianBlur(diff, 3)
return mask
def main():
# カメラのキャプチャ
cap = cv2.VideoCapture(r'C:\Users\Gen\Videos\VideoProc\WIN_20190215_11_24_25_Pro.mp4')
kernel = np.ones((50,50),np.float32)/2500
# フレームを3枚取得してグレースケール変換
frame1 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
frame2 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
while(cap.isOpened()):
# フレーム間差分を計算
mask = frame_sub(frame1, frame2, frame3, th=30)
closing=cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
opening=cv2.morphologyEx(closing, cv2.MORPH_CLOSE, kernel)
ret,thresh = cv2.threshold(frame2,127,125,0)
imgEdge,contours,hierarchy = cv2.findContours(frame2,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(frame2,(x,y),(x+w,y+h),(0,255,0),2)
# 結果を表示
cv2.imshow("Frame2", frame2)
cv2.imshow("Mask", img)
# 3枚のフレームを更新
frame1 = frame2
frame2 = frame3
frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
# qキーが押されたら途中終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
cv2.namedWindow("Frame2", cv2.WINDOW_NORMAL)
cv2.namedWindow("Mask", cv2.WINDOW_NORMAL)
if __name__ == '__main__':
main()
2019/02/20 00:03 編集
あと cnt = contours[0] ですと、抽出される輪郭は1つとは限らないので、複数検出された場合は1つ目しか描画されないことになります。
2019/02/20 02:11
ありがとうございます。