Zenn
🔍

映像ストリーミングをつかってリアルタイム顔認識

2025/02/27に公開

本記事では、THINKLETからストリーミングした映像を用いてサーバサイドでリアルタイム顔認識を行う簡単なPythonプログラムを紹介します。
元々、THINKLET開発者ポータル 向けのチュートリアル記事の一部として書いていたのですが、諸般の事情で ボツネタ としたのでこちらで公開することにしました。

すでにFairy DevicesからはTHINKLETから映像ストリミーングをする方法として、直接YouTubeやTwitchなどへ配信をするアプリ thinklet.squid.run (GitHub) を公開しており、本記事でも映像ストリーミング部分はこのアプリを用います。
本記事で示したサンプルプログラムを活用することで、THINKLETからの映像に対してリアルタイムに映像処理を行うソフトウェアの開発イメージを掴んでいたければ幸いです。

構成イメージ

構成は次のようになります。

前提

  • thinklet.squid.run (GitHub) のREADMEを参照しアプリを構築、アプリが MediaMTX に映像を送れること。
  • Python3.8以降で、OpenCVが利用できる PC(Windows/MacOS/Linux) があること。
    • なお、ポートは適宜開放できるようにしてください。

準備

  • PowerShellやターミナルを起動し、任意の作業環境を用意します。
    ここでは、faceTest というディレクトリを作成し、test という仮想環境をvenvで構築します。
    $ mkdir faceTest
    $ cd faceTest/
    
    /faceTest$ python3 -m venv test
    /faceTest$ source test/bin/activate
    
  • OpenCVをインストールします。
    • python -m pip install opencv-python
  • 学習済みファイルを取得
    • OpenCVの学習済みファイルを取得します。haarcascade_frontalface_default.xml というファイルをダウンロードしてください。
    • haarcascade_frontalface_default.xml は、faceTest のディレクトリに配置します。

プログラム

  • faceTest のディレクトリに face.py というファイルを作成し、次のプログラムを記述します。
    import cv2
    
    # 顔認識をする設定ファイル
    model_url = r"haarcascade_frontalface_default.xml"
    # RTMPストリームのURL 
    #   適宜、RTMPサーバーを動かすマシンのアドレスに変更してください。MediaMTXを動かしているマシンと同じならば変更不要です。
    rtmp_url = r"rtmp://localhost:1935/live/face"
    
    # 顔認識器を取得
    cascade = cv2.CascadeClassifier(model_url)
    print("Created faceDetector")
    # OpenCVのVideoCaptureを使ってRTMPストリームを開く
    cap = cv2.VideoCapture(rtmp_url)
    print("Created videoCapture")
    # 読み取ったフレームの枚数
    read_count = 0
    current_face_count = -1
    
    if not cap.isOpened():
        print("Error: Could not open RTMP stream.")
    else:
        while True:
            # フレームを取得
            ret, frame = cap.read()
            # フレームが正常に取得されたか確認
            if not ret:
                print("Error: Could not read frame.")
                break
    
            # 読み取ったフレームの数
            read_count += 1
            # 全フレームを探査しても非効率なので,5枚に1枚にする
            if read_count % 5 != 0:
                continue
    
            # 顔認識の処理
            facerect = cascade.detectMultiScale(frame)
            # 前回取得したサイズと異なるならば,標準出力に書き出す
            if current_face_count != len(facerect):
                current_face_count = len(facerect)
                print(current_face_count)
    
    # 終了
    cap.release()
    cv2.destroyAllWindows()
    

実行

  • 次の順に起動していきます。なお、MediaMTX は、RTMPサーバーとして動かしますので、Pythonを実行するターミナルとは別に起動してください。
  1. RTMPサーバー(MediaMTX) を起動
  2. thinklet.squid.run からRTMPサーバーに映像を送る。
  • 実行例
adb shell am start \
  -n ai.fd.thinklet.app.squid.run/.MainActivity \
  -a android.intent.action.MAIN \
  -e streamUrl "rtmp://<マシンのIPアドレス>:1935/live" \
  -e streamKey "face" \
  --ei longSide 720 \
  --ei shortSide 480 \
  --ei videoBitrate 4096 \
  --ei audioSampleRate 44100 \
  --ei audioBitrate 128 \
  --ez preview true
# 第2キーを短押しして、ストリーミングを開始します
  1. Pythonのプログラムを実行します
  • 正しく起動できた場合、THINKLETのカメラに映す対象を変えてOpenCVが検出した顔の数に変化が起きると標準出力されるようになります。
python face.py
Created faceDetector
Created videoCapture
0
1
4
5
4
7
4
5

まとめ

このように今回はTHINKLETからストリーミングした映像に対してリアルタイムに顔画像検出を行うプログラムを紹介しました。
本記事のサンプルは検出した顔の数を標準出力するだけの面白みがないものですが、紹介したプログラムを改良すれば、
例えば、検出した顔を囲う枠(バウンディングボックス)を描画した映像や画像を表示することもできます。
また機械学習を顔認識以外のものに変えることで、さまざまなアプリケーションの応用が期待できます。

近年ではGeminiのMultimodal Live API のように、映像ストリーミングを送れるAI APIも出てきているので、いろんな応用もできそうです。

THINKLETが気になった方は、冒頭で紹介した開発者ポータルや、公式ページをご覧ください。
またTHINKLETのアプリケーションを開発するAndroidエンジニアや、THINKLETを使ったサービス開発に興味のある方も募集しています。興味のある方はこちらから募集ポジションの一覧をご確認ください。

フェアリーデバイセズ公式

Discussion

ログインするとコメントできます