AIで物体検出してくれるOSSのNVR「Frigate」を試した

物体検出を試してみたい
GIGAZINEの次の紹介記事を見つけ、カメラ映像に映っている物体が何かを機械学習モデルで認識してくれるというオープンソースのNVR「Frigate」を手元で試してみたくなった。どこかの横断歩道のカメラ映像を使っているデモサイトもある。
なお、NVRとは「ネットワークビデオレコーダー」の略だ。サーバにNVRソフトウェアを導入すると、ネットワークカメラの映像を束ねた監視カメラシステムが構築できる。
今回の実験の前提条件
Frigateを手元でとりあえず素早く試すことを目標に、手元の仮想化プラットフォームProxmox VE (PVE) の上にUbuntuの仮想マシンを構築し、その中でFrigateのdockerコンテナを動かすことにする。
仮想化プラットフォームのCPUは「AMD Ryzen 5 PRO 3400GE」で、別立てのGPUは無し。私は今回初めて存在を知ったハードウェアである、エッジAI用アクセラレータ「Google Coral (TPU)」も持っていないので、必然的に一般的なサーバソフトウェアと同じハードウェア構成となる (PVEにUSBやPCI (GPU) Passthroughも設定しない)。すなわち、物体検出の演算には仮想マシンのCPUを用いる構成だ。

Google Coral USB Accelerator Edge TPU AI アクセラレータ
Frigateの導入手順
次のリンク先のFrigate公式ドキュメントを参考に導入を進める。
Step-1. Docker環境を用意する
Dockerを動かす場所を用意する。既存のDocker環境でも良いだろうし、今回の実験では、前述の前提条件のように仮想のUbuntu Server (x86_64) の中に新規構築した。
- 仮想マシンを「CPU: 8 core, Memory: 8GB, Storage: 64GB」で構成する
- Ubuntu Server 22.04 LTSをインストールする
- Dockerを公式手順で導入する (非Rootless modeにした)
- ユーザ権限で
docker run hello-world
が動かせることを確認する
Step-2. RTSPソースを用意する
RTSPでのVideoストリーミングが可能な、ネットワークカメラまたはカメラアプリを用意する。今回の実験では2台用意してみたが1台でも構わない。
カメラ | ソース | 備考 |
---|---|---|
No.1 | ネットワークカメラ「ATOM Cam 2」 | アプリ上でこの設定をするとRTSP配信が可能になる: Atomcam2の公式アプリがRTSP対応しました。 | Astrotourism Lab |
No.2 | Androidアプリ「RTSP Security Camera」 | アプリを起動すると画面の真ん中にRTSPのURLが表示される |

アトムテック(ATOM tech) 屋内/屋外兼用の防犯カメラ ATOM Cam 2 (アトムカムツー) 1080PフルHD Alexa対応 見守りカメラ 監視カメラ ネットワークカメラ ペットカメラ/ベビーモニター AC2
アトムテック(ATOM tech)
Step-3. 設定ファイルを用意する
Docker環境の母艦で作業を行う。
- https://docs.frigate.video/frigate/installation/#docker の「version: “3.9”」で始まるファイルの内容を、任意のpathに
docker-compose.yml
として保存する - 保存した
docker-compose.yml
の編集を行うshm_size
を https://docs.frigate.video/frigate/installation#calculating-required-shm-size の計算式にしたがって調整する。今回の実験ではざっくり"128mb"
へ増量した (カメラNo.1 (1920x1080) = 26.95MB, カメラNo.2 (640x480) = 4.21MB, ログ = 30MB を全て含められるように)- volumes部分にある
/path/to/your/...
2箇所を自身の環境に合わせて書き換える。今回の実験では/path/to/your/
を/home/hoge/frigate/
へ置換する形とする
version: "3.9" services: frigate: container_name: frigate privileged: true # this may not be necessary for all setups restart: unless-stopped image: ghcr.io/blakeblackshear/frigate:stable #shm_size: "64mb" # update for your cameras based on calculation above shm_size: "128mb" # update for your cameras based on calculation above devices: - /dev/bus/usb:/dev/bus/usb # passes the USB Coral, needs to be modified for other versions - /dev/apex_0:/dev/apex_0 # passes a PCIe Coral, follow driver instructions here https://coral.ai/docs/m2/get-started/#2a-on-linux - /dev/dri/renderD128 # for intel hwaccel, needs to be updated for your hardware volumes: - /etc/localtime:/etc/localtime:ro - /home/hoge/frigate/config.yml:/config/config.yml - /home/hoge/frigate/storage:/media/frigate - type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear target: /tmp/cache tmpfs: size: 1000000000 ports: - "5000:5000" - "8554:8554" # RTSP feeds - "8555:8555/tcp" # WebRTC over tcp - "8555:8555/udp" # WebRTC over udp environment: FRIGATE_RTSP_PASSWORD: "password"
/home/hoge/frigate/config.yml
として次の内容を保存する (部分ごとの説明は後述する)
mqtt: host: mqtt.server.com cameras: atomcam2: ffmpeg: inputs: - path: rtsp://hoge:fuga@192.168.1.XXX/live roles: - detect detect: width: 1920 height: 1080 android: ffmpeg: inputs: - path: rtsp://hoge:fuga@192.168.1.YYYY:NNNN roles: - detect detect: width: 640 height: 480 record: enabled: True retain: days: 3 mode: motion events: retain: default: 7 mode: active_objects detectors: cpu1: type: cpu num_threads: 3 cpu2: type: cpu num_threads: 3 objects: track: - person - bicycle - car - motorcycle - airplane - bus - train - car - boat - traffic light - fire hydrant - street sign - stop sign - parking meter - bench - bird - cat - dog - horse - sheep - cow - elephant - bear - zebra - giraffe - hat - backpack - umbrella - shoe - eye glasses - handbag - tie - suitcase - frisbee - skis - snowboard - sports ball - kite - baseball bat - baseball glove - skateboard - surfboard - tennis racket - bottle - plate - wine glass - cup - fork - knife - spoon - bowl - banana - apple - sandwich - orange - broccoli - carrot - hot dog - pizza - donut - cake - chair - couch - potted plant - bed - mirror - dining table - window - desk - toilet - door - tv - laptop - mouse - remote - keyboard - cell phone - microwave - oven - toaster - sink - refrigerator - blender - book - clock - vase - scissors - teddy bear - hair drier - toothbrush - hair brush
cameras:
ここでは、atomcam2とandroidという2台のカメラを定義している。それぞれの - path: rtsp://...
の行は、各RTSPソースのURLに書き換える。
record:
カメラ映像が、一定期間、検出したオブジェクトごとに保存されるように適宜設定している。
detectors:
上記リンク先では「not recommended」となっているけれども、カメラの台数に合わせてCPU Detectorを2つ定義している。
objects:
認識するオブジェクトを定義している (テストのためにありったけ定義した)。この定義を書かないデフォルト状態の場合、検出されるオブジェクトは「person」のみである。
Step-3. 保存領域を準備する
Docker環境の母艦にて、Frigateが保存領域として使用するディレクトリを作成する。
$ mkdir /home/hoge/frigate/storage/
Step-4. Frigateを起動する
Docker環境でFrigateコンテナを次のように起動し、コンソール画面に特にエラーが表示されないことを確認する。
$ cd <docker-compose.ymlを置いたpath> $ docker compose up
Dockerの母艦のIPアドレスの5000/tcp http://192.168.1.ZZZ:5000/ へウェブブラウザでアクセスすると、鳥 (アメリカグンカンドリ?) のアイコンが左上にある「FRIGATE」画面が確認できる。左メニューの「Cameras」を選択すると、接続しているカメラの映像が静止画で一覧できる。全カメラの動画を一覧したい場合は「Birdseye」を選択すれば良いようだ。
Frigateの物体検出はどんな感じか
左メニューの「Cameras」を選択し、次に右側で任意のカメラ映像を一度クリックする。そしてカメラ映像の右上に薄く現れているメニューを「Live」から「Debug」へ切り替えると、機械学習モデル (この場合はTensowFlow Liteのモデル) がカメラ映像に映った各物体をリアルタイム検出し、分類の確度とともに四角い枠で表示している様子を、毎秒5コマぐらいの動きで見ることができる。ほおお、すごい。
また、左メニューの「Events」を選択すると、物体検出の様子を時系列イベントとして閲覧できる。対象の物体部分がきっちり切り抜かれている画像がサムネイルとして並び、当該時間帯の動画もワンクリックで確認できる (我が家のピンク色のぬいぐるみが「Teddy Bear」と認識されているのはご愛嬌)。
所感
機械学習モデルを使って物体が何かを認識することは昨今当たり前に行われている。Frigateはその機能が予め組み込まれているオープンソースなNVRソフトウェアであり、物体検出関連も含めてセットアップがとても簡単で驚いた。今回の実験では物体検出の演算にCPUのみを利用しており、GPU等を利用する場合はセットアップが実際どうなるか不明だけども。
以前試した下記記事のShinobiも面白かったが、それぞれに特色があり、こちらFrigateもなかなか実用的な予感がする (Home Assistantへの統合方法も案内されている)。機会があれば実戦投入して、NVRで物体検出が利用できると実際どのような利点があるのか、確かめてみたいと思う。