【実践】PythonとOpenCVで作る顔認識システム(Haar CascadeからDNNまで徹底比較)

プログラミング

コンピュータビジョン領域において「顔認識(Face Detection / Recognition)」は最も歴史が深く、かつ現在でも需要が高い技術の一つです。店舗の顧客分析からスマートフォンの生体認証まで、私たちの生活のあらゆる場面で活用されています。

本記事では、OpenCVを用いた顔検出の基礎技術である「Haar Cascade分類器」による古典的アプローチから始まり、現在主流となっている「DNN(Deep Neural Network)モジュール」を用いた高精度な顔認識パイプラインの構築まで、Pythonの実装コードを交えながら徹底的に解説します。

1. Haar Cascade分類器:古典的かつ超軽量なアプローチ

2001年にPaul ViolaとMichael Jonesによって発表されたHaar特徴量ベースのカスケード分類器は、リアルタイム顔検出に革命をもたらしました。特定の明るさのパターン(Haar特徴)を大量の画像から学習し、画像内をスライディングウィンドウで走査しながら顔を探します。

import cv2
def detect_face_haar(image_path):
    # 画像の読み込みとグレースケール変換(Haarは輝度情報のみを使うため)
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # OpenCVに標準同梱されているHaar Cascadeファイルの読み込み
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    # 顔検出の実行(scaleFactorとminNeighborsで感度を調整)
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
    return img

このアプローチの最大のメリットは圧倒的な軽さです。安価なマイコンデバイスでもリアルタイムで動作します。しかし、「顔が横や上下を向いている」「照明が極端に暗い・明るい」「一部が隠れている」といったケースでは極端に精度が低下するという弱点があります。

2. DNNモジュールによる次世代の顔検出(ResNet)

Haar Cascadeの弱点を克服し、現代の実用レベルに達しているのがDeep Learningを用いた顔検出です。OpenCVの cv2.dnn モジュールを使えば、TensorFlowやCaffeで事前学習されたResNetベースの顔検出モデルなどをそのまま実行できます。

DNNベースのアプローチは、マスクをしている顔や、極端な角度の顔でも高確率でディテクトできるため、セキュリティシステムなどの厳しい要件に最適です。

def detect_face_dnn(image_path, prototxt_path, model_path):
    # CaffeベースのResNet SSDモデルをロード
    net = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
    
    img = cv2.imread(image_path)
    h, w = img.shape[:2]
    # 画像をBlob形式に変換(300x300にリサイズ、チャネル毎の平均値を引く)
    blob = cv2.dnn.blobFromImage(cv2.resize(img, (300, 300)), 1.0, 
                                 (300, 300), (104.0, 177.0, 123.0))
    net.setInput(blob)
    detections = net.forward()
    # 検出結果を解析
    for i in range(0, detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        
        # 信頼度が50%以上のものだけを描画
        if confidence > 0.5:
            box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
            (startX, startY, endX, endY) = box.astype("int")
            # 確信度のテキストとバウンディングボックスを描画
            text = f"{confidence * 100:.2f}%"
            cv2.rectangle(img, (startX, startY), (endX, endY), (0, 0, 255), 2)
            cv2.putText(img, text, (startX, startY - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
    return img

3. 開発・検証用デバイスの選び方

実際に上記のコードをリアルタイムビデオストリーム(映像)に対して実行し、パラメータ調整を行うには、安定したフレームレートが出せる定番のWebカメラ検証環境が必須です。

まとめ:次のステップ「顔の識別(Recognition)」

本記事で紹介したのは、画像の中から「顔の位置を見つける(Face Detection)」処理です。実際のビジネスでは、その顔が「見知らぬ人か、登録されたAさんか」を判別する「Face Recognition(顔認証)」にステップアップする必要があります。
顔認証に進むにあたり、Deep Learningの基礎となるニューラルネットワークの数学的構造を理解しておくと、トラブルシューティングが格段にしやすくなります。基礎固めとして以下の書籍などを一読しておくことを強く推奨します。

コメント

タイトルとURLをコピーしました