PythonとOpenCVを使用して写真の顔を認識する



この記事では、顔認識アルゴリズムについて詳しく説明すると同時に、非常に興味深く有用なOpenCVライブラリーを紹介します。 この資料は、この分野の初心者に役立つと確信しています。



必要なもの:

•NumPyおよびPILライブラリを含むPython 2.7をインストールしました

•OpenCV 2ndバージョン



以下は 、必要なすべてのコンポーネントをインストールするための資料へのリンクです。 必要なものをすべてインストールするのは難しくありません。



まず、写真で顔を認識する方法を理解しましょう。 まず、人の顔が写真のどこにあるかを見つけ、壁の時計や窓辺のサボテンと混同しないようにする必要があります。 人にとって単純なタスクは、コンピュータにとってそれほど単純ではないように思われます。 顔を見つけるには、鼻、額、目、唇などの主要なコンポーネントを強調表示する必要があります。 これを行うには、次のようなテンプレート(Haarプリミティブ)を使用します。







パターンが画像内の特定の領域に対応する場合、画像には人間の顔があると想定されます。 実際、このようなテンプレートはさらに多くあります。 それぞれについて、白と黒の領域の明るさの違いが考慮されます。 この値は標準と比較され、ここに人間の顔の一部があるかどうかが決定されます。

このメソッドは、Viola-Jonesメソッド(Haarカスケードとも呼ばれます)と呼ばれます。 写真に大きな顔が1つではなく、小さな顔がたくさんあると想像してみましょう。 テンプレートを画像全体に適用すると、そこに顔が見つかりません。 それらは小さなテンプレートになります。 さまざまなサイズの写真のすべての顔を検索するために、スライディングウィンドウ方式が使用されます。 プリミティブが計算されるのはこのウィンドウ内です。 ウィンドウは画像全体をスライドします。 画像が通過するたびに、ウィンドウが拡大され、大きな顔が検出されます。



このビデオでアルゴリズムのデモを見ることができます:





それで、写真で顔を見つけましたが、この顔がまさに私たちが探しているものであると判断する方法は? この問題を解決するために、ローカルバイナリパターンアルゴリズムを使用します。 その本質は、画像を部分に分割し、各部分で各ピクセルを隣接する8ピクセルと比較するという事実にあります。 中央のピクセルの値が隣のピクセルよりも大きい場合、0を書き込みます。それ以外の場合は1を書き込みます。したがって、各ピクセルに対して特定の数を取得します。 さらに、これらの数値に基づいて、写真を分割するすべての部分について、ヒストグラムが考慮されます。 すべての部分のすべてのヒストグラムは、画像全体を特徴付ける1つのベクトルに結合されます。 2つの面がどれだけ似ているかを知りたい場合は、それぞれの面についてこのようなベクトルを計算し、それらを比較する必要があります。 以下の図は、アルゴリズムの本質をよりよく理解するのに役立ちます。









さて、最後にいくつかのコードを書きましょう。 基礎として、この記事のコードを取り上げました。



#    import cv2, os import numpy as np from PIL import Image #       cascadePath = "haarcascade_frontalface_default.xml" faceCascade = cv2.CascadeClassifier(cascadePath) #       recognizer = cv2.createLBPHFaceRecognizer(1,8,8,8,123)
      
      





cascadePathパラメーターには、顔認識用の既製の値を持つファイル名が含まれています。 このファイルは、OpenCV(opencv \ build \ etc \ haarcascades \)を使用してディレクトリから取得できます。

次に、CascadeClassifierオブジェクトとLBPHFaceRecognizer顔認識オブジェクトを作成します。 後者について、より詳細に、より正確に、そのパラメーターについて説明しましょう。 最初の2つの値1と8は、ピクセルの近傍を特徴付けます。 これがこの写真で実証できることは明らかです。





つまり、最初の数値はピクセルを選択する半径であり、2番目の数値はこれらのピクセルの数です。 取得するポイントの近くのピクセルが多いほど、認識はより正確になります。

次のパラメーター(8.8)は、元の画像を顔で分割する領域のサイズを特徴付けます。 小さいほど、そのような領域が多くなり、認識が向上します。

最後に、最後の値は、顔認識のしきい値を定義する信頼しきい値パラメーターです。 信頼性が低いほど、アルゴリズムは写真が彼に知られている人物を示していると確信します。 しきい値は、自信がほとんどないときに、アルゴリズムがこの人物を不慣れだと見なすことを意味します。 この場合、しきい値は123です。



どうぞ すべての写真から特定の方法で人々の顔を見つけて保存する関数を作成します。



 def get_images(path): #        image_paths image_paths = [os.path.join(path, f) for f in os.listdir(path) if not f.endswith('.happy')] images = [] labels = [] for image_path in image_paths: #    -        gray = Image.open(image_path).convert('L') image = np.array(gray, 'uint8') #       ,    subject_number = int(os.path.split(image_path)[1].split(".")[0].replace("subject", "")) #      faces = faceCascade.detectMultiScale(image, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) #        images,       labels for (x, y, w, h) in faces: images.append(image[y: y + h, x: x + w]) labels.append(subject_number) #     cv2.imshow("", image[y: y + h, x: x + w]) cv2.waitKey(50) return images, labels
      
      





たとえば、 Yale Facesという顔データベースを使用しました。 その中には、写真ごとに異なる表情を持つ15人の人物がいます。





このデータベース内の各ファイルの名前は、subject01.sadです。 最初に件名という単語、次に人物のシリアル番号、そして写真の特徴が続きます。 たとえば、特徴的な悲しいとは、悲しい顔、幸せな陽気などを意味します。

get_images関数は、.happyで終わるものを除くすべての写真を読み取り、顔が位置する領域を選択します。 認識のための次のステップでは、陽気な表情の写真を使用します。これは、対照サンプル、つまり 認識の品質を確認する写真。

また、写真内の人物の番号が各ファイル名から抽出され、ラベルリストが保存されます。 その結果、各番号にはこの番号が割り当てられます。

faceCascade.detectMultiScale()関数は、人間がいる写真の領域を定義します

顔。 検出された各顔のパラメーター[x、y、w、h]を含むリストを返します。 これら

パラメータは、顔が見つかった場所の長方形の領域を表します。



次に、関数のパラメーターを見てみましょう。

画像 -ソース画像

scaleFactor-各反復でスライド検索ボックスがどれだけ増加するかを決定します。 1.1は10%、1.05 5%などを意味します。 この値が大きいほど、アルゴリズムの実行が速くなります。

minNeighbors-この値が高いほど、検索がより偏執的になり、これが実際の顔をスキップする頻度が高くなります。これは誤検知であると考えられます。 最適値は3〜6です。

minSize-写真の最小顔サイズ。 通常、30〜30で十分です。



さて、これで面とそれに対応するラベルのセットを作成できます。 これらの顔を認識するプログラムを教えましょう。

 #    path = './yalefaces' #       images, labels = get_images(path) cv2.destroyAllWindows() #     recognizer.train(images, np.array(labels))
      
      







写真へのパスを示し、写真とタグのリストを取得します。 次に、LBPアルゴリズムを使用してトレーニング関数を起動します。 それには超自然的なものは何もありません。get_images()関数を実行した後に取得した値を渡すだけです。 プログラムが残りの処理を行います。

そして、私たちには訓練された「認識者」がおり、幸せそうな顔のセットがあります。 次に、これらの幸せな顔を認識するようにアルゴリズムに依頼する必要があります。

 #      image_paths = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.happy')] for image_path in image_paths: #     gray = Image.open(image_path).convert('L') image = np.array(gray, 'uint8') faces = faceCascade.detectMultiScale(image, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) for (x, y, w, h) in faces: #   ,    #  recognizer.predict         confidence, #      ,     ,   ,    number_predicted, conf = recognizer.predict(image[y: y + h, x: x + w]) #          ,    number_actual = int(os.path.split(image_path)[1].split(".")[0].replace("subject", "")) if number_actual == number_predicted: print "{} is Correctly Recognized with confidence {}".format(number_actual, conf) else: print "{} is Incorrect Recognized as {}".format(number_actual, number_predicted) cv2.imshow("Recognizing Face", image[y: y + h, x: x + w]) cv2.waitKey(1000)
      
      





ループでは、末尾が.happyである各写真の顔の位置を再度決定します。 すべてのパラメーターと手順は、前のステップと同じです。

検出された各顔について、recognizer.predict()関数を実行します。この関数は、写真にあると思われる被写体の識別番号と信頼性パラメーターを返します。 次に、関数から返された値を対象の実数と比較します。これらが等しい場合、認識は成功しました。

それだけです。さらにコンソールに、コントロールサンプルの各写真の認識結果が表示されます。





プログラムのソースコードはこちらにあります



All Articles