Raspberry Pi でカメラをつなぎ顔検出

サイト内の関連ページ

目次

  1. 前準備(Python 仮想環境の作成)
  2. dlib のインストール
  3. 学習済みモデルファイルのダウンロード
  4. サンプル画像を用いた動作確認
  5. カメラで撮影した画像で顔検出

前準備(Python 仮想環境の作成)

Raspberry Pi OS では、PEP 668 により、システムの Python に pip でパッケージを追加しようとすると externally-managed-environment のエラーになる。パッケージの追加は、Python に標準で付属する venv で仮想環境を作成し、その中で行う。

  1. Raspberry Pi にリモートログインする

    画面表示を伴うプログラムを実行するため、ssh では -X オプション(X11 転送)を付ける。ユーザ名とホスト名は、Raspberry Pi Imager で設定したものを指定する。

    ssh -X pi@raspberrypi.local
    
  2. ビルドに必要なパッケージのインストール

    dlib は C++ で書かれており、Python から使うためにはソースコードからのビルドが必要である。そのために cmake とコンパイラを導入する。

    # パッケージリストの情報を更新
    sudo apt update
    sudo apt -y install cmake build-essential pkg-config python3-dev python3-venv libopenblas-dev libjpeg-dev libpng-dev
    
  3. venv を使って、隔離された Python 環境を作る

    ここでは、仮想環境を $HOME/dlibenv に作成する

    python3 -m venv $HOME/dlibenv
    source $HOME/dlibenv/bin/activate
    python -m pip install -U pip setuptools wheel
    

dlib のインストール

  1. 端末で、次のコマンドを実行し、Python 仮想環境 $HOME/dlibenv を有効にする
    source $HOME/dlibenv/bin/activate
    
  2. dlib と、画像処理に使う numpy, pillow のインストール

    dlib はソースコードからビルドされるため、Raspberry Pi では 20 分から 40 分程度かかる。

    python -m pip install -U numpy pillow
    python -m pip install -U dlib
    
    搭載メモリが 2G バイト以下の Raspberry Pi では、ビルド中にメモリ不足でエラーになることがある。その場合は、次のコマンドでスワップ領域を 2048M バイトに増やしてからビルドを行う。ビルド後は、CONF_SWAPSIZE を元の値に戻しておく。
    sudo sed -i 's/^CONF_SWAPSIZE=.*/CONF_SWAPSIZE=2048/' /etc/dphys-swapfile
    sudo systemctl restart dphys-swapfile
    
  3. 確認

    バージョン番号が表示されれば、インストールは成功している

    python -c "import dlib; print( dlib.__version__ )"
    

学習済みモデルファイルのダウンロード

  1. 次のコマンドで、3つのファイルをダウンロードする

    この3つのファイルについての説明は、trydlib.html の「学習済みモデルデータのダウンロードの展開(解凍)」のところにある

    cd /tmp
    wget http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2
    wget http://dlib.net/files/dlib_face_recognition_resnet_model_v1.dat.bz2
    wget http://dlib.net/files/mmod_human_face_detector.dat.bz2
    ls -la *.bz2
    
  2. 展開(解凍)し、/usr/local/dlib にコピー
    cd /tmp
    bzip2 -d shape_predictor_5_face_landmarks.dat.bz2
    bzip2 -d dlib_face_recognition_resnet_model_v1.dat.bz2
    bzip2 -d mmod_human_face_detector.dat.bz2
    sudo mkdir -p /usr/local/dlib
    sudo cp /tmp/*.dat /usr/local/dlib
    ls -la /usr/local/dlib
    

サンプル画像を用いた動作確認

  1. 端末で、次のコマンドを実行し、Python 仮想環境 $HOME/dlibenv を有効にする
    source $HOME/dlibenv/bin/activate
    
  2. dlib のソースコード一式を取得する

    サンプルプログラムとサンプル画像を使うために取得する

    cd /tmp
    rm -rf dlib
    git clone https://github.com/davisking/dlib
    
  3. 動作確認

    サンプル画像から顔を検出し、顔の特徴量(128 次元のベクトル)を求めるプログラムである。検出結果が画面に表示されるため、ssh の -X オプションによる X11 転送が必要である。

    cd /tmp/dlib/examples/faces
    python /tmp/dlib/python_examples/face_recognition.py /usr/local/dlib/shape_predictor_5_face_landmarks.dat /usr/local/dlib/dlib_face_recognition_resnet_model_v1.dat .
    

カメラで撮影した画像で顔検出

  1. Raspberry Pi の電源を切った状態で、カメラモジュールを CSI コネクタに接続する

    ケーブルの金属端子の向きを合わせて差し込む。接続後に電源を入れる。

  2. 端末で、カメラが認識されていることを確認する

    接続されているカメラの一覧が表示される

    rpicam-hello --list-cameras
    
    Raspberry Pi OS の Bookworm 以降では、カメラ用のコマンド名は rpicam-* である。Bullseye 以前では libcamera-*(libcamera-hello, libcamera-jpeg など)を使用する。
  3. 静止画を撮影し、/tmp/capture.jpg に保存する
    rpicam-jpeg --output /tmp/capture.jpg --width 1280 --height 960 --timeout 2000
    
  4. 端末で、次のコマンドを実行し、Python 仮想環境 $HOME/dlibenv を有効にする
    source $HOME/dlibenv/bin/activate
    
  5. 撮影した画像に対して顔検出を行う

    dlib の get_frontal_face_detector(HOG 特徴量と SVM による顔検出器)を用いる。検出された顔の個数と、顔の外接矩形の座標を表示し、矩形を描き込んだ画像を /tmp/result.jpg に保存する。

    python << 'EOS'
    import dlib
    from PIL import Image, ImageDraw
    
    img_path = '/tmp/capture.jpg'
    detector = dlib.get_frontal_face_detector()
    img = dlib.load_rgb_image(img_path)
    
    # 第2引数は画像の拡大回数。1 にすると小さい顔も検出しやすくなる
    dets = detector(img, 1)
    print("Number of faces detected: {}".format(len(dets)))
    
    pil_img = Image.open(img_path).convert('RGB')
    draw = ImageDraw.Draw(pil_img)
    for i, d in enumerate(dets):
        print("Face {}: Left {} Top {} Right {} Bottom {}".format(
            i, d.left(), d.top(), d.right(), d.bottom()))
        draw.rectangle([d.left(), d.top(), d.right(), d.bottom()],
                       outline=(0, 255, 0), width=3)
    
    pil_img.save('/tmp/result.jpg')
    print('saved: /tmp/result.jpg')
    EOS
    
  6. 結果の画像を表示して確認する

    ImageMagick の display コマンドで表示する。画面表示には、ssh の -X オプションによる X11 転送が必要である。

    sudo apt -y install imagemagick
    display /tmp/result.jpg