01.02 DeepFace ~顔照合・顔/眼抽出~

前回本サイトで「python未来の技術」と題した「感情分析」にライブラリ「DeepFace」を用いました。当時使用していたpython仮想環境py36からpythonのバージョンを「3.9」に上げ、新バージョンのDeepFaceを使用したサンプルプログラムで動作を確認しました。 「感情分析」という目新しい機能を試すためネット検索するとDeepFaceが真っ先にピックアップされますが、実は感情・年齢・人種を分析する機能は「顔に関するライブラリ」の一部分でしかありません。 DeepFaceは「顔認識」が正確に行えるようになったことで、顔を分析したり認証したりが可能になりました。

そこで原点に立ち返り、DeepFaceの基になっている「顔認識」「顔認証」を解析・調査していきます。

まず、 顔認識システム概要とは、
    検出(detect) ⇒ 整列(align) ⇒ 表現(represent) ⇒ 分類(classify)
という4つの段階で構成されます。
以降で詳しく説明しますが、顔認識の精度が購入した大きな要因はニューラルネットワークが使用されるようになったからと言えます。DeepFaceで使用されるネットワーク構成は9層からなり、1億2千万のパラメータが含まれ、標準的畳み込みは使用せず、重みを共有しないローカルな接続モデルを使用します。4千を超えるアイデンティティに属する400万のラベル付きデータセットで学習され、最終的に97.35%の精度を持っているとしています。(以降引用する画像は「DeepFace: Closing the Gap to Human-Level Performance in Face Verification」(Yaniv Taigman, Ming Yang, Marc’Aurelio Ranzato,Lior Wolf)からの引用)

詳細を知りたい方は、下記サイトから論文をダウンロードできます。
https://research.facebook.com/publications/deepface-closing-the-gap-to-human-level-performance-in-face-verification/

★ DeepFace ~顔認識~

本サイト最初に見よう見まねでワオキツネザル顔認識システムでは第一世代OpenCVカスケード分類器が使用されていました。カスケード分類器は、機械学習によって指定した部位やモノを識別します。



次に使用したのが三世代オブジェクト検出「YOLO」で画像から「人」を検出するとともに、提示した画像に写っているモノ=「オブジェクト」を検出出来るようになりました。



画像の中から特定のオブジェクトを検出する「オブジェクト検出」とカテゴリーへと変化してきました。実際には「見分けている」「識別する」のではなく、ニューラルネットワークが分類しているためです。
「識別」が可能になったtことで、「顔」を検出する「顔認識」、比較評価するのが「顔認証」、他のニューラルネットワークを使用した「感情分析」が可能になったというストーリで、世代によりどんどんと用途も機能も変化してきたということ、その点を少しまとめておきます。


【オブジェクト検出第一世代】
オブジェクト検出第一世代が「sliding windows approach」、つまり検出窓をスライドさせ物体を検出する技術を指し、openCVのカスケード分類器がその代表例です。機械学習による「パーツ検出する技術」で、ターゲットは「特定パーツ」であり、機械学習時のデータセットの種類により「特定パーツ」が一意的に決定されました。

【オブジェクト検出第二世代】
第二世代はディープラーニング技術の進化とともに機械学習からR-CNN(Regions with CNN)に変化したことによって、対象が「特定パーツ」から「オブジェクト識別」という概念に変化しました。一方では収集できる情報の数も増加したため、物体認識精度需要により実装には高速かつ高精度が求められるようになりました。

【オブジェクト検出第三世代】
そこで登場したのが第三世代、一般的には「End to end」の時代と称される「検出」と「認識」を同時に複数個行う手法で、「検出」も「認識」もCNNを用います。その代表格は「YOLO」です。「YOLO」解説によると、 『オブジェクト検出に関する以前の作業では、分類子を再利用して検出を実行します。代わりに、オブジェクト検出を空間的に分離されたバウンディングボックスへの回帰問題としてフレーム化し、関連するクラス確率。単一のニューラルネットワークは、バウンディングボックスとクラス確率を直接予測します』



この「オブジェクト検出」の技術的変化を実感してみましょう。

第一世代「sliding windows approach」を使用したopenCVのカスケード分類器で、ニューラルネットワークが普及していなかったため「機械学習」で行っていました。
その技法は本サイトでやった「OCR手法」に類似する点が多く、フォントで書かれた文字OCRで、文字行と空白行の境目を検出する技術で使用した「Haar-Like特徴計算」を用います。



「Haar-Like特徴」とは単純に言うと、画像に対し指定された矩形窓をスライドさせながら画像の明暗を抽出し抽象化したイメージから、機械学習によって顔や顔パーツを探すという技術です。



但し、実際に使用してみると誤認率が非常に高いことから、機械学習から普及し始めたニューラルネットワークを用いるR-CNN(Regions with CNN)という物体検出専用モデルを使用する第二世代オブジェクト検出へ移行していったということです。
R-CNNによる物体検出は3つのパートに分かれています。
    ・ パートが領域提案(Region Proposal)
    ・ CNNによる候補領域の特徴抽出部分
    ・ サポートベクターマシン(SVM)による候補内の物体の分類

つまり、個別の機械学習からCNNに変化したことで、「オブジェクト検出」の識別できる数が増加するとともに高速かつ正確に認識が可能になったことで、広範囲なカテゴリ検出に変化していきました。しかし逆説的に解釈すると、第一世代が顔パーツを識別していましたが、広範囲検出されたことで顔に特化したモジュールがなくなったと言えます。もしかしたら第一世代も第二世代も顔パーツ検出精度に大きな差がなかったのかもしれません。

CNNは入力形状を行ベクトルではなく3層RGBのピクセルデータを使用することで、位置と色を情報として取り入れることが出来るようになりましたが、実装時学習精度は必ずしもよい結果とは言えませんでした。一番の原因は、キャプチャした顔写真の顔の向きがバラバラな方向を向いている点にあります。

そこで登場してきたのは第三世代オブジェクト検出です。

① 精度の良い顔キャプチャ
キャプチャーに非常に多くのデータセットを使用した学習済みネットワークが使用されたことで、 精度の良い顔の外観キャプチャーが出来るようになりました。

② 3Dモデリング
第三世代オブジェクト検出モジュール「DeepFace」は顔に特化したと言え、顔をキャプチャした後3Dモデリング前処理を行い、学習を行うようになりました。

③ 3Dモデリング中の顔の位置合わせシステム
「DeepFace」では 前処理で3Dモデリングすることで顔パーツを3Dで位置を把握することが出来る様になりました。 実際に論文に掲載されている手順は次の通りです。

    a)6つの初期基準点を顔から抽出
            ↓
    b)2D整列された画像変換
            ↓
    c)67基準点対応Delaunary三角部位分割し2Dブロック変換
            ↓
    d)クロックイメージプレーンに変換された2D形状
            ↓
    e)トライアングル付き2D-3D可視化画像
            ↓
    f)3D誘導された67基準点画像変換
            ↓
    g)改認識結果最終物
            ↓
    h)3Dモデルによる生成物



④ 入力とネットワーク構造
DeepFaceは今までのように画像ピクセルを直接入力とするのではなく、3Dモデリング等の前処理をしたデータを入力として再構築されました。
このため、顔検出と顔の位置合わせ等に必要なライブラリも提供されます。 検出器のバックエンドはtensorflowとKerasを使用しており、顔画像学習は基本CNNを使用したオートエンコーダを使用し、全て学習済みモデルをダウンロードして使用します。



3Dモデリングと tensorflowとKerasを使用することでGPUの使用が可能になり、高速に顔の特徴点を立体的に抽出できるようになり、それは横向いていても正面を向いた姿を推定できるようになったことを意味します。



前回行った「感情分析」は顔認識結果を分析したにすぎず、DeepFaceの本来の顔認識技術のほんの一部であったことが分かり、これ以降が重要になってきます。

非常に長い前振りでしたが、サンプルプログラムで試していきましょう。

★ 顔認証(Facial Verification)解説

【要注意 事前審査結果】
現在2024/03/14時点での話です。
HP掲載前事前調査を行いましたところ仮想環境py36(python 3.6)では動作しますが、py39(python3.9)ではエラーになるとが確認されています。

原因は最新版「tensorflow(2.16.0)」
にあることが判明しました。

仮想環境 py36 py39
python 3.6.10 3.9.18
deepface 0.0.75 0.0.86
tensorflow 1.14.0 2.16.0

DeepFaceは内部処理でtensorflowを使用しますが、tensorflowバージョンが(~2.15.0)に限定されており、最新版2.16.0はエラーとなります。
DeepFaceは実行するメソッドや使用する学習モデル等々により付帯的に使用するモジュールが異なります。事前調査でインストール要求と共にエラーになった必要になったモジュールを調査しました。以降で実施する試験は、モデル・バックエンド・類似度・正規化の全ての組み合わせをチェックした際に必要としたモジュールになります。


【事前注意点】
一般的モジュールはモジュール不足時エラーコメントを出しますが、For文を使用した全試験ではエラーコメントが出ず停止しました。このため、1つずつデバッグしてエラーを確認する必要があり少々面倒です。

このためディスク容量がない方・試験しない方・デフォルト使用する方は不要となります。但し、前述のようにエラーなしでスルーする場合があるので注意してください。
ディスク容量に余裕がある方は、全てを事前にインストールしておきましょう。

pip install tensorflow==2.15.0
pip3 install mecab-python3
pip install psutil
pip install dlib
pip install ultralytics
pip install facenet-pytorch
pip install mediapipe

仮想環境 py36 py39
python 3.6.10 3.9.18
deepface 0.0.75 0.0.86
tensorflow 1.14.0 2.15.0

【使用環境】
Python               3.9.18
opencv-python    4.8.1.78
deepface             0.0.86



最初に行いますサンプルプログラムは「顔認証」カテゴリ内の「Facial Verification(顔照合)」です。二つの画像を用意し顔のみを比較し同一人物かを照合します。

【ポイント】
・ 用意する写真サイズは制限がありません。
・ 同一サイズではなくても構いません。
・ 「同じような写真」「髪型が違う」「一方が横を向いている」でレベルが異なります。
・ 今回の試験はpython仮想環境py39で実装してください。

尚、DeepFaceモジュールは必要とされる学習済パラメータを自動でネットからダウンロードしますのでネット環境で実施してください。またGPUの使用の有無はtensorflowとCUDAの関係によって自動使用されます。
初回試験は「同じような方向を向き、髪型が異なる」レベル1の写真を選択しました。


【使用画像】





【顔認識・顔抽出】
DeepFaceは最初に「顔抽出=キャプチャー」を実施します。
バックエンドとして機能するオブジェクト検出器を複数個ラップしており選択肢てて使用します。OpenCV がデフォルトの検出器です。

【バックエンド(backends)】
# /// バックエンド(backends)
# /// オプションの検出器バックエンド入力引数を受け入れます。
# /// この引数を使用して、これらの検出器を切り替えることができます。 OpenCV がデフォルトの検出器です。
# ////////////////////////////////////////////////////////////////////////////
backends = [
  'opencv',
  'ssd',
  'dlib',
  'mtcnn',
  'retinaface',
  'mediapipe',
  'yolov8',
  'yunet',
  'fastmtcnn',
]



【3Dモデリングとディープラーニングモデル】
使用されるディープラーニングモデルは、VGG-Face、Google FaceNet等複数ラップされており、使用時にダウンロードされ使用します。デフォルト設定では VGG-Face モデルが使用されます。



【顔認識モデル(models)】
# /// 顔認識モデル(models)
# ///   ハイブリッド顔認識パッケージです。多くの最先端の顔認識モデル、VGG-Face、Google FaceNet,,,をラップ
# ///   デフォルト設定では VGG-Face モデルが使用
# ////////////////////////////////////////////////////////////////////////////
models = [
  "VGG-Face",
  "Facenet",
  "Facenet512",
  "OpenFace",
  "DeepFace",
  "DeepID",
  "ArcFace",
  "Dlib",
  "SFace",
]



【照合】
顔認識モデルCNNで顔はベクトルとして表現されます。このため結果の評価・照合はベクトル間の「類似度」を計算します。類似度には、コサイン類似度、ユークリッド距離、L2 形式などがラップされており選択して使用します。デフォルト設定ではコサイン類似度が使用されています。最近の研究では、コサインや通常のユークリッド距離よりもユークリッド L2 形式が安定していると報告されています。

【類似度( metrics)】
# /// 類似度( metrics)
# ///   顔認識モデルは通常の畳み込みニューラル ネットワークであり、顔をベクトルとして表現する役割を果たします。
# ///   類似度は、コサイン類似度、ユークリッド距離、L2 形式などのさまざまな指標によって計算できます。
# ///   デフォルト設定ではコサイン類似度が使用されます。
# ///   実験によると、ユークリッド L2 形式はコサインや通常のユークリッド距離よりも安定しているようです。
# ////////////////////////////////////////////////////////////////////////////
metrics = ["cosine", "euclidean", "euclidean_l2"]

★ 顔認証(Facial Verification)実装

顔照合処理をサンプルプログラムとして実装してみましょう。

今回はライブラリー化を視野に、顔認識モデル・類似度・バックエンド選択肢を全て表記してパラメータ入力方式にしてあります。また、今回使用するメソッドはフルパラメータ表示としました。

【構文】
画像のペアが同じ人物を表しているのか、それとも異なる人物を表しているのかを確認します。
def verify(
    img1_path: Union[str, np.ndarray, List[float]],
    img2_path: Union[str, np.ndarray, List[float]],
    model_name: str = "VGG-Face",
    detector_backend: str = "opencv",
    distance_metric: str = "cosine",
    enforce_detection: bool = True,
    align: bool = True,
    expand_percentage: int = 0,
    normalization: str = "base",
    silent: bool = False,
) -> Dict[str, Any]:

【引数】
・ img1_path (str or np.ndarray or List[float]): 最初の画像へのパス。
画像パスを文字列、numpy配列(BGR)、base64でエンコードされた画像

・ img2_path (str or np.ndarray or List[float]):2番目の画像へのパス。
画像パスを文字列、numpy配列(BGR)、base64でエンコードされた画像

・ model_name (str): 顔認識のモデル。
オプション:VGG-Face、Facenet、Facenet512、 OpenFace、DeepFace、DeepID、Dlib、ArcFace、SFace (デフォルトは VGG-Face)。

・ detector_backend (文字列): 顔検出バックエンド。
オプション: 'opencv', 'retinaface','mtcnn', 'ssd', 'dlib', 'mediapipe', 'yolov8' (デフォルトは opencv)。

・ distance_metric (文字列): 類似性を測定するためのメトリック。
オプション: 'cosine'、 'euclidean'、'euclidean_l2' (既定値は cosine)。

・ enforce_detection (ブール値): 画像内で顔が検出されない場合、例外を発生させます。
低解像度の画像の例外を回避するには、False に設定します (既定値は True)。

・ align (bool): 顔のアライメントを有効にするフラグ (既定値は True)。

・ expand_percentage (int): 検出された顔の領域をパーセンテージで拡大します
 (既定値は 0)。

・ normalization (文字列): 入力画像をモデルに供給する前に正規化します。
オプション: base、raw、Facenet、Facenet2018、VGGFace、VGGFace2、ArcFace(デフォルトはbase)

・ silent (ブール値): 一部のログメッセージを抑制または許可します
(既定値は False です)。


【DF_FaceVerification_test01A.py】
#coding: utf-8
# ////////////////////////////////////////////////////////////////////////////
# ///【DeepFace・顔認証(Facial Verification)】
# ////////////////////////////////////////////////////////////////////////////
if "__file__" in globals():
    import os, sys
    sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
    sys.path.append(os.path.join(os.path.dirname(__file__), "..") + "//..//")
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
from DeZero.common.nlp_util import *
import cv2
from deepface import DeepFace
tensorflow_warning_cancel()

if __name__ == "__main__":
    img1_path = "c:\\Photo\\aragaki.jpg"
    img2_path = "c:\\Photo\\aragaki-2.jpg"

    # /// 顔認識モデル(models)
    # ////////////////////////////////////////////////////////////////////////////
    models = [
      "VGG-Face",
      "Facenet",
      "Facenet512",
      "OpenFace",
      "DeepFace",
      "DeepID",
      "ArcFace",
      "Dlib",
      "SFace",
    ]

    # /// バックエンド(backends)
    # ////////////////////////////////////////////////////////////////////////////
    backends = [
      'opencv',
      'ssd',
      'dlib',
      'mtcnn',
      'retinaface',
      'mediapipe',
      'yolov8',
      'yunet',
      'fastmtcnn',
    ]

    # /// 類似度( metrics)
    # ////////////////////////////////////////////////////////////////////////////
    metrics = ["cosine", "euclidean", "euclidean_l2"]

    # /// 顔照合(face verification)
    # ////////////////////////////////////////////////////////////////////////////
     verification = DeepFace.verify(
        img1_path=img1_path,                        # img1_path: Union[str, np.ndarray, List[float]]
        img2_path=img2_path,                        # img2_path: Union[str, np.ndarray, List[float]]
        model_name=models[0],                       # model_name: str = "VGG-Face"
        detector_backend = backends[0],             # detector_backend: str = "opencv"
        distance_metric=metrics[0],                 # distance_metric: str = "cosine"
        enforce_detection=False,                    # enforce_detection: bool = True
        align=True,                                 # align: bool = True
        expand_percentage= 0,                       # expand_percentage: int = 0
        normalization="base",                       # normalization: str = "base"
        silent=False,                               # silent: bool = False
    )

★ 顔認証(Facial Verification)動作結果

動作結果は次のようになります。

【結果】
・ result (dict): 以下のキーを持つ検証結果を含む辞書。
    - 'verified' (bool): 画像が同一人物かの判定結果
        同一(True)または別の人(False)。

    - 'distance' (float): 面ベクトル間の距離の尺度。
    距離が短いほど、類似度が高いことを示します。

    - 'max_threshold_to_verify' (float): 検証に使用される最大しきい値。
    距離がこの閾値を下回る場合、画像は一致と見なされます。

    - 'model' (str): 選択された顔認識モデル。

    - 'distance_metric' (str): 距離を測定するために選択された類似度指標。

    - 'facial_areas' (dict): 両方の画像の顔の矩形の関心領域。

    - 'img1':{'x':int、'y':int、'w':int、'h':int} 最初のイメージの関心領域。

    - 'img2':{'x':int、'y':int、'w':int、'h':int} 2番目の画像の関心領域。

    - 'time' (浮動小数点数): 検証プロセスにかかった時間(秒単位)。


キー「'verified': True」結果で、「True」=同一人物であることが確認されました。

# [result]
# (py39) d:\VisualStudio2017\Python3.5_GPU\Sample_TEST\顔認識2024>python DF_FaceVerification_test01A.py
#
# verification :  {
#     'verified': True,
#     'distance': 0.6333374542244692,
#     'threshold': 0.68,
#     'model': 'VGG-Face',
#     'detector_backend': 'opencv',
#     'similarity_metric': 'cosine',
#     'facial_areas': {
#         'img1': {'x': 102, 'y': 75, 'w': 276, 'h': 276, 'left_eye': (86, 100) , 'right_eye': (187, 101)},
#         'img2': {'x': 151, 'y': 118, 'w': 447, 'h': 447, 'left_eye': (147, 180), 'right_eye': (294, 173)}
#     },
#     'time': 4.06
# }

★ 顔認証(Facial Verification)動作結果可視化

細かい話ですが、「Facial Verification」の直訳は「顔認証」、「顔認証」は一般的には「Face Recognition」、前述までは所謂「顔照合」=「Face Matching」とか「顔比較」=「Face Comparison」のように思えるのですが、顔認証(Facial Verification)としているのは、DeepFaceは根底として3Dモデリング前処理とする顔認証を行っているため、どのようなケースでも諸段階で認証が行われていることを示します。

このグダグダ屁理屈は、照合結果が「True」であったことのみだけみると何の意味もありません。今回「顔認証」を証明するため、可視化して分かり易く表現してみます。



【顔比較結果の可視化】
最初に比較対象を可視化してみます。
抽出結果キー「'facial_areas'」内にあるキー「'img1'」とキー「'img2'」が比較対象です。 キー「'img1'」をみると、「{'x': 102, 'y': 75, 'w': 276, 'h': 276, 'left_eye': (86, 100) , 'right_eye': (187, 101)},」とあり内訳は{座標、サイズ、左目、右目}で、前半が顔の位置、後半が目の位置を示します。
そこで、この情報からオリジナル画像内所定位置に□と〇を記載するサンプルプログラムを作成しました。 ちなみに、両イメージ中のキー 'left_eye' 、 'right_eye'は眼の位置を示す顔座標系は、顔が示すローカル座標系を示します。

【DF_FaceVerification_test02A.py】
#coding: utf-8
# ////////////////////////////////////////////////////////////////////////////
# ///【DeepFace・顔認証(Facial Verification)】
# ////////////////////////////////////////////////////////////////////////////
if "__file__" in globals():
    import os, sys
    sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
    sys.path.append(os.path.join(os.path.dirname(__file__), "..") + "//..//")
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
from DeZero.common.nlp_util import *
import cv2
import numpy as np
from deepface import DeepFace
tensorflow_warning_cancel()


if __name__ == "__main__":
    img1_path = "c:\\Photo\\aragaki.jpg"
    img2_path = "c:\\Photo\\aragaki-2.jpg"

    # /// 顔認識モデル(models)
    # ////////////////////////////////////////////////////////////////////////////
    models = [
      "VGG-Face",
      "Facenet",
      "Facenet512",
      "OpenFace",
      "DeepFace",
      "DeepID",
      "ArcFace",
      "Dlib",
      "SFace",
    ]

    # /// バックエンド(backends)
    # ////////////////////////////////////////////////////////////////////////////
    backends = [
      'opencv',
      'ssd',
      'dlib',
      'mtcnn',
      'retinaface',
      'mediapipe',
      'yolov8',
      'yunet',
      'fastmtcnn',
    ]

    # /// 類似度( metrics)
    # ////////////////////////////////////////////////////////////////////////////
    metrics = ["cosine", "euclidean", "euclidean_l2"]

    # /// 顔比較(face verification)
    # ////////////////////////////////////////////////////////////////////////////
    verification = DeepFace.verify(
        img1_path=img1_path,                        # img1_path: Union[str, np.ndarray, List[float]]
        img2_path=img2_path,                        # img2_path: Union[str, np.ndarray, List[float]]
        model_name=models[0],                       # model_name: str = "VGG-Face"
        detector_backend = backends[0],             # detector_backend: str = "opencv"
        distance_metric=metrics[0],                 # distance_metric: str = "cosine"
        enforce_detection=False,                    # enforce_detection: bool = True
        align=True,                                 # align: bool = True
        expand_percentage= 0,                       # expand_percentage: int = 0
        normalization="base",                       # normalization: str = "base"
        silent=False,                               # silent: bool = False
    )

    # /// 比較結果の抽出
    # ////////////////////////////////////////////////////////////////////////////
    faceArea_1 = verification["facial_areas"]["img1"]
    faceArea_2 = verification["facial_areas"]["img2"]

    print("faceArea_1        : " , faceArea_1)
    print("faceArea_2        : " , faceArea_2)

    # /// 認識ラインサイズ宣言
    # ////////////////////////////////////////////////////////////////////////////
    line_thickness	= 3
    line_color		= (255, 0, 0)
    line_type		= cv2.LINE_AA
    circle_size		= 20
    common_figsize	= (300, 300)

    # /// 画像読み込み
    # ////////////////////////////////////////////////////////////////////////////
    frame_1 = cv2.imread(img1_path)
    frame_2 = cv2.imread(img2_path)

    # /// 眼の認識・可視化
    # ////////////////////////////////////////////////////////////////////////////
    eyeArea_L1 = (faceArea_1["left_eye"][0]+faceArea_1["x"] , faceArea_1["left_eye"][1]+faceArea_1["y"])
    eyeArea_R1 = (faceArea_1["right_eye"][0]+faceArea_1["x"] , faceArea_1["right_eye"][1]+faceArea_1["y"])
    cv2.circle(frame_1, eyeArea_L1, circle_size, line_color, thickness=-1)
    cv2.circle(frame_1, eyeArea_R1, circle_size, line_color, thickness=-1)

    eyeArea_L2 = (faceArea_2["left_eye"][0]+faceArea_2["x"] , faceArea_2["left_eye"][1]+faceArea_2["y"])
    eyeArea_R2 = (faceArea_2["right_eye"][0]+faceArea_2["x"] , faceArea_2["right_eye"][1]+faceArea_2["y"])
    cv2.circle(frame_2, eyeArea_L2, circle_size, line_color, thickness=-1)
    cv2.circle(frame_2, eyeArea_R2, circle_size, line_color, thickness=-1)

    # /// 顔の認識・可視化
    # ////////////////////////////////////////////////////////////////////////////
    cv2.rectangle(frame_1, (faceArea_1["x"], faceArea_1["y"]), (faceArea_1["x"]+faceArea_1["w"], faceArea_1["y"]+faceArea_1["h"]), line_color, line_thickness, line_type)
    cv2.rectangle(frame_2, (faceArea_2["x"], faceArea_2["y"]), (faceArea_2["x"]+faceArea_2["w"], faceArea_2["y"]+faceArea_2["h"]), line_color, line_thickness, line_type)

    # /// 表示用リサイズ
    # ////////////////////////////////////////////////////////////////////////////
    result_1 = cv2.resize(frame_1, common_figsize)
    result_2 = cv2.resize(frame_2, common_figsize)
    mergeImg = np.hstack((result_1, result_2))
    cv2.imshow("deepface  verification", mergeImg)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

★ 可視化結果

結果を見てみましょう。

2つの結果を並べて表示すると、各々の顔と目の部分が抽出されていることが分かります。 画像中で目の部分の大きさが異なります。



この原因は、両画像サイズが異なるためで、同じサイズの円を描いた後、描画する際リサイズしたことによって表示サイズが変化したためです。




# [result]
# (py39) d:\VisualStudio2017\Python3.5_GPU\Sample_TEST\顔認識2024>python DF_FaceVerification_test02.py
# WARNING:tensorflow:From C:\Users\yamin\anaconda3\envs\py39\lib\site-packages\keras\src\losses.py:2976: The name tf.losses.sparse_softmax_cross_entropy is deprecated. Please use tf.compat.v1.losses.sparse_softmax_cross_entropy instead.
#
# faceArea_1        :  {'x': 102, 'y': 75, 'w': 276, 'h': 276, 'left_eye': (86, 100), 'right_eye': (187, 101)}
# faceArea_2        :  {'x': 151, 'y': 118, 'w': 447, 'h': 447, 'left_eye': (147, 180), 'right_eye': (294, 173)}


★ まとめ

前回の「感情分析」、今回の「顔比較」の根底にあるのは、少なくともディープラーニングモデルによって顔が正確に抽出できたということ。そして抽出部分の顔領域情報と眼情報は、出力情報として提供されるということです。 つまり、DeepFaceは、実は複数の学習済み畳み込みディープラーニングモデルをラップした顔に関する万能ライブラリで、かなりの精度があるということです。

以降も様々なモジュールを試験していきますが、事前調査によって分かったことは、本サイトが最初に使用したpython仮想環境py36当時のDeepFaceモジュール内のファイル構成と、今回py39でインストールした新しいDeepFaceとでは、全く異なったファイル構成になっていました。 このため、py36でインストールされたdeepface バージョン0.0.75と、今回の使用している 0.0.86ではかなりの個所が動かなくなるはずです。 このため、DeepFaceのネットリファレンス等のサンプルプログラムも、かなり使用不能になっていますので、ご注意ください。


≪清須電脳倶楽部メインページへ戻る場合はここをクリックしてください≫
Copyright(c)2018 GGE Kiyosu Cyber Club Allrights Reserved
inserted by FC2 system