はじめに
顔認識をするときに毎回顔データの処理を行うのがめんどくさいと思ったので、初回起動時にデータを保存することにしました。
顔認識自体のコードは以下の記事を見てください。
実行環境
- Python 3.11
- Windows 10
使用ライブラリ
ライブラリ名 | バージョン | 主な機能 |
---|---|---|
cv2 (opencv-python) |
4.10.0.84 | 画像処理ライブラリ |
face_recognition |
1.3.0 | 顔認識ライブラリ |
numpy |
2.2.1 | 数値計算ライブラリ |
tqdm |
4.67.1 | 進捗バー表示 |
以下のコマンドで一括インストールできます。
ライブラリのインストール
pip install opencv-python face-recognition numpy tqdm
バージョン指定は基本必要ないですが、エラーが起きる場合はバージョンを指定してみてください。
実装
以下のコードを .py
ファイルにコピペして実行してください。
処理の流れは以下の通りです。
-
face_data.pkl
がある場合はロードし、顔データを利用 -
face_data.pkl
が無ければ、画像フォルダから顔データを取得し保存 - 画像処理が完了すると、カメラ映像が表示され顔認識が開始
-
q
キーを押すと終了
顔認識する画像を変更した場合はface_data.pkl
を削除してください。
コード全文
import cv2
import face_recognition
import numpy as np
import os
import pickle # データ保存用
from tqdm import tqdm # プログレスバー表示ライブラリ
tolerance = 0.4
data_file = "face_data.pkl" # 保存するデータファイル名
# 顔データをロードする
def load_face_data(file):
if os.path.exists(file):
with open(file, "rb") as f:
return pickle.load(f)
return None
# 顔データを保存する
def save_face_data(file, encodings, names):
with open(file, "wb") as f:
pickle.dump((encodings, names), f)
# 既存データをロード
face_data = load_face_data(data_file)
if face_data:
known_face_encodings, known_face_names = face_data
print("顔データをロードしました。")
else:
print("顔データが見つからないため、新たに作成します。")
# 画像フォルダのパス
image_folder = 'images/'
# 画像を読み込み、顔の特徴を記録する
known_face_encodings = []
known_face_names = []
# フォルダごとに画像を処理
folder_list = [folder for folder in os.listdir(image_folder) if os.path.isdir(os.path.join(image_folder, folder))]
# tqdm を使ってフォルダの処理状況を表示
for foldername in tqdm(folder_list, desc="Processing Folders"):
folder_path = os.path.join(image_folder, foldername)
# フォルダ内の画像ファイルを処理
image_files = [f for f in os.listdir(folder_path) if f.endswith(".jpg")]
# tqdm を使ってフォルダ内の画像ファイルの処理状況を表示
for filename in tqdm(image_files, desc=f"Processing Images in {foldername}", leave=False):
image_path = os.path.join(folder_path, filename)
image = face_recognition.load_image_file(image_path)
encoding = face_recognition.face_encodings(image)
if encoding:
# 複数の画像から同じ人物の特徴を追加
known_face_encodings.append(encoding[0])
known_face_names.append(foldername) # フォルダ名を表示名として取得
# データを保存
save_face_data(data_file, known_face_encodings, known_face_names)
print("顔データを保存しました。")
# カメラを初期化
video_capture = cv2.VideoCapture(0)
process_this_frame = True
while True:
ret, frame = video_capture.read()
if process_this_frame:
# ここで顔認識処理
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
rgb_small_frame = np.ascontiguousarray(small_frame[:, :, ::-1])
# 顔検出と顔認識
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
# 顔の座標を拡大して元のフレームに戻す
face_locations = [(top * 4, right * 4, bottom * 4, left * 4) for (top, right, bottom, left) in face_locations]
# 毎フレーム処理を行わないようにする
process_this_frame = not process_this_frame
# 各顔に対して認識
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
matches = face_recognition.compare_faces(known_face_encodings, face_encoding, tolerance=tolerance) # 厳しくするならtoleranceを小さく
name = "Unknown"
# マッチした顔があれば名前を取得
if True in matches:
first_match_index = matches.index(True)
name = known_face_names[first_match_index]
# 顔の周りにボックスを描画
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 0.5, (255, 255, 255), 1)
# フレームを表示
cv2.imshow('Video', frame)
# 'q'キーが押されたらループを終了
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# カメラを解放し、ウィンドウを閉じる
video_capture.release()
cv2.destroyAllWindows()
おわりに
顔認識プログラムを使うたびに毎回顔データを処理するのは時間がかかるので、
一度処理した顔データを保存して、次回以降はそのデータを利用できるようにしました。
これにより処理時間が短縮され、スムーズに顔認識を実行できます。
参考になれば嬉しいです。