👱Python+OpenCVで顔認証してみた

Face Recognition PCソフト開発

画像処理の練習で顔認証に挑戦してみたらうまくいったので、日記的に残しておきます。

1.動作環境

  • Windows 11
  • VSCode Ver. 1.108.0
  • Python言語 Ver3.13.1
  • OpenCV (画像処理ライブラリ)、 opencv-python
  • Jupyter (VSCodeで対話的なプログラミング実行をサポートするライブラリ)

2. ライブラリのインストール

opencv-pythonのインストールをします。Jupyter Note Bookのセルで実行します。その他matplotlibなど必要ライブラリを適宜インストールしてください。

Bash
%pip install opencv-python

3. 顔認証の実装コード

Python
import cv2
import matplotlib.pyplot as plt
import os

def detect_and_sort_faces(image_path, max_faces=6):
    # 1. 画像の読み込み
    img = cv2.imread(image_path)
    if img is None:
        print("画像が見つかりません。パスを確認してください。")
        return

    # OpenCVはBGR形式なので、表示用にRGB形式に変換
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # 検出用にグレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 2. 学習済みモデル(カスケード分類器)の読み込み
    # OpenCVに標準で含まれている顔検出用ファイルを使用
    face_cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
    face_cascade = cv2.CascadeClassifier(face_cascade_path)

    # 3. 顔の検出
    # scaleFactor: 画像を縮小して検出する際の倍率
    # minNeighbors: 信頼性のしきい値
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.05, minNeighbors=5, minSize=(30, 30))

    # 4. 面積(w * h)が大きい順にソート
    # facesは (x, y, w, h) のリスト
    faces_sorted = sorted(faces, key=lambda f: f[2] * f[3], reverse=True)

    # 5. 上位指定人数(最大4人)までに絞り込む
    faces_to_draw = faces_sorted[:max_faces]

    print(f"検出された顔の数: {len(faces)}")
    print(f"描画対象(面積上位): {len(faces_to_draw)}人")

    # 6. 枠の描画
    for i, (x, y, w, h) in enumerate(faces_to_draw):
        # 枠を描画(RGB形式に合わせて青色: (0, 0, 255) などに設定)
        # 面積順位をテキストで表示
        cv2.rectangle(img_rgb, (x, y), (x + w, y + h), (255, 0, 0), 3)
        cv2.putText(img_rgb, f"No.{i+1}", (x, y - 10), 
                    cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255, 0, 0), 2)

    # 7. 結果の表示
    plt.figure(figsize=(12, 8))
    plt.imshow(img_rgb)
    plt.axis('off')
    plt.show()

# --- 実行 ---
# ここに作成した画像のファイル名を指定してください
# 例: 'sample.jpg'
image_file = r"1-person.png" 

if os.path.exists(image_file):
    detect_and_sort_faces(image_file, 4)
else:
    print(f"ファイル '{image_file}' が現在のディレクトリに存在しません。")

4. コードのポイント

このコードでは、OpenCVの「Haar Cascade分類器」を使用します。検出された顔を面積(幅 × 高さ)でソートし、上位4人までに限定して枠を描画します。
処理画像のファイルは、54行目で指定しています。

  • 面積順のソート: sorted関数のkeylambda f: f[2] * f[3] を指定することで、幅(w)と高さ(h)を掛け合わせた面積で並び替えています。
  • 人数の制限: [:max_faces] でスライスすることで、検出された顔が多数あっても、面積の大きい(重要な)上位6人だけに絞り込んでいます。
  • Jupyterでの表示: cv2.imshow は別ウィンドウが開いてしまいVS Code上で止まることがあるため、matplotlib を使ってインラインで表示するようにしています。

5. 認証結果

5.1 1人のみの画像

5.3 4人の画像

6.まとめ

Python + OpenCVで手軽に顔認証ができることがわかりました。しかり、証明の当たり方が不均一(顔の半分が暗いなど)では、検出率がさがるようです。その場合は、顔認識の前処理が必要になるかもしれません。
微調整なら、下記パラメータをいじることでうまくいくと思います。(あまりやってませんが。)

  • scaleFactor
    検出できない顔がある場合: 1.05 などに下げます。より細かく計算しますが、計算時間は増えます。
  • minNeighbors
    誤検出が多い場合: 610 程度に上げます。検出されない場合: 3 程度に下げます。
  • minSize
    遠くの小さな顔が消える場合: (20, 20) などに下げます。ただし誤検出は増えます。