0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】顔データの保存

Posted at

はじめに

顔認識をするときに毎回顔データの処理を行うのがめんどくさいと思ったので、初回起動時にデータを保存することにしました。
顔認識自体のコードは以下の記事を見てください。

実行環境

  • 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 ファイルにコピペして実行してください。
処理の流れは以下の通りです。

  1. face_data.pkl がある場合はロードし、顔データを利用
  2. face_data.pkl が無ければ、画像フォルダから顔データを取得し保存
  3. 画像処理が完了すると、カメラ映像が表示され顔認識が開始
  4. 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()

おわりに

顔認識プログラムを使うたびに毎回顔データを処理するのは時間がかかるので、
一度処理した顔データを保存して、次回以降はそのデータを利用できるようにしました。

これにより処理時間が短縮され、スムーズに顔認識を実行できます。
参考になれば嬉しいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?