見出し画像

思い出したかのようにラスパイを使って監視カメラを作った

以前サソリの管理プログラムを作り1年半くらい運用したが、他にも生体が増えたりして置き場がなくなったので使うのをやめてしまった。
さらに2年くらい寝かしている間に、いろいろペット環境も変わったりしたので思い出したかのように引っ張り出して監視カメラを作ってみた。
AIの力も借りて作ってみた。


やりたいこと

今回作りたいものはカメラから取得した映像をブラウザで見るだけのシンプルなもの。
FastAPIを使いWebサーバーを立てて、ラズパイカメラをから取得した映像をブラウザを使って監視する。ラズパイ内にローカルサーバーを立てるため、同じwifi内ならどこからでもアクセスできるようにする。


環境設定

ラズパイを買ってから4年くらい経っていたので初期化して新たにOSを設定した。当時はRaspbianを使っていたけど今回はbullseyeを採用した。

今回の環境
Raspberry Pi 3 B+
bullseye 32bit full
python 3.9.2

仮想環境は作らずラズパイ直にFastAPIはpipインストールする。

ハードは次の記事の時点のまま、
赤外線LED、温度湿度計をついているが今回は使っていない。

実装

構成

ブラウザで確認するためhtmlファイルを作っておく。

projectmain.pytemplatesindex.html

プログラム

FastAPIのWebサーバーはroot("/")からstream("/stream")へリダイレクトする。streamからhtmlを表示する。
htmlからcamera("/camera")のAPIを叩いて映像を取得する。
カメラではジェネレーターを作り常に映像を返すようにする。

main.py

from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse, HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from picamera import PiCamera
from io import BytesIO
import uvicorn


app = FastAPI()
templates = Jinja2Templates(directory="templates")

camera = PiCamera()
camera.rotation = 90  # 任意解カメラ回転
camera.resolution = (640, 480)  # 任意解像度
camera.framerate = 24


def generator():
    stream = BytesIO()
    for _ in camera.capture_continuous(stream, "jpeg", use_video_port=True):
        stream.seek(0)
        yield (b"--frame\r\n"
            b"Content-Type: image/jpeg\r\n\r\n" + stream.getvalue() + b"\r\n\r\n")
        stream.truncate()


@app.get("/")
async def root():
    return RedirectResponse(url="/stream")

@app.get("/camera")
async def video_feed():
    return StreamingResponse(generator(), media_type="multipart/x-mixed-replace;boundary=frame")

@app.get("/stream", response_class=HTMLResponse)
async def stream(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

htmlはAIに書いてもらったでシンプルなもの。
video_feedでカメラの映像を取得する。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Live Streaming</title>
</head>
<body>
    <h1>Live Streaming from Raspberry Pi</h1>
    <img src="{{ url_for('video_feed') }}">
</body>
</html>

カメラから取得した映像をブラウザで見るだけのプログラムはこれだけ。
これで遠隔の監視ができるようになった。

実は運用しているものは、ハードについているLEDと湿度温度測定の機能を付与してクラス化して使ってる。

いいなと思ったら応援しよう!