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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

1410閲覧

①Pythonを使用し自作の監視カメラを作ったのですが、 img1、img2、img3をどうして初期化する必要があるのですか? ②フレーム差分法で、グレースケールにする理由 画像との差分を抽出する理

ikum

総合スコア1

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2021/01/29 13:27

編集2021/02/01 10:19

Python

1import cv2 2import os 3 4 5 6# 保存パスの指定 7save_path = "./gray_image/camera_capture_" 8def main(): 9 10 # カメラのキャプチャを開始 カメラの番号は、内蔵カメラが0、USBで追加のカメラを接続すると1 11 #基本的に0から順番に割り当てられる 12 cam = cv2.VideoCapture(0) 13 # フレームの初期化 img1 img2 img3 と一枚、一枚と変化している画像を格納している。 14 #画像配列[高さ、幅、RGB] (3次元配列) 15 img1 = img2 = img3 = camera(cam) 16 17 18 # 保存 19 20 th =70 21 num = 1 22 while True: 23 # Enterキーが押されたら終了 24 if cv2.waitKey(1) == 13: break 25 # 差分を調べる 26 print(img1) 27 diff = checkimage(img1, img2, img3) 28 # 差分がthの値以上なら動きがあったと判定 29 cnt = cv2.countNonZero(diff)#countNoneroは面積計測をする 30 print(cnt) 31 if cnt > th: 32 print("カメラに動きを検出") 33 #画像をウィンドウ上に表示するためのもの,# 34 # 第1引数は文字列型で指定するウィンドウ名です.第2引数は表示したい画像です 35 cv2.imshow('PUSH', img3) 36 #すでにファイルがあるかどうかをチェックするためのもの( os.path.exists) 37 while os.path.exists( save_path + str(num) + ".jpg"): 38 num += 1 39 # 画像を保存 40 cv2.imwrite(save_path + str(num) + ".jpg", img3) 41 42 else: 43 cv2.imshow('PUSH', diff) 44 # 比較用の画像を保存 45 img1, img2, img3 = (img2, img3, camera(cam)) 46 47 48 # 後始末 49 # カメラを使った処理には開放粗利が必要 50 cam.release() 51 # Windowを開いた場合は閉じる処理が必要 52 cv2.destroyAllWindows() 53 54 55 56# 画像に動きがあったか調べる関数 フレーム差分法を使用 57#フレーム間差分とは、背景差分とは違い背景画像を用意する必要がなく、連続画像の差分から動体検知をすることができる。 58#IMREAD_GRAYSCALE : グレースケール画像として読み込む 59def checkimage(img1, img2, img3): 60 # グレイスケール画像に変換 読み取りの精度を上げるため 61 gray1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY) 62 gray2 = cv2.cvtColor(img2, cv2.COLOR_RGB2GRAY) 63 gray3 = cv2.cvtColor(img3, cv2.COLOR_RGB2GRAY) 64 65 66 67 # 画像との差分を抽出 変数名(今回はimg_diff)= cv2,absdiff(変化後の画像,変化前の画像) 68 diff1 = cv2.absdiff(gray1, gray2) 69 diff2 = cv2.absdiff(gray2, gray3) 70 71 # 論理積を調べる   72 diff_and = cv2.bitwise_and(diff1, diff2,) 73 74 # 白黒二値化 img_th(変数名) = cv2.threshold(使用数画像,閾値最小値,閾値最大値,閾値処理の種類) 75 _, diff_wb = cv2.threshold(diff_and, 50, 255, cv2.THRESH_BINARY) 76 77 # ノイズの除去 78 diff = cv2.medianBlur(diff_wb, 5) 79 return diff 80 81 82 83# カメラから画像を取得する 84def camera(cam): 85 86 img = cam.read() 87 88 img = cv2.resize(img, (800, 800))#画像の大きさを変える(resize) 89 return img 90 91 # モジュールを直接実行した時だけ、実行したいコード   92 #Pythonスクリプトを直接実行した時には、そのスクリプトファイルは「__main__」という名前のモジュールとして認識される 93 #そのため、スクリプトファイルを直接実行すると__name__変数の中に自動で'__main__'という値が代入される 94if __name__ == '__main__': 95 main()```ここに言語を入力

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

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

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

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

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

quickquip

2021/01/29 14:11

質問は後から編集できますよ
guest

回答1

0

ベストアンサー

こちらの修正しようした編集ミスと捉えて回答します。

①Pythonを使用し自作の監視カメラを作ったのですが、

img1、img2、img3をどうして初期化する必要があるのですか?

まずこの方法の大きな流れを考えましょう。
前の前のフレーム、前フレーム、今のフレームを比較する方法です。
3フレーム目以降であればすべてのデータがありますが、1、2フレーム目に関しては比較対象のデータがありません。ないままプログラムを走らせると、「未定義のimg2、img3をどうするの?」という旨のエラーでコケます。

試しに、
img1 = img2 = img3 = camera(cam)

img1 = camera(cam)
とすると言わんとすることが良くわかるはずです。

②フレーム差分法で、グレースケールにする理由

画像との差分を抽出する理由
論理積を調べる理由
画像を二値化にする理由
ノイズを除去する理由
これらの理由が知りたいです

問題をいくつかに分けましょう。
A. グレースケールにする理由
B. 画像との差分を抽出する理由
C. 論理積を調べる理由
D. 画像を二値化にする理由
E. ノイズを除去する理由

このプログラムのキモは、「"最終的な理解"としての差分を検出する」で、ほかの処理はこれに付随する飾りです。"最終的な理解"とあるのは、単に差分を取るのではなくて、「明らかに差分で合って、細かい誤差みたいなものは取り除いておきたい」、という意味です。

プログラムを後ろ側から見ていくと良くわかります。
サンプル動画はこちらの一番初めのものを使いました。

E. ノイズを除去する理由
ノイズを取り除く処理をすると、細かくちぎれてしまったピクセルを繋げて大きくとらえることができます。もろもろの処理でうっかり取りこぼしてしまったピクセルを救済できるイメージです。
イメージ説明

D. 画像を二値化にする理由
プログラムで差分を検出することはできますが、そのままの差分だと、差分の絶対値が返ってきます。これでは、10の差は差なのか、20の差は差なのか、30ならどうか、50ならどうか、100ならどうか、という線引きができない生煮えの回答になってしまいます。これに、ここ以上の差は差です、という線引きを与える効果があります。

C. 論理積を調べる理由
論理積は、AとBと両方同じもの、を探す処理です。ここでは、「前の前のフレームと前のフレームの差」、「前のフレームと今のフレームの差」と共通する差、つまり、うっかりできてしまった差ではなく**「本当に明らかな差」を検出する処理**として使われています。

B. 画像との差分を抽出する理由
「"最終的な理解"としての差分を検出する」に至る前の、もろもろの計算処理をする前のざっくりとした生の差を計算するためです。

A. グレースケールにする理由
カラー画像の差もBGRのチャネル別にやれば計算できると思いますが、煩雑になるのでグレースケールで差の計算をする準備としてやっているものと思います。


このプログラムのdiff_and = cv2.bitwise_and(diff1, diff2,)の部分が不可解に見えます。というのも、cv2.bitwise_and()は通常マスク画像のような0,1のデータに使われる関数で、0-255のデータに使った場合、完全に値が一致した場合しか結果が返ってこない(他のピクセルは0が返ってくる)ためです。
イメージ説明

べた塗アニメで無圧縮のようなものでは大変効果がありますが、同じことをするのであれば、二値化してからcv2.bitwise_and()の方が良いのではないか、と個人的には感じています。

具体的な差は以下のような感じです。
イメージ説明

投稿2021/01/30 00:10

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ikum

2021/02/01 10:18

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問