Raspberry Pi顔認識の次のステップ:face_recognitionライブラリで「顔認証」を実装する
はじめに
前回の記事「Raspberry PiとOpenCVではじめるリアルタイム顔認識入門」では、カメラ映像から顔を「検出」する方法を解説しました。
今回はその次のステップとして、検出した顔が事前に登録した「誰」の顔なのかを「認証」する、本格的な顔認証システムの構築に挑戦します。
このプロジェクトの主役は、dlib
という強力な機械学習ライブラリをラップした、face_recognition
というPythonライブラリです。これを使うことで、驚くほど少ないコードで高精度な顔認証を実装できます。
Step 1: 「顔検出」と「顔認証」の違い
まず、言葉の整理をしておきましょう。
- 顔検出 (Face Detection): 画像や映像の中から、顔が 「あるかどうか」 を見つける技術です。(前回やったこと)
- 顔認証 (Face Recognition): 検出した顔が、登録済みのデータと照合して 「誰の顔なのか」 を特定する技術です。(今回やること)
face_recognition
ライブラリの準備
Step 2: 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 「学習」フェーズ:既知の顔を覚える
まず、認証させたい人物の顔写真を準備します。
- プロジェクトディレクトリに
known_faces
というフォルダを作成します。 - その中に、
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
Discussion