OpenCV ツールキットを使用して、従来のビジョンやディープラーニング手法 (完全なコード、吐血など) を含む顔検出と顔認識を正常に実装します。

OpenCVは顔検出を実装します

顔認識機能を実現するには、まず顔検出を実行し、写真内の顔の位置を判断してから次のステップを実行する必要があります。

参考リンク:
1. OpenCV顔検出
2. 【OpenCV-Python】 32. OpenCV顔検出と認識 - 顔検出
3. 【youcans画像処理学習講座】 23. 顔検出:Haarカスケード検出 4. OpenCV実戦 5:LBPカスケード分類器で顔検出を実現5.コンピュータビジョン
OpenCv学習シリーズ:第10回 リアルタイム顔検出

OpenCVの顔検出方法

OpenCVでは顔検出に主にHaar特徴とLBP特徴という2つの特徴(つまり2つの方式)が使用されます。最もよく使用されているのは Haar 特徴による顔検出ですが、OpenCV には深層学習手法も統合されており、顔検出を実現しています。

Haar 特徴に基づく顔検出

Haar カスケード検出器の事前トレーニング モデルのダウンロード

OpenCV では、顔検出のために XML 形式でトレーニングされた分類子を使用します。OpenCV インストール ディレクトリのソース フォルダー内のデータ フォルダー、または github で opencv ソース コードをダウンロードすると、ソース コードのデータ フォルダーにモデル ファイルがあります: https://github.com/opencv/opencv /
tree /4.x/データ

haarcascade_eye.xml、目
haarcascade_eye_tree_eyeglasses.xml、メガネをかけた目
haarcascade_frontalcatface.xml、猫の正面 haarcascade_frontalcatface_extended.xml、猫の正面
haarcascade_frontalface_alt.xml、正面の顔
haarcascade_frontalface_alt2.xml
、正面の顔
haar cascade_frontalface_alt_tree.xml、正面の顔 haar
arcascade_frontalface_default.xml、フロント顔
haarcascade_fullbody.xml、人体
haarcascade_lefteye_2splits.xml、左目
haarcascade_license_plate_rus_16stages.xml、
haarcascade_ lowerbody.xml 、
haarcascade_profileface.xml、haarcascade_righteye_2splits.xml 、
右目
haarcascade_russ ian_plate_number.xml、
haarcascade_smile.xml 、スマイリーフェイス
haarcascade_upperbody.xml、上半身

Haar カスケード分類器

Haar 特徴に基づくカスケード分類器は、Paul Viola が論文「Boosted Cascade of Simple features を使用した高速オブジェクト検出」で提案したオブジェクト検出方法です。

Haar カスケード分類器は、AdaBoost アルゴリズムを使用して、ノードの各レベルで高い検出率と低い拒否率を持つ多層分類器を学習します。その特徴は次のとおりです。

  • Haar のような入力特徴を使用して、長方形の画像領域の合計または差をしきい値に設定します。
  • 積分イメージを使用して 45 度回転した領域のピクセル合計を計算し、Haar 類似の入力特徴の計算を高速化します。
  • 統計的ブースティングを使用して、バイナリ (顔/非顔) 分類子ノード (高い合格率、低い拒否率) を作成します。
  • 弱分類器は並列に結合されて、スクリーニング カスケード分類器を形成します。
    Haar カスケード分類器

すべてのレベルのブースト分類器は、人間の顔の検出ウィンドウを通過させると同時に、顔以外の検出ウィンドウのごく一部を拒否し、検出ウィンドウを次の分類器に渡すことができます。類推すると、最後の分類子は顔以外の検出ウィンドウをほぼすべて拒否し、人間の顔検出ウィンドウのみを残します。したがって、検出ウィンドウ領域がすべてのレベルのブースティング分類器を通過する限り、検出ウィンドウ内に人間の顔が存在すると考えられます。

実際のアプリケーションでは、入力画像のサイズが大きく、複数領域および複数スケールの検出が必要です。マルチ領域は画像の異なる位置を横断することであり、マルチスケールは画像内の異なるサイズの顔を検出することです。
Haar カスケード分類顔検出器では、主に顔の構造的特徴が使用されます。
1) 頬と比較して、目の色が暗い
2) 目と比較して、鼻筋の領域が明るい
3) 目、口、鼻の位置は比較的固定されており、
この 5 つの長方形領域の明暗関係により、顔の各部位の識別特徴が形成されます。たとえば、以下の画像では、最初の特徴は目と上頬の間の強度の差を検出し、2 番目の特徴は目の間の距離を検出します。
ここに画像の説明を挿入
Haar顔検出は正面顔の認識率は高いが、横顔の検出性能は低い。

OpenCV-Pythonの実装

Haar カスケード検出器を使用して写真内の顔を検出する手順:

(1) CascadeClassifier カスケード分類子オブジェクトを作成し、.xml ファイルからカスケード分類子モデルをロードします。
(2) 検出したい画像を読み込みます。
(3) detectMultiScale() メソッドを使用して画像を検出し、検出された顔または目の外接する四角形を返します。
(4) 検出した外接四角形を検出画面上に描画します。
カスケード分類子クラス cv::CascadeClassifier は OpenCV で定義されています。Python 言語では、インターフェイス関数 cv2.CascadeClassifier() を使用してファイルから分類子を作成します。メンバー関数 cv.CascadeClassifier.detectMultiScale() は、画像上でターゲット検出を実行するために使用されます。

import cv2
cv2.CascadeClassifier.detectMultiScale(image[, scaleFactor=1.1, minNeighbors=3, flags=0, minSize=Size(), maxSize=Size()]) → objects

パラメータの説明:

  • filename: ロードされた分類子モデルのファイル パスと名前、文字列。ロードされたカスケード分類子モデル ファイル (拡張子 .xml)。
  • image: 検出される入力画像 (CV_8U 形式)。
  • scaleFactor: 検索ウィンドウの倍率。デフォルト値は 1.1 です。
  • minNeighbors: 検出対象を構成する隣接する四角形の最小数を示し、デフォルト値は 3 です。
  • flags: バージョン互換性フラグ。デフォルト値は 0 です。
  • minSize: 検出対象のタプル(h,w)の最小サイズ。
  • maxSize: 検出対象のタプル(h,w)の最大サイズ。

戻り値

  • オブジェクト: 戻り値、検出されたターゲットの長方形の境界ボックスは、(N,4) のような形状の Numpy 配列です。各行には 4 つの要素 (x、y、幅、高さ) があり、長方形のボックスの左上の頂点座標 (x、y) と幅と高さを表します。

Haar カスケード検出器を使用して画像内の顔を検出します。

import numpy as np
import cv2 as cv

if __name__ == '__main__':
    # (6) 使用 Haar 级联分类器 预训练模型 检测人脸
    # 读取待检测的图片
    img = cv.imread("../data/single.jpg")
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "../data/haarcascade_frontalface_alt2.xml"
    face_detector = cv.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=1,
                                           minSize=(30, 30), maxSize=(300, 300))
    print(faces.shape)  # (17, 4)
    print(faces[0])  # (x, y, width, height)

    # 绘制人脸检测框
    for x, y, width, height in faces:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
    # 显示图片
    cv.imshow("faces", img)
    cv.waitKey(0)
    cv.destroyAllWindows()

単一の顔の検出
Haar カスケード検出器を使用して、画像内の人間の目を検出します。
人間の目の検出方法は、haarcascade_eye.xml などの事前トレーニング済みモデルが使用されることを除いて、顔検出の方法と同じです。
目は顔の大きさより小さいため、検出関数 detectMultiScale() のパラメータ minSize=(20, 20) が小さくなります。
さらに、scaleFactor と minNeighbors も、検出される人間の目の数に影響します。

import cv2 as cv

if __name__ == '__main__':
    # (7) 使用 Haar 级联分类器 预训练模型 检测人眼
    # 读取待检测的图片
    img = cv.imread("./data/single.jpg")
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "./data/haarcascade_eye.xml"
    eye_detector = cv.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    eyes = eye_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=10,
                                           minSize=(10, 10), maxSize=(80, 80))
    # 绘制人脸检测框
    for x, y, width, height in eyes:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
    # 显示图片
    cv.imshow("Haar_Cascade", img)
    # cv.imwrite("../images/imgSave3.png", img)
    cv.waitKey(0)
    cv.destroyAllWindows()

単一の顔と目の検出
スケールファクター = 1.1、最小ネイバー = 10
単一の顔と目の検出
スケールファクター = 1.1、最小ネイバー = 5

Haarカスケード検出器を使用した顔と目の同時検出
検出効率を向上させるために、最初に人間の顔を検出し、次に人間のウィンドウで人間の目を検出することができます。これにより、検出効率が向上するだけでなく、検出精度も向上します。

import cv2 as cv

if __name__ == '__main__':
    # (8) 使用 Haar 级联分类器 预训练模型 检测人脸和人眼
    # 读取待检测的图片
    img = cv.imread("./data/multiface1.jpeg")
    print(img.shape)

    # 加载 Haar 级联分类器 预训练模型
    face_path = "./data/haarcascade_frontalface_alt2.xml"  # 人脸检测器
    face_detector = cv.CascadeClassifier(face_path)  # <class 'cv2.CascadeClassifier'>
    eye_path = "./data/haarcascade_eye.xml"  # 人眼检测器
    eye_detector = cv.CascadeClassifier(eye_path)  # <class 'cv2.CascadeClassifier'>
    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5,
                                           minSize=(30, 30), maxSize=(300, 300))
    print(faces.shape)  # (15, 4)

    # 绘制人脸检测框
    for x, y, width, height in faces:
        cv.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2, cv.LINE_8, 0)
        # 在人脸区域内检测人眼
        roi = img[y:y + height, x:x + width]  # 提取人脸
        # 检测人眼
        eyes = eye_detector.detectMultiScale(roi, scaleFactor=1.1, minNeighbors=1,
                                             minSize=(2, 2), maxSize=(80, 80))
        # 绘制人眼
        for ex, ey, ew, eh in eyes:
            cv.rectangle(img, (x+ex, y+ey), (x+ex+ew, y+ey+eh), (255, 0, 0), 2)

    # 显示图片
    cv.imshow("Haar_Cascade", img)
    # cv.imwrite("../images/imgSave4.png", img)
    cv.waitKey(0)
    cv.destroyAllWindows()


比較的正常な顔の検出効果はまだ良好であることがわかります (detectMultiScale() メソッドのパラメーターを手動で調整する必要があります)。ただし、横顔、曲がった顔、小さな顔の検出効果は理想的ではありません。瞳の検出 フレームを描画することしかできず、キーポイントの検出は実現できないので、この人間の瞳の検出を使用して顔の位置合わせのキーポイントに変換し、後でその効果を確認することを検討しています。

深層学習に基づく顔検出

OpenCV のディープ ニューラル ネットワーク (DNN) モジュールは、深層学習に基づいた顔検出機能を提供します。DNN モジュールでは、Caffe、TensorFlow、Torch、Darknet などの一般的な深層学習フレームワークが使用されています。
OpenCV は、Caffe モデルと TensorFlow モデルという 2 つの事前トレーニングされた顔検出モデルを提供します。
Caffeモデルは、次の 2 つのファイルをロードする必要があります。

  • deploy.prototxt: モデル構造を定義する構成ファイル
  • res10_300x300_ssd_iter_140000_fp16.caffemodel: 実際のレイヤーの重みを含むトレーニング モデル ファイル

TensorFlowモデルは、次の 2 つのファイルをロードする必要があります。

  • opencv_face_detector_uint8.pb: モデル構造を定義する構成ファイル
  • opencv_face_detector.pbtxt: 実際のレイヤーの重みを含むトレーニング モデル ファイル

モデル設定ファイルは OpenCV ソースコードの「\samples\dnn\face_detector」フォルダーに提供されていますが、モデルトレーニングファイルは提供されていません。このフォルダー内の download_models.py ファイルを実行して、上記の 2 つのトレーニング モデル ファイルをダウンロードできます。または、公式リンク https://github.com/spmallick/learnopencv/find/master から直接ダウンロードします(このリンクはダウンロードするのが難しすぎます)、このリンクからダウンロードします: OpenCV School/OpenCV コース情報 https://gitee.com /opencv_ai /opencv_tutorial_data (重要な瞬間には Gitee に依存します)
(検索ボックスに「年齢」と入力して検索すると見つかりません)  ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

事前トレーニングされたモデルを使用して顔検出を実行するには、主に次の手順が含まれます。
(1) cv2.dnn.readNetFromCaffe() または cv2.dnn.readNetFromTensorflow() 関数を呼び出してモデルをロードし、検出器を作成します。
(2) cv2.dnn.blobFromImage()関数を呼び出して、検出対象の画像を画像ブロックデータに変換します。
(3) 検出器の setInput() メソッドを呼び出し、画像ブロック データをモデルの入力データとして設定します。
(4) 検出器の forward() メソッドを呼び出して計算を実行し、予測結果を取得します。
(5) 規定値以上の信頼度が高い予測結果を検出結果とし、原画像中の顔をマークし、その信頼度を基準として出力する。

単一画像検出

# 基于深度学习的人脸检测(脸-眼_视频)
import cv2
import numpy as np


# dnnnet = cv2.dnn.readNetFromCaffe("deploy.prototxt", "res10_300x300_ssd_iter_140000_fp16.caffemodel")
dnnnet = cv2.dnn.readNetFromTensorflow("./data/opencv_face_detector_uint8.pb", "./data/opencv_face_detector.pbtxt")

img = cv2.imread("./data/multiface1.jpeg")
h, w = img.shape[:2]
blobs = cv2.dnn.blobFromImage(img, 1.0, (300, 300), [104., 117., 123.], False, False)
dnnnet.setInput(blobs)
detections = dnnnet.forward()
faces = 0
for i in range(0, detections.shape[2]):
    confidence = detections[0, 0, i, 2]
    if confidence > 0.6:               
        faces += 1
        box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
        x1,y1,x2,y2 = box.astype("int")
        y = y1 - 10 if y1 - 10 > 10 else y1 + 10
        text = "%.3f"%(confidence * 100)+'%'
        cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 2)
        cv2.putText(img,text, (x1, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
cv2.imshow('faces',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

ここに画像の説明を挿入
対照的に、深層学習モデルの効果はさらに優れています。

ビデオ検出

import cv2
import numpy as np


# win7系统在代码中所有的cv2.VideoCapture要加cv2.CAP_DSHOW,不然会报错
capture = cv2.VideoCapture(0, cv2.CAP_DSHOW) 
frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = capture.get(cv2.CAP_PROP_FPS)

dnnnet = cv2.dnn.readNetFromTensorflow("./data/opencv_face_detector_uint8.pb", "./data/opencv_face_detector.pbtxt")

if capture.isOpened() is False:
    print('CAMERA ERROR !')
    exit(0)

while capture.isOpened():

    ret, frame = capture.read()

    if ret is True:

        # cv2.imshow('FRAME', frame)  # 显示捕获的帧

        h, w = frame.shape[:2]
        blobs = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104., 117., 123.], False, False)
        dnnnet.setInput(blobs)
        detections = dnnnet.forward()
        faces = 0
        for i in range(0, detections.shape[2]):
            confidence = detections[0, 0, i, 2]
            if confidence > 0.6:
                faces += 1
                box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                x1, y1, x2, y2 = box.astype("int")
                y = y1 - 10 if y1 - 10 > 10 else y1 + 10
                text = "%.3f" % (confidence * 100) + '%'
                cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 2)
                cv2.putText(frame, text, (x1, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)

        cv2.imshow('faces', frame)
        k = cv2.waitKey(1)
        if k == ord('q'):
            break
    else:
        break
capture.release()
cv2.destroyAllWindows()


検出のために携帯電話をカメラの前に置くと、一部の顔がまだ検出できないことがわかり、後で生体検出を追加することを検討できます。

従来のビジョン手法とディープラーニング手法の比較

同じビデオ ファイルについて、速度と検出統計の総数を比較します。
ここに画像の説明を挿入

OpenCVは顔認識を実装します

参考リンク:
1. OpenCV の顔認識(メイン コード リファレンス)
2. [OpenCV-Python] 33. OpenCV の顔検出と認識 - 顔認識
自体は、ブロガーのコードに従って、独自のプロジェクトの要件に合わせて適切な変更を加えています。

OpenCV には 3 つの顔認識アルゴリズムがあります。

Eigenfaces (アイゲンフェイス) の顔認識は、顔データセットの主成分を特定し、データセットに対する認識対象の画像領域の乖離度 (0 ~ 20k) を計算する PCA (主成分分析) によって実現されます。 、値が小さいほど差は小さくなり、値 0 は完全一致を意味します。4k ~ 5k 未満はかなり信頼できる認識です。
EigenFaces 顔認識の基本手順は次のとおりです。
(1) cv2.face.EigenFaceRecognizer_create() メソッドを呼び出して、EigenFace レコグナイザーを作成します。
(2) 認識エンジンの train() メソッドを呼び出し、既知の画像を使用してモデルをトレーニングします。
(3) 認識装置のpredict()メソッドを呼び出して、未知の画像を認識に使用し、その同一性を確認します。
cv2.face.EigenFaceRecognizer_create() 関数の基本形式は次のとおりです。

recognizer = cv2.face.EigenFaceRecognizer_create([num_components[, threshold]])

# recognizer为返回的EigenFaces识别器对象
# num_components为分析时的分量数量, 默认为0, 表示根据实际输入决定
# threshold为人脸识别时采用的阈值

EigenFaces レコグナイザーの train() メソッドの基本形式は次のとおりです。

recognizer.train(src, label)

# src为用于训练的已知图像数组, 所有图像必须为灰度图且大小要相同
# label为标签数组, 与已知图像数组中的人脸一一对应, 同一个人的人脸标签应设置为相同值

EigenFaces レコグナイザーの detect() メソッドの基本形式は次のとおりです。

label, confidence = recoginer.predict(testimg)

# label为返回的标签值
# confidence为返回的可信度, 表示未知人脸和模型中已知人脸之间的距离, 0表示完全匹配, 低于5000可认为是可靠的匹配结果
# test_img为未知人脸图像, 图像必须为灰度图且大小要与训练图像相同

FisherFaces の顔認識は PCA から開発され、顔認識を実現するために線形判別分析 (LDA) 手法を使用し、より正確な結果を得るためにより複雑な計算が使用されます。4k~5k以下はかなり信頼できる認識です。
FisherFaces 顔認識の基本手順は次のとおりです。
(1) cv2.face.FisherFaceRecognizer_create() メソッドを呼び出して、FisherFaces レコグナイザを作成します。
(2) 認識エンジンの train() メソッドを呼び出し、既知の画像を使用してモデルをトレーニングします。
(3) 認識装置のpredict()メソッドを呼び出して、未知の画像を認識に使用し、その同一性を確認します。
OpenCV では、cv2.face.EigenFaceRecognizer クラスと cv2.face.FisherFaceRecognizer クラスは、xxx_create()、train に対応する、cv2.face.BasicFaceRecognizer クラス、cv2.face.FaceRecognizer クラス、および cv2.Algorithm クラスのサブクラスに属します。 ()predict()などのメソッドの基本的な形式や使い方は同じです。

ローカル バイナリ パターン ヒストグラム (LBPH) 顔認識では、顔を小さな単位に分割し、それらをモデル内の対応する単位と比較して、各領域の一致値のヒストグラムを生成します。これにより、データセット内の画像の形状やサイズとは異なる顔領域を検出できるようになり、より便利で柔軟になります。50 未満の基準値は良好な認識とみなされ、80 を超える基準値は不良とみなされます。
画像を処理する LBPH アルゴリズムの基本原理は次のとおりです:
(1) ピクセル x の周囲 8 つのピクセルを取得し、それと比較し、ピクセル値がピクセル x より大きい場合は 0 を取得し、そうでない場合は 1 を取得します。8 ピクセルに相当する 0 と 1 を接続して 8 ビットの 2 進数を取得し、それを 10 進数に変換し、ピクセル x の LBP 値として使用します。
(2) ピクセルのすべてのピクセルを同様に処理して画像全体の LBP 値を取得し、画像のヒストグラムが画像の LBPH になります。
LBPH 顔認識の基本的な手順は次のとおりです;
(1) cv2.face.LBPHFaceRecognizer_create() メソッドを呼び出して、LBPH レコグナイザーを作成します。
(2) 認識エンジンの train() メソッドを呼び出し、既知の画像を使用してモデルをトレーニングします。
(3) 認識装置のpredict()メソッドを呼び出して、未知の画像を認識に使用し、その同一性を確認します。

cv2.face.LBPHFaceRecognizer_create() 関数の基本形式は次のとおりです。

recognizer = cv2.face.LBPHFaceRecognizer_create([radius[, neighbors[, grid_x[, grid_y[, threshold]]]]])

# recognizer为返回的LBPH识别器对象
# radius为邻域的半径大小
# neighbors为邻域内像素点的数量, 默认为8
# grid_x为将LBP图像划分为多个单元格时, 水平方向上的单元格数量, 默认为8
# grid_y为将LBP图像划分为多个单元格时, 垂直方向上的单元格数量, 默认为8
# threshold为人脸识别时采用的阈值

LBPH レコグナイザーの train() メソッドの基本形式は次のとおりです。

recognizer.train(src, label)

# src为用于训练的已知图像数组, 所有图像必须为灰度图且大小要相同
# label为标签数组, 与已知图像数组中的人脸一一对应, 同一个人的人脸标签应设置为相同值

LBPH レコグナイザーの detect() メソッドの基本形式は次のとおりです。

label, confidence = recoginer.predict(testimg)

# label为返回的标签值
# confidence为返回的可信度, 表示未知人脸和模型中已知人脸之间的距离, 0表示完全匹配, 低于50可认为是非常可靠的匹配结果
# test_img为未知人脸图像, 图像必须为灰度图且大小要与训练图像相同

データセットを作成する

どのアルゴリズムを使用する場合でも、トレーニング セットが必要です。ビデオまたはアニメーションからトレーニング セットを作成する方が効率的です。インターネットからダウンロードすることも、カメラ キャプチャ プログラムを自分で作成して収集することもできます。この実験では、いくつかの星のアニメーションをインターネットから直接ダウンロードし、アニメーションをフレームごとに分解し、OpenCV の Haar カスケードを使用して顔領域を検出し、すべての顔領域を 200X200 のグレースケール画像として保存しました。対応するフォルダーを選択してトレーニング セットを作成します。

from PIL import Image
import os
import cv2
import numpy as np

# GIF动图转图片
def gifSplit2Array(gif_path):
    import numpy as np
    img = Image.open(os.path.join(path, gif_path))
    for i in range(img.n_frames):
        img.seek(i)
        new = Image.new("RGBA", img.size)
        new.paste(img)
        arr = np.array(new).astype(np.uint8)  # image: img (PIL Image):
        yield arr[:, :, 2::-1]  # 逆序(RGB 转BGR), 舍弃alpha通道, 输出数组供openCV使用


# 人脸检测
def face_generate(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    front_face_cascade = cv2.CascadeClassifier('./data/haarcascade_frontalface_alt2.xml')  # 检测正脸
    faces0 = front_face_cascade.detectMultiScale(gray, 1.02, 5)
    eye_cascade = cv2.CascadeClassifier('./data/haarcascade_eye_tree_eyeglasses.xml')  # 检测眼睛
    if faces0 is not None:
        for (x, y, w, h) in faces0:
            face_area = gray[y: y + h, x: x + w]  # (疑似)人脸区域
            quasi_eyes = eye_cascade.detectMultiScale(face_area, 1.03, 5, 0)  # 在人脸区域检测眼睛
            if len(quasi_eyes) == 0: continue
            quasi_eyes = tuple(
                filter(lambda x: x[2] / w > 0.18 and x[1] < 0.5 * h, quasi_eyes))  # ex,ey,ew,eh; ew/w>0.18,尺寸过滤 ,且眼睛在脸的上半部
            if len(quasi_eyes) <= 1: continue
            yield cv2.resize(face_area, (200, 200))


# 制作数据集
def get_dataset(path, gif_list):
    i = 0
    all_items = os.listdir(path)
    print(all_items)
    for item in all_items:
        name = item.split('-')[0]
        name_path = os.path.join(path, name)
        if not os.path.exists(name_path):
            os.mkdir(name_path)

    for gif in gif_list:
        print(gif)
        for img in gifSplit2Array(gif):
            for face in face_generate(img):
                cv2.imwrite("./dataset/%s/%s.pgm" % (gif.split('-')[0], i), face)
                # print(i)
                i += 1



if __name__ == '__main__':
    path = './dataset'
    gif_list = ["Yangmi-1.gif", "Yangmi-2.gif", "Yangmi-3.gif", "Liushishi-1.gif", "Liushishi-2.gif", "Liushishi-3.gif"]
    get_dataset(path, gif_list)

処理結果

データセットをロードする

すべてのデータを 1 つの ndarray 配列に入れる

def load_dataset(datasetPath):
    names = []
    X = []
    y = []
    ID = 0
    for name in os.listdir(datasetPath):
        subpath = os.path.join(datasetPath, name)
        if os.path.isdir(subpath):
            names.append(name)
            for file in os.listdir(subpath):
                im = cv2.imread(os.path.join(subpath, file), cv2.IMREAD_GRAYSCALE)
                X.append(np.asarray(im, dtype=np.uint8))
                y.append(ID)
            ID += 1
    X = np.asarray(X)
    y = np.asarray(y, dtype=np.int32)
    return X, y, names

トレーニングデータセット

X, y, names = load_dataset(path)
# 报错找不到face模块是因为只安装了主模块
# pip uninstall opencv-python,   pip install opencv0-contrib-python
# 创建人脸识别模型(三种识别模式)
# model = cv2.face.EigenFaceRecognizer_create() #createEigenFaceRecognizer()函数已被舍弃
# model = cv2.face.FisherFaceRecognizer_create()
model = cv2.face.LBPHFaceRecognizer_create()
model.train(X, y)

単一画像テスト

注: face_generate() 関数の最後の行を次のように変更します。

yield cv2.resize(face_area, (200, 200)), x, y, w, h

テストを開始する

    path = './dataset'
    infer_path = './data/Yangmi.jpeg'
    # gif_list = ["Yangmi-1.gif", "Yangmi-2.gif", "Yangmi-3.gif", "Liushishi-1.gif", "Liushishi-2.gif", "Liushishi-3.gif"]
    # get_dataset(path, gif_list)
    X, y, names = load_dataset(path)
    # 报错找不到face模块是因为只安装了主模块
    # pip uninstall opencv-python,   pip install opencv0-contrib-python
    # 创建人脸识别模型(三种识别模式)
    # model = cv2.face.EigenFaceRecognizer_create() #createEigenFaceRecognizer()函数已被舍弃
    # model = cv2.face.FisherFaceRecognizer_create()
    model = cv2.face.LBPHFaceRecognizer_create()
    model.train(X, y)
    img = cv2.imread(infer_path)
    for roi, x, y, w, h in face_generate(img):
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 画红色矩形框标记正脸
        ID_predict, confidence = model.predict(roi)  # 预测!!!
        name = names[ID_predict]
        print("name:%s, confidence:%.2f" % (name, confidence))
        text = name if confidence < 70 else "unknow"  # 10000 for EigenFaces #70 for LBPH
        cv2.putText(img, text, (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)  # 绘制绿色文字

    cv2.imshow('', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

試験結果:
Yang Mi の顔検出と認識効果

補足:この実装方法は完全にopencvの組み込みメソッドを利用していますが、現時点では画像認識は1枚のみでデータセットも比較的少ないです、実環境での認識効果は検証が必要で、顔位置合わせプログラムはありません自分で書いたものを追加しました、後で組み合わせて認識効果を向上させたいと思います

おすすめ

転載: blog.csdn.net/weixin_42149550/article/details/131474284