はじめに
こんにちは。
今回はRaspberryPiにUSBカメラを接続して動体検知し、カメラで写している範囲に動くものがあった際に動画を撮影するよう設定していきます。
用意したもの
家にあった少し古いRaspberryPiを使用しています。
・Raspberry Pi 3 model B+
・Logicool USBウェブカメラ
RaspberryPiのOSは Raspbian version10 で、インストールされているPythonのバージョンはPython 3.7.3です。
RaspberryPiへのOSインストール、初期設定は以下の記事に書いています。
www.77-lifework.com
RaspberryPiにUSBカメラを接続してストリーミングで映像を見る場合は以下記事で。
www.77-lifework.com
OpenCVのインストールと操作
今回は画像の撮影のため、Pythonの画像処理ライブラリであるOpenCVをRaspberryPiにインストールし、これを使っていきます。
インストールは簡単です。
RaspberryPiにsshでログインし、以下コマンドを実行しましょう。
pip3 install opencv-python
RaspberryPiにはPython2系とPython3系がインストールされていると思いますが、今回私はPython3系を使用したいので、
「pip3」としています。
インストールが完了したら、コマンドラインで「python3」と入力し、「import cv2」と入力してみます。
すると、私の環境では以下のエラーが出ました。
pi@raspberrypi:~ $ python3 Python 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import cv2 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/pi/.local/lib/python3.7/site-packages/cv2/__init__.py", line 5, in <module> from .cv2 import * ImportError: libcblas.so.3: cannot open shared object file: No such file or directory
ライブラリが不足しているようなので追加でインストールします。
以下を実行しましょう。
sudo apt-get install libatlas-base-dev
すると、以下のようにOpenCVを正常に読み込むことができました。
pi@raspberrypi:~ $ python3 Python 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import cv2 >>> >>>
さて、次はOpenCVを使って画像を撮影してみましょう。
とりあえず動作確認のため、以下のようなPythonコードを組みました。
import cv2 from datetime import datetime def main(): cam = cv2.VideoCapture(0) # カメラデバイスが見つからない場合、終了 if not cam.isOpened(): return ret, frame = cam.read() date = datetime.now().strftime("%Y%m%d_%H%M%S") path = "./usbcam-img/" + date + ".png" cv2.imwrite(path, frame) cam.release() if __name__ == '__main__': main()
上のプログラムを実行すると、そのタイミングで画像を撮影して「path」で指定した場所に保存する動作となります。
動体検知して動画撮影
次はカメラで映している範囲に動きがあったときに撮影するプログラムを組んでみます。
フレームの動きを検知したらそこから数秒間動画を撮影して保存する仕様としました。
フレーム間差分法ってやつです。これは検索するとやり方いっぱい出てきます。
import cv2 import time from datetime import datetime def main(): base_path = "./usbcam-img/" cam = cv2.VideoCapture(-1) # カメラデバイスが見つからない場合、終了 if not cam.isOpened(): return fps = int(cam.get(cv2.CAP_PROP_FPS)) size = (int(cam.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cam.get(cv2.CAP_PROP_FRAME_HEIGHT))) while True: ret1, frame1 = cam.read() ret2, frame2 = cam.read() ret3, frame3 = cam.read() if ret1 and ret2 and ret3: #グレースケールに変換 gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY) gray3 = cv2.cvtColor(frame3, cv2.COLOR_BGR2GRAY) diff1 = cv2.absdiff(gray2,gray1) diff2 = cv2.absdiff(gray3,gray2) diff_and = cv2.bitwise_and(diff1, diff2) th = cv2.threshold(diff_and, 50, 255, cv2.THRESH_BINARY)[1] wh_pixels = cv2.countNonZero(th) #閾値を超えたら動画撮影 if wh_pixels > 500: date = datetime.now().strftime("%Y%m%d_%H%M%S") print(date + " whitePixels:"+str(wh_pixels)) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') out = cv2.VideoWriter(base_path + date + '.mp4',fourcc, fps, size) for i in range(400): ret_rec, frame_rec = cam.read() if ret_rec: out.write(frame_rec) out.release() time.sleep(1) cam.release() if __name__ == '__main__': main()
上のプログラムを実行し、動作している間にフレームの動きを検知すると以下のようにmp4ファイルが保存されます。
保存された動画ファイルを開くと、以下のように検知した映像が撮影できています。
(実際は動画なんですが、ここでは動画から切り取った写真を貼っています)
今回は以上です。
ここで使ったRaspberryPiとUSBカメラを以下に貼っておきますので、もしよかったら参考にしてみてください。
次は動体検知したタイミングで撮影した動画をスマホにとばすとかやってみたいなー、とか考えてます。