人脸识别(dlib.face_recognition_model_v1 方法 -- 使用resnet模型)

人脸识别

思路:通过检测面部特征, 对该特征与数据存放的特征进行比对

文件结构:
文件名:weights 的目录下:resnet模型(.dat文件)、识别68个关键点模型(.dat文件)、共两个模型文件
补充:你如果不使用dlib库中自带的HOG人脸检测器, 那你可能会将识别人脸区域的模型再放入其中。
文件名:save 的目录下:每个人的多张图像文件被存储在独立的文件夹内。

一、找面部特征

代码文件名:ao1
1.人脸区域检测
2.检测人脸68个关键点
3.将68个关键点转换为128D面部描述符
4.转换为自己需要的np格式

import cv2
import numpy as np
import dlib


def cv_show(neme, img):
    cv2.namedWindow(neme, cv2.WINDOW_NORMAL)
    cv2.imshow(neme, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


class Eigenvector(object):
    def __init__(self):
        # resnet模型
        self.face_descriptor_extractor = dlib.face_recognition_model_v1(
            './weights/dlib_face_recognition_resnet_model_v1.dat')

        # 人脸检测模型
        self.hog_face_detector = dlib.get_frontal_face_detector()
        # 获取人脸的68个关键点
        self.shape_detector = dlib.shape_predictor('./weights/shape_predictor_68_face_landmarks.dat')

    def fun1(self, img):
        # 检测人脸
        detections = self.hog_face_detector(img, 1)
        # 可能识别多张人脸(但只要第一个识别到的人脸)
        for face in detections:
            # # 人脸框坐标
            # l, t, r, b = face.left(), face.top(), face.right(), face.bottom()
            # 获取68个关键点
            points = self.shape_detector(img, face)

            # # 绘制关键点
            # for point in points.parts():
            #     cv2.circle(img, (point.x, point.y), 2, (0, 255, 0), 1)
            #
            # # 绘制矩形框
            # cv2.rectangle(img, (l, t), (r, b), (0, 255, 0), 2)
            # cv_show('neme', img)

            # 获取特征描述符
            # 功能:图像中的68个关键点转换为128D面部描述符,其中同一人的图片被映射到彼此附近,并且不同人的图片被远离地映射。
            # 参数:img_rd:人脸灰度图,类型:numpy.ndarray
            #    shape:68个关键点位置
            # 返回值:128D面部描述符
            face_descriptor = self.face_descriptor_extractor.compute_face_descriptor(img, points)

            # 转为numpy 格式的数组
            face_descriptor = [f for f in face_descriptor]

            face_descriptor = np.array(face_descriptor, dtype=np.float64)

            face_descriptor = np.reshape(face_descriptor, (1, -1))
            # print(face_descriptor.shape)
            return face_descriptor


if __name__ == '__main__':
    # 提取人脸区域
    path = './images_1/Angelababy/a1.jpg'
    img = cv2.imread(path)
    # 转为RGB  为了准确率
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    # 返回值:128D面部描述符
    p = Eigenvector().fun1(img)
    print(p.shape)

二、存每个人的面部特征

代码文件名:ao2

# 批量读取数据
import os
import cv2
import numpy as np

import ao1


def cv_show(neme, img):
    cv2.namedWindow(neme, cv2.WINDOW_NORMAL)
    cv2.imshow(neme, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def r_path_name(path):
    list_img = os.listdir(path)

    # 一个人的特征表
    person = []
    # 标签列表
    lab = []

    # 标签号
    lab_n = 0

    for i in range(len(list_img)):
        list_img_name = os.listdir(path + list_img[i])

        lab_n += 1

        # 当前类别的特征集合
        feature_list = None

        for j in list_img_name:
            path_n = path + list_img[i] + "/" + j

            # 读取图片
            img = cv2.imread(path_n)
            # 转为RGB  为了提高准确率
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

            # cv_show('neme', img)

            # 人脸特征向量
            feat = ao1.Eigenvector().fun1(img)

            # 如果识别到了人脸
            if not feat is None:
                if feature_list is None:
                    feature_list = feat
                else:
                    # 特征列表 拼接矩阵 竖向合并
                    feature_list = np.concatenate((feature_list, feat), axis=0)
        person.append(feature_list)
        lab.append(lab_n)
    return person, lab


if __name__ == '__main__':
    path = "./images_1/"
    img, lab = r_path_name(path)

    print(len(img))
    print(len(lab))

    # 保存路径
    path_s = "./save/"
    # 保存csv
    for i, j in zip(img, lab):

        fo1 = open(f"{path_s}{j}.txt", "w", encoding="utf-8")

        # 写入
        fo1.write(str(i.tolist()))
        # 关闭打开的文件
        fo1.close()

三、解析存的每个人面部特征

代码文件名:ao3

import numpy as np
import os


def characteristic_list():
    path = "./save/"
    list_txt = os.listdir(path)

    # 所有人的特征向量列表
    po = []

    # 每个txt就是一个类别
    for i in list_txt:
        fo = open(f"{path}{i}", "r", encoding="utf-8")

        # 读取所有, 返回列表
        x = fo.readlines()
        # 关闭打开的文件
        fo.close()

        # print("-" * 100)

        for j in x:
            # 将txt内的图像分开, 每一张图像的特征向量存在一个列表中
            # 分开返回的是, 每张图像的字符串形式的 特征向量

            # 多张图像 的特征矩阵 列表, 每个元素都是 单张图像的特征矩阵
            list_f = None

            # 需要将每个数字 从字符串 转 浮点型
            for str_ in j[2:-3].split('], ['):

                # 重新合成 单张图像的特征向量
                feature_list = []

                # 单个数字
                for s_1 in str_.split(','):
                    # -0.060944315046072006,
                    feat = float(s_1)

                    feature_list.append(feat)

                # 转换为np格式  并 变换维度
                feature_list = np.reshape(np.array(feature_list), (1, -1))

                if list_f is None:
                    list_f = np.array(feature_list)
                else:
                    # 特征列表 拼接矩阵 竖向合并
                    list_f = np.concatenate((list_f, np.array(feature_list)), axis=0)

            # print(list_f.shape)
            po.append(list_f)

    return po

四、当前人的面部特征与库中的面部特征进行比对

代码文件名:ao4

import ao3
import ao1

import cv2
import numpy as np

# 提取人脸区域
path = './2.jpg'
img = cv2.imread(path)
# 转为RGB  为了准确率
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 返回值:128D面部描述符
feat = ao1.Eigenvector().fun1(img)

# 每个人脸特征 列表
feature_list = ao3.characteristic_list()

# 每个人脸 特征值相距的最小值 列表
min_x = []
for i in feature_list:
    # 计算欧式距离
    distances = np.linalg.norm((feat - i), axis=1)
    min_x.append(min(distances))

# 最小值索引
min_index = np.argmin(min_x)
print(min_index)

你可能感兴趣的:(计算机视觉项目,opencv,计算机视觉,python)