[Detección de rostros] Prueba la versión de python Dlib detección de rostros, puntos clave, alineación y reconocimiento

Refiérase principalmente a dos artículos:

https://blog.csdn.net/liuxiao214/article/details/83411820

https://www.jianshu.com/p/577af31ced74

0. Medio ambiente

windows
python3.6
Dlib
numpy==1.14.5
glob
opencv-python==3.4.3.18

Instale la referencia de Dlib: https://blog.csdn.net/qq_35975447/article/details/109802787

0.1 Estructura de archivos

│  .gitignore
│  faceAlignment.py
│  faceDetect.py
│  faceLandmarks.py
│  faceRecognition.py
│  file.txt
│      
├─data
│  │  test_1988.jpg
│  │  
│  ├─candidate-faces
│  │      liushishi.jpg
│  │      liuyifei.jpg
│  │      tangyan.jpg
│  │      tongliya.jpg
│  │      yangzi.jpg
│  │      zhaoliying.jpg
│  │      
│  └─faces
│          tangyan.jpg
│          zhaoliying.jpg
│          
├─models
│      dlib_face_recognition_resnet_model_v1.dat
│      mmod_human_face_detector.dat
│      shape_predictor_5_face_landmarks.dat
│      shape_predictor_68_face_landmarks.dat
│      
└─results
    ├─alignment
    │      test_1988_0_Align68.jpg
    │      test_1988_1_Align68.jpg
    │      test_1988_2_Align68.jpg
    │      test_1988_3_Align68.jpg
    │      test_1988_4_Align68.jpg
    │      test_1988_5_Align68.jpg
    │      
    ├─detect
    │      test_1988_HOG.jpg
    │      test_1988_MMOD.jpg
    │      
    ├─landmarks
    │      test_1988_5Landmarks.jpg
    │      test_1988_68Landmarks.jpg
    │      
    └─recongnition
            recognition_reslut.txt
            

0.2 Descarga del modelo

https://github.com/davisking/dlib-models

0.3 mi código

https://download.csdn.net/download/qq_35975447/13129563

1. Comparación de dos métodos de detección de rostros

Los dos métodos incluyen principalmente: Dlib incluye y llama al modelo de aprendizaje profundo.

1.1 Hora

CERDO

MMOD

1.437422513961792s

 

106.82666826248169s

1.2 Efecto

Imagen original:

 Efecto HOG:

Efecto MMOD:

1.2 Código

El código aquí se refiere principalmente al primer enlace, y luego, de acuerdo con el método propio de Dlib y llamando al modelo de aprendizaje profundo, el tiempo de prueba se ejecuta en un bucle y la imagen se guarda en el directorio results / detect /:

# encoding:utf-8

import dlib
import cv2
import os
import time

def rect_to_bb(rect): # 获得人脸矩形的坐标信息
    x = rect.left()
    y = rect.top()
    w = rect.right() - x
    h = rect.bottom() - y
    return (x, y, w, h)

def resize(image, width=1200):  # 将待检测的image进行resize
    r = width * 1.0 / image.shape[1]
    dim = (width, int(image.shape[0] * r))
    resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
    return resized

def detect(isHOG=False):
    image_path = "./data/"
    image_file = "test_1988.jpg"
    startTime = time.time()
    if isHOG:
        detector = dlib.get_frontal_face_detector()  # 基于HOG+SVM分类
    else:
        model_path = "./models/mmod_human_face_detector.dat"  # 基于 Maximum-Margin Object Detector 的深度学习人脸检测方案
        detector = dlib.cnn_face_detection_model_v1(model_path)
    image = cv2.imread(image_path + image_file)
    image = resize(image, width=1200)
    # image = resize(image, width=600)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    rects = detector(gray, 1)
    print("{} method, detect spend {}s ".format(("HOG" if isHOG else "MMOD"), time.time()-startTime))
    for (i, rect) in enumerate(rects):
        if isHOG:
            (x, y, w, h) = rect_to_bb(rect)
        else:
            (x, y, w, h) = rect_to_bb(rect.rect)
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.putText(image, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

    cv2.imshow("Output", image)
    savePath = "./results/detect/"
    if not os.path.exists(savePath):
        os.makedirs(savePath)
    if isHOG:
        saveName = image_file[:-4] + "_HOG.jpg"
    else:
        saveName = image_file[:-4] + "_MMOD.jpg"
    cv2.imwrite(savePath + saveName, image)
    cv2.waitKey(10)

if __name__ == "__main__":
    isHOG = True
    detect(isHOG)
    if isHOG:
        isHOG = not isHOG
        detect(isHOG)

2. Dos comparaciones de detección de puntos clave de rostros

Los dos tipos principales incluyen: 5 puntos clave y 68 puntos clave. Ambos necesitan llamar al modelo.

2.1 Hora

68Hitos

5Hitos

0.011994600296020508s

0.0030002593994140625s

2.2 Efecto de rendimiento

5 puntos de referencia

68 puntos de referencia

2.3 Código

El código aquí se refiere principalmente al primer enlace, ejecuta los dos métodos respectivamente y luego guarda los resultados en ./results/landmarks/:

# encoding:utf-8

import dlib
import numpy as np
import cv2
import os
import time

def rect_to_bb(rect): # 获得人脸矩形的坐标信息
    x = rect.left()
    y = rect.top()
    w = rect.right() - x
    h = rect.bottom() - y
    return (x, y, w, h)

def shape_to_np(shape, is68Landmarks=True, dtype="int"): # 将包含68个特征的的shape转换为numpy array格式
    if is68Landmarks:
        landmarkNum = 68
    else:
        landmarkNum = 5
    coords = np.zeros((landmarkNum, 2), dtype=dtype)
    for i in range(0, landmarkNum):
        coords[i] = (shape.part(i).x, shape.part(i).y)
    return coords


def resize(image, width=1200):  # 将待检测的image进行resize
    r = width * 1.0 / image.shape[1]
    dim = (width, int(image.shape[0] * r))
    resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
    return resized

def feature(is68Landmarks=True):
    image_path = "./data/"
    image_file = "test_1988.jpg"
    detector = dlib.get_frontal_face_detector()
    if is68Landmarks:
        predictor = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat")
    else:
        predictor = dlib.shape_predictor("./models/shape_predictor_5_face_landmarks.dat")

    image = cv2.imread(image_path + image_file)
    image = resize(image, width=1200)# 1200
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    rects = detector(gray, 1)
    shapes = []
    startTime = time.time()
    for (i, rect) in enumerate(rects):
        shape = predictor(gray, rect)
        shape = shape_to_np(shape, is68Landmarks)
        shapes.append(shape)
        (x, y, w, h) = rect_to_bb(rect)
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.putText(image, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
    print("{} method, detect spend {}s ".format(("68Landmarks" if is68Landmarks else "5Landmarks"), time.time()-startTime))

    for shape in shapes:
        for (x, y) in shape:
            cv2.circle(image, (x, y), 2, (0, 0, 255), -1)
    cv2.imshow("Output", image)
    savePath = "./results/landmarks/"
    if not os.path.exists(savePath):
        os.makedirs(savePath)
    if is68Landmarks:
        saveName = image_file[:-4] + "_68Landmarks.jpg"
    else:
        saveName = image_file[:-4] + "_5Landmarks.jpg"
    cv2.imwrite(savePath + saveName, image)
    cv2.waitKey(10)

if __name__ == "__main__":
    is68Landmarks = True
    feature(is68Landmarks)
    if is68Landmarks:
        is68Landmarks = not is68Landmarks
        feature(is68Landmarks)

3. Alineación facial

Tuve que probar los dos métodos aquí, pero los 5 puntos clave no parecían ser fáciles de cambiar, así que me di por vencido, pero el código de referencia todavía está en él y puede eliminarlo usted mismo.

3.1 Hora

Alineación

0.04295229911804199s

3.2 Efecto

Dado que la imagen es demasiado vaga, elija algunas:

3.3 Código

Los puntos clave aquí se basan en:

Inserte la descripción de la imagen aquí

Los resultados se guardarán en ./results/alignment/:

# encoding:utf-8

import dlib
import cv2
import numpy as np
import math
import os
import time

def rect_to_bb(rect): # 获得人脸矩形的坐标信息
    x = rect.left()
    y = rect.top()
    w = rect.right() - x
    h = rect.bottom() - y
    return (x, y, w, h)

def resize(image, width=1200):  # 将待检测的image进行resize
    r = width * 1.0 / image.shape[1]
    dim = (width, int(image.shape[0] * r))
    resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
    return resized

def face_alignment_68(faces):
    # 使用68点关键点模型,根据关键点信息求解变换矩阵,然后把变换矩阵应用到整个图像上。
    predictor = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat") # 用来预测关键点
    faces_aligned = []
    global startTime
    startTime = time.time()
    for face in faces:
        rec = dlib.rectangle(0,0,face.shape[0],face.shape[1])
        shape = predictor(np.uint8(face),rec) # 注意输入的必须是uint8类型
        order = [36,45,30,48,54] # left eye, right eye, nose, left mouth, right mouth  注意关键点的顺序,这个在网上可以找
        for j in order:
            x = shape.part(j).x
            y = shape.part(j).y
            cv2.circle(face, (x, y), 2, (0, 0, 255), -1)

        eye_center =((shape.part(36).x + shape.part(45).x) * 1./2, # 计算两眼的中心坐标
                      (shape.part(36).y + shape.part(45).y) * 1./2)
        dx = (shape.part(45).x - shape.part(36).x) # note: right - right
        dy = (shape.part(45).y - shape.part(36).y)

        angle = math.atan2(dy,dx) * 180. / math.pi # 计算角度
        RotateMatrix = cv2.getRotationMatrix2D(eye_center, angle, scale=1) # 计算仿射矩阵
        RotImg = cv2.warpAffine(face, RotateMatrix, (face.shape[0], face.shape[1])) # 进行仿射变换,即旋转
        faces_aligned.append(RotImg)
    return faces_aligned


def face_alignment_5(rgb_img, faces):
    startTime = time.time()
    faces_aligned = []
    for face in faces:
        # RotImg = dlib.get_face_chip(rgb_img, face)
        RotImg = dlib.get_face_chip(np.uint8(rgb_img), np.uint8(face))
        # RotImg = dlib.get_face_chip(rgb_img, face, size=224, padding=0.25)
        faces_aligned.append(RotImg)
    return faces_aligned

def demo(isAlignment_5=True):
    image_path = "./data/"
    image_file = "test_1988.jpg"
    im_raw = cv2.imread(image_path + image_file).astype('uint8')

    # detector = dlib.get_frontal_face_detector()
    model_path = "./models/mmod_human_face_detector.dat"  # 基于 Maximum-Margin Object Detector 的深度学习人脸检测方案
    detector = dlib.cnn_face_detection_model_v1(model_path)
    im_raw = resize(im_raw, width=1200)
    gray = cv2.cvtColor(im_raw, cv2.COLOR_BGR2GRAY)
    rects = detector(gray, 1)

    src_faces = []
    for (i, rect) in enumerate(rects):
        (x, y, w, h) = rect_to_bb(rect.rect)
        detect_face = im_raw[y:y+h,x:x+w]
        src_faces.append(detect_face)
        cv2.rectangle(im_raw, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.putText(im_raw, "Face: {}".format(i + 1), (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
    if isAlignment_5:
        faces_aligned = face_alignment_5(im_raw, src_faces)
    else:
        faces_aligned = face_alignment_68(src_faces)
    print("{} method, detect spend {}s ".format(("Alignment_5" if isAlignment_5 else "Alignment_68"), time.time()-startTime))

    cv2.imshow("src", im_raw)
    savePath = "./results/alignment/"
    if not os.path.exists(savePath):
        os.makedirs(savePath)
    if isAlignment_5:
        saveName = "_Align5.jpg"
    else:
        saveName = "_Align68.jpg"
    i = 0
    for face in faces_aligned:
        cv2.imshow("det_{}".format(i), face)
        cv2.imwrite(savePath + image_file[:-4] + "_{}".format(i) + saveName, face)
        i = i + 1
    cv2.waitKey(10)

if __name__ == "__main__":
    isAlignment_5 = False
    demo(isAlignment_5)
    if isAlignment_5:
        isAlignment_5 = not isAlignment_5
        demo(isAlignment_5)

4. Reconocimiento facial

Este lugar pasa mucho tiempo, principalmente cuando el reconocimiento no es bueno, no me hundí el corazón para analizar el código, aquí se modifica de acuerdo al código en la referencia uno, no es necesario configurar manualmente la lista de candidatos, solo necesitamos para establecer las caras de los candidatos nosotros mismos. La biblioteca de candidatos de la carpeta lleva el nombre de la persona que se puede distinguir.

4.1 Proceso de preparación

(1) Candidatos-caras en la base de datos de candidatos, vamos a esta base de datos para consultar, cuáles son conocidas y tienen la identidad correcta.

(2) Asignación de nombres de las caras de los candidatos:

 

 

(3) Caras a consultar: 

tangyan.jpg

 

zhaoliying.jpg
zhaoliying.jpg

(4) Resultados 

Processing file: ./data/candidate-faces\liushishi.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\liuyifei.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\tangyan.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\tongliya.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\yangzi.jpg
Number of faces detected: 1
Processing file: ./data/candidate-faces\zhaoliying.jpg
Number of faces detected: 1
c_d :[('tangyan', 0.45614611065543303), ('liushishi', 0.4777414300544273), ('yangzi', 0.520176500668875), ('tongliya', 0.547071465533885), ('zhaoliying', 0.64414064895386), ('liuyifei', 0.669962308077882)]
The person_test--./data/faces/tangyan.jpg is:  tangyan
c_d :[('zhaoliying', 0.4041512584817519), ('liushishi', 0.4681194204229278), ('tangyan', 0.4728928349513442), ('yangzi', 0.47474913579746303), ('tongliya', 0.5446001882500634), ('liuyifei', 0.6104574640831666)]
The person_test--./data/faces/zhaoliying.jpg is:  zhaoliying

4.2 Código

Los resultados se guardarán en el archivo ./results/recongnition/recognition_reslut.txt.

# encoding:utf-8

import dlib
import cv2
import numpy as np
import os, glob


def resize(image, width=1200):  # 将待检测的image进行resize
    r = width * 1.0 / image.shape[1]
    dim = (width, int(image.shape[0] * r))
    resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
    return resized

def rect_to_bb(rect): # 获得人脸矩形的坐标信息
    x = rect.left()
    y = rect.top()
    w = rect.right() - x
    h = rect.bottom() - y
    return (x, y, w, h)

def create_face_space():

    # 对文件夹下的每一个人脸进行:
    # 1.人脸检测
    # 2.关键点检测
    # 3.描述子提取

    # 候选人脸文件夹
    faces_folder_path = "./data/candidate-faces/"
    # 候选人脸描述子list
    descriptors = []
    candidates = []
    for f in glob.glob(os.path.join(faces_folder_path, "*.jpg")):
        print("Processing file: {}".format(f))
        img = cv2.imread(f)
        # img = resize(img, width=300)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 1.人脸检测
        dets = detector(img, 1)
        print("Number of faces detected: {}".format(len(dets)))
        candidate = f.split('\\')[-1][:-4]
        for k, d in enumerate(dets):
            # 2.关键点检测
            shape = sp(img, d)

            # 3.描述子提取,128D向量
            face_descriptor = facerec.compute_face_descriptor(img, shape)

            # 转换为numpy array
            v = np.array(face_descriptor)
            descriptors.append(v)
            candidates.append(candidate)
    return descriptors, candidates


def predict(descriptors, path):
    # 对需识别人脸进行同样处理
    # 提取描述子
    img = cv2.imread(path)
    # img = io.imread(path)
    # img = resize(img, width=300)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    dets = detector(gray, 1)
    dist = []
    if len(dets) == 0:
        pass
    for k, d in enumerate(dets):
        shape = sp(img, d)
        face_descriptor = facerec.compute_face_descriptor(img, shape)
        d_test = np.array(face_descriptor)

        # 计算欧式距离
        for i in descriptors:
            dist_ = np.linalg.norm(i-d_test)
            dist.append(dist_)
            # print(dist)
    return dist

def demo():
    global detector, sp, facerec
    # 加载正脸检测器
    detector = dlib.get_frontal_face_detector()

    # 加载人脸关键点检测器
    sp = dlib.shape_predictor("./models/shape_predictor_68_face_landmarks.dat")

    # 3. 加载人脸识别模型
    facerec = dlib.face_recognition_model_v1("./models/dlib_face_recognition_resnet_model_v1.dat")

    # 提取候选人特征与候选人名单
    descriptors, candidates = create_face_space()
    savePath = "./results/recongnition/"
    if not os.path.exists(savePath):
        os.makedirs(savePath)
    fp = open(savePath + 'recognition_reslut.txt', 'a')
    predict_path = "./data/faces/*.jpg"
    for f in glob.glob(predict_path):
        f = f.replace("\\", '/')
        # print("f :{}".format(f))
        dist = predict(descriptors, f)
        # 候选人和距离组成一个dict
        c_d = dict(zip(candidates, dist))
        if not c_d:
            print(str(c_d) + " is None")
            continue
        cd_sorted = sorted(c_d.items(), key=lambda d:d[1])
        print("c_d :{}".format(cd_sorted))

        print("The person_test--{} is: ".format(f), cd_sorted[0][0])
        fp.write("\nThe person_test--{} is: with similar : {}".format(f, cd_sorted[0][0]))
    fp.close()

if __name__ == "__main__":

    demo()

 referencia

1. [Dlib] detección de rostros, detección de puntos de características, alineación de rostros, reconocimiento de rostros

2. [Herramienta] Aprendizaje de la interfaz Dlib e introducción de funciones comunes

3.dlib-modelos

4. Detección de puntos clave: leyenda de 68 puntos

5. Dlib extrae puntos de características faciales (68 puntos, dibujo opencv)

 

Supongo que te gusta

Origin blog.csdn.net/qq_35975447/article/details/109843045
Recomendado
Clasificación