以下は、Raspberry Piのカメラモジュールからリアルタイムで映像を取得し、動体検知を行うPythonコードの例です。OpenCVを使用します。
from flask import Flask, render_template, Response import time import io import cv2 import numpy as np app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') def gen(camera): while True: time.sleep(0.1) frame = camera.get_frame() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') @app.route('/video_feed') def video_feed(): return Response(gen(Camera()), mimetype='multipart/x-mixed-replace; boundary=frame') class Camera(object): def __init__(self): # カメラの設定 self.cap = cv2.VideoCapture(0) # 0は内蔵カメラ、1はUSBカメラ self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # フレームの横幅を設定 self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # フレームの縦幅を設定 # 動体検知用の背景差分の設定 self.fgbg = cv2.createBackgroundSubtractorMOG2() def __del__(self): # 終了処理 self.cap.release() cv2.destroyAllWindows() def get_frame(self): # カメラからフレームを取得 ret, frame = self.cap.read() # 背景差分による前景領域の抽出 fgmask = self.fgbg.apply(frame) # 前景領域の二値化 ret,thresh = cv2.threshold(fgmask,127,255,0) # ノイズ除去 kernel = np.ones((3,3),np.uint8) thresh = cv2.erode(thresh, kernel, iterations=1) thresh = cv2.dilate(thresh, kernel, iterations=1) # 輪郭抽出 contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # 輪郭を囲む矩形を描画 for contour in contours: # 輪郭が一定の大きさ以上である場合に描画する if cv2.contourArea(contour) > 500: (x, y, w, h) = cv2.boundingRect(contour) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # フレームをリサイズ frame = cv2.resize(frame, (640, 480)) _, imgencode = cv2.imencode('.jpg', frame) return imgencode.tostring() if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=True, threaded=True)
このコードでは、cv2.VideoCapture()
を使用して、カメラからリアルタイムで映像を取得し、cv2.createBackgroundSubtractorMOG2()
を使用して、前景領域を抽出します。そして、cv2.findContours()
を使用して、前景領域の輪郭を抽出し、cv2.rectangle()
を使用して、輪郭を囲む矩形を描画します。
また、以下の記事で紹介しているラズパイでのキャプチャ映像をストリーミング配信する方法も加えて、動体検知した様子をそのままストリーミングします。
実物はこんな感じです。