🔑

Raspberry Pi顔認識の次のステップ:face_recognitionライブラリで「顔認証」を実装する

に公開

はじめに

前回の記事「Raspberry PiとOpenCVではじめるリアルタイム顔認識入門」では、カメラ映像から顔を「検出」する方法を解説しました。

今回はその次のステップとして、検出した顔が事前に登録した「誰」の顔なのかを「認証」する、本格的な顔認証システムの構築に挑戦します。

このプロジェクトの主役は、dlibという強力な機械学習ライブラリをラップした、face_recognitionというPythonライブラリです。これを使うことで、驚くほど少ないコードで高精度な顔認証を実装できます。

Step 1: 「顔検出」と「顔認証」の違い

まず、言葉の整理をしておきましょう。

  • 顔検出 (Face Detection): 画像や映像の中から、顔が 「あるかどうか」 を見つける技術です。(前回やったこと)
  • 顔認証 (Face Recognition): 検出した顔が、登録済みのデータと照合して 「誰の顔なのか」 を特定する技術です。(今回やること)

Step 2: face_recognitionライブラリの準備

face_recognitionは非常に強力ですが、Raspberry Piにインストールする際には少し注意が必要です。依存しているdlibのコンパイルに時間がかかります。

依存パッケージのインストール

sudo apt-get update
sudo apt-get install build-essential cmake pkg-config
sudo apt-get install libx11-dev libatlas-base-dev
sudo apt-get install libgtk-3-dev libboost-python-dev

Pythonライブラリのインストール

pip3 install dlib
pip3 install face_recognition

⚠️【重要】dlibのコンパイルには時間がかかります!
Raspberry Pi 4でも、pip3 install dlibの実行には30分〜1時間以上かかることがあります。処理が止まっているように見えても、気長に待ってください。Pi本体が熱を持つため、ヒートシンクを付けておくことを強く推奨します。

Step 3: 顔認証システムの構築

システムは大きく分けて、①既知の顔を学習させる「エンコード」フェーズと、②リアルタイムで照合する「認証」フェーズの2つで構成されます。

3.1 「学習」フェーズ:既知の顔を覚える

まず、認証させたい人物の顔写真を準備します。

  1. プロジェクトディレクトリにknown_facesというフォルダを作成します。
  2. その中に、suzuki.jpg, tanaka.pngのように、「名前.拡張子」の形式で顔写真を入れます。

次に、これらの写真から顔の特徴量(エンコーディング)を抽出し、ファイルに保存するスクリプト(encode_faces.py)を作成します。

encode_faces.py

import face_recognition
import pickle
import os

print("顔画像のエンコードを開始します...")
known_encodings = []
known_names = []

# known_facesディレクトリ内の各画像をループ
for image_name in os.listdir("known_faces"):
    # 画像をロード
    image_path = os.path.join("known_faces", image_name)
    image = face_recognition.load_image_file(image_path)
    
    # 顔のエンコーディングを取得 (画像内の最初の顔)
    # 存在しない場合はスキップ
    encodings = face_recognition.face_encodings(image)
    if len(encodings) > 0:
        encoding = encodings[0]
        
        # エンコーディングと名前をリストに追加
        known_encodings.append(encoding)
        known_names.append(os.path.splitext(image_name)[0]) # ファイル名から拡張子を除いたものを名前とする

# エンコーディングと名前をファイルに保存
data = {"encodings": known_encodings, "names": known_names}
with open("encodings.pickle", "wb") as f:
    f.write(pickle.dumps(data))

print("エンコードが完了しました。")

このスクリプトを実行すると、encodings.pickleというファイルが生成されます。これが、私たちの「顔のデータベース」になります。

3.2 「認証」フェーズ:リアルタイムで顔を照合する

次に、カメラの映像から顔を検出し、先ほど作成したデータベースと照合するメインのスクリプト(recognize_faces.py)を作成します。

recognize_faces.py

import face_recognition
import pickle
import cv2

# Step 3.1で作成したエンコーディング情報をロード
with open("encodings.pickle", "rb") as f:
    data = pickle.load(f)

# カメラをキャプチャ
cap = cv2.VideoCapture(0)
# パフォーマンス改善のため解像度を下げる
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)

print("顔認証を開始します...")

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # BGR画像(OpenCV)をRGB画像(face_recognition)に変換
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # 映像中の顔の位置とエンコーディングを検出
    boxes = face_recognition.face_locations(rgb_frame, model="hog")
    encodings = face_recognition.face_encodings(rgb_frame, boxes)

    names = []
    # 検出した各顔のエンコーディングをループ
    for encoding in encodings:
        # 既知のエンコーディングと照合
        matches = face_recognition.compare_faces(data["encodings"], encoding)
        name = "Unknown" # デフォルトは"Unknown"

        if True in matches:
            # マッチしたインデックスを取得
            matched_idxs = [i for (i, b) in enumerate(matches) if b]
            # 最初のマッチから名前を取得
            name = data["names"][matched_idxs[0]]
        
        names.append(name)

    # 認識結果を描画
    for ((top, right, bottom, left), name) in zip(boxes, names):
        # 矩形を描画
        cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
        # 名前を描画
        y = top - 15 if top - 15 > 15 else top + 15
        cv2.putText(frame, name, (left, y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2)

    cv2.imshow("Face Recognition", frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

このスクリプトを実行すると、カメラに写った顔がknown_facesフォルダ内の画像と一致すればその名前が、一致しなければ「Unknown」と表示されます。

パフォーマンスについて

リアルタイムの顔認証はRaspberry Piにとって非常に負荷の高い処理です。上記コードでは解像度を下げていますが、さらに処理を軽くしたい場合は、毎フレーム認証するのではなく、数フレームに1回だけ認証処理を行うのが効果的です。

おわりに

face_recognitionライブラリのおかげで、かつては専門家のものであった「顔認証」技術が、驚くほど手軽に試せるようになりました。
このシステムを応用すれば、

  • 特定の人物が来たらLINEで通知する
  • 家族の顔を認証して玄関の鍵をスマートロックで開ける
    といった、より未来的なプロジェクトに発展させることも可能です。ぜひ挑戦してみてください。

この記事で紹介した内容以外にも、技術情報をブログで発信しています。
MyNote by MEANTIX
https://mynote.meantix.com/

Discussion