顔認識の最初のステップは、各顔の特徴を簡潔かつ差別化された方法で正確に反映できるモデルを見つけることです。顔を認識する場合、まず上記と同じ方法で現在の顔の特徴を抽出し、次に既存の特徴セットから現在の特徴の最近傍サンプルを見つけて、現在の顔のラベルを取得します。
OpenCVでは、LBPH方式、EigenFishfaces方式、Fisherfaces方式という3つの顔認識方式を提供しています。ここでは主にLBPH法について簡単に紹介します。
LBPH (ローカル バイナリ パターン ヒストグラム、ローカル バイナリ パターン ヒストグラム) で使用されるモデルは、LBP (ローカル
バイナリ パターン、ローカル バイナリ パターン) アルゴリズムに基づいています。LBP は
効果的なテクスチャ記述演算子として最初に提案され、画像の局所的なテクスチャ特徴を表現する際に優れた効果を発揮するため広く使用されています。
基本的
LBP アルゴリズムの基本原理は、ピクセル A の値をその 8 つの最近傍の値と 1 つずつ比較することです。
- A のピクセル値がその近傍のピクセル値より大きい場合、0 が返されます。
- A のピクセル値がその近傍のピクセル値より小さい場合は 1 を取得します。
最後に、ピクセル A とその周囲の 8 ピクセル点を比較して得られた 0 と 1 の値を接続して 8 ビットのバイナリ シーケンスを取得し、そのバイナリ シーケンスを点 A の LBP 値として 10 進数に変換します。
以下では、図 23-6 の左側の 3×3 領域の中心点 (ピクセル値 76 の点) を例として、この点の LBP 値の計算方法を説明します。計算時はその画素値76を閾値として、その周囲8画素を二値化処理し、
- 値が 76 より大きいピクセルを 1 として処理します。たとえば、近傍のピクセル値が 128、251、99、213 である点はすべて 1 として扱われ、対応するピクセル位置が埋められます。
- ピクセル値が 76 未満のピクセルを 0 として処理します。たとえば、近傍のピクセル値が 36、9、11、および 48 の点はすべて 0 として扱われ、対応するピクセル位置に埋め込まれます。
上記の計算により、図 23-6 右図に示す 2 値の結果が得られます。
2値化完了後、開始位置を任意に指定し、得られた2値化結果をシリアル化して8ビットの2進数を形成します。
たとえば、現在のピクセル点の真上から開始して、時計回りの順序でバイナリ シーケンス「01011001」が取得されます。最後に、図 23-7 に示すように、バイナリ シーケンス「01011001」を、現在の中心点のピクセル値として対応する 10 進数「89」に変換します。
上記の方法で画像をピクセルごとに処理して LBP 特徴画像を取得します。この特徴画像のヒストグラムは LBPH (LBP ヒストグラム) と呼ばれます。
さまざまなスケールでテクスチャ構造を取得するために、円形近傍を使用して計算を任意のサイズの近傍に拡張することもできます。円形近傍は (P, R) で表すことができます。ここで、P は円形近傍の操作に参加するピクセルの数を表し、R は近傍の半径を表します。
たとえば、図 23-8 では、異なる円形近傍が使用されています。
-
左側では (4, 1) 近傍が使用され、現在のピクセルのピクセル値と近傍の 4 つのピクセルが比較され、使用される半径は 1 です。
-
右側では (8, 2) 近傍が使用され、現在のピクセルのピクセル値と近傍内の 8 つのピクセル ポイントが比較され、使用される半径は 2 です。比較に参加する 8 つの近傍ピクセルのうち、一部の近傍は実際に存在する特定の位置のピクセルを直接取得せず、計算によって「仮想」ピクセル値を構築し、現在のピクセルと比較します。
光の影響により、顔全体のグレー スケールは変化することがよくありますが、顔の各部分間の相対的なグレー スケールは基本的に同じままです。LBP の主なアイデアは、現在の点とその隣接ピクセルの間の相対関係を処理結果として取得することです。このため、LBP アルゴリズムから抽出された特徴は、画像全体のグレー レベルが変化しても変化しないままにすることができます (単調な変化)。
したがって、LBP は顔認識に広く使用されています。
上記の紹介からわかるように、LBP 特徴は Haar 特徴に非常に似ており、どちらも画像のグレースケール変更特徴です。
機能紹介
OpenCV では、函数 cv2.face.LBPHFaceRecognizer_create()
LBPH 認識インスタンス モデルを生成し、それを適用しcv2.face_FaceRecognizer.train() 函数完成训练
、最後にcv2.face_FaceRecognizer.predict()
関数を使用して顔認識を完了できます。
上記 3 つの機能について以下に説明します。
- 関数 cv2.face.LBPHFaceRecognizer_create()
関数 cv2.face.LBPHFaceRecognizer_create() の構文形式は次のとおりです。
retval = cv2.face.LBPHFaceRecognizer_create( [, radius[, neighbors[,
Grid_x[, Grid_y[, Threshold]]]]])
すべてのパラメータはオプションであり、次の意味があります。
- radius: 半径値、デフォルト値は 1 です。
- 隣接ポイント: 隣接ポイントの数。デフォルトでは 8 隣接ポイントが使用され、必要に応じてさらに多くの隣接ポイントを計算できます。
- Grid_x: LBP 特徴画像をセルに分割したときの、各セルの水平方向のピクセル数。
このパラメータのデフォルト値は 8 です。つまり、LBP 特徴画像は行方向に 8 ピクセル単位でグループ化されます。 - Grid_y: LBP 特徴画像をセルに分割したときの、各セルの垂直方向のピクセル数。
このパラメータのデフォルト値は 8 です。つまり、LBP 特徴画像は列方向に 8 ピクセル単位でグループ化されます。 - しきい値: 予測時に使用されるしきい値。このしきい値より大きい場合は、ターゲット オブジェクトが識別されていないと見なされます。
- 関数 cv2.face_FaceRecognizer.train()
関数 cv2.face_FaceRecognizer.train() は、各参照画像の LBPH を計算し、ベクトルを取得します。各面は
ベクトル セット全体の点です。この関数の構文は次のとおりです。
なし = cv2.face_FaceRecognizer.train( src, ラベル )
式内の各パラメータの意味は次のとおりです。
- src: 学習画像、学習に使用される顔画像。
- ラベル: ラベル、顔画像に対応するラベル。
この関数には戻り値がありません。
- 関数 cv2.face_FaceRecognizer.predict()
関数 cv2.face_FaceRecognizer.predict() は、テスト対象の顔画像を判定し、現在の画像に最も近い顔画像を見つけます。どちらの顔画像が最も近いかに関係なく、テスト対象の現在の画像が対応するラベルとしてマークされます。もちろん、テスト対象の画像とすべての顔画像の間の距離が、関数
cv2.face.LBPHFaceRecognizer_create() のパラメーターしきい値で指定された距離値よりも大きい場合は、対応する結果が見つからないとみなされます。 、現在の顔を認識できません。
関数 cv2.face_FaceRecognizer.predict() の構文は次のとおりです。
ラベル、信頼度 = cv2.face_FaceRecognizer.predict( src )
式中のパラメータと戻り値の意味は次のとおりです。
- src: 認識する顔画像。
- label: 返された認識結果のラベル。
- 信頼性: 返された信頼性スコア。信頼スコアは、認識結果と元のモデルの間の距離を測定するために使用されます。
0 は完全一致を意味します。一般に、50 未満の値は許容されるとみなされ、80 を超える値は有意な差とみなされます。
例: 簡単な顔認識プログラムを完成させる
import cv2
import numpy as np
images=[]
images.append(cv2.imread("face\\face2.png",cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread("face\\face3.png",cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread("face\\face4.png",cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread("face\\face5.png",cv2.IMREAD_GRAYSCALE))
labels=[0,0,1,1]
#print(labels)
recognizer = cv2.face.LBPHFaceRecognizer.create()
recognizer.train(images, np.array(labels))
predict_image=cv2.imread("face\\face4.png",cv2.IMREAD_GRAYSCALE)
label,confidence= recognizer.predict(predict_image)
print("label=",label)
print("confidence=",confidence)
その中の写真は私がインターネットからランダムにダウンロードした有名人の写真です。全体的な認識度は高くなく、認識できなかった場合はそのまま0を返してしまう。この問題も根深いところで発生する。判定ロジックの調整が必要です。
返される結果:
label= 1
confidence= 0.0
まずそれに慣れてから、いくつかの顔認識アルゴリズムの違いと、より適切なアプリケーション シナリオを比較することに集中してください。