使用dlib库进行人脸识别

一、安装opencv和dlib

我使用的anaconda,安装比较方便。

安装opencv,在指定环境下输入:

conda install opencv

安装dlib:

conda install -c conda-forge dlib

二、实现

1、项目结构介绍

其中face_detect文件夹保存检查到的人脸,face_repo里是待检测的人脸照片,face_test里是用来测试的照片。

2、人脸检测

定义检测器和识别模型:

detector = dlib.get_frontal_face_detector()
# detector = dlib.cnn_face_detection_model_v1('mmod_human_face_detector.dat')
sp = dlib.shape_predictor(FLAGS.shape_predictor)
facerec = dlib.face_recognition_model_v1(FLAGS.reco_model)

detector有两种选择,其中dlib.cnn_face_detection_model_v1使用的cnn进行检测。

对于单张图片的检测如下:

def return_face_features(path_img):
    img = cv2.imread(path_img)
    if img.shape[0] * img.shape[1] > 400000:  # 对大图可以进行压缩,阈值可以自己设置
        img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)
    dets = detector(img, 1)  # 使用检测算子检测人脸,返回的是所有的检测到的人脸区域
    print("检测的人脸图像:", path_img, "\n")
    d = dets[0]     # 默认处理第一个检测到的人脸区域
    bb = np.zeros(4, dtype=np.int32)
    bb[0] = np.maximum(d.left(), 0)
    bb[1] = np.maximum(d.top(), 0)
    bb[2] = np.minimum(d.right(), img.shape[1])
    bb[3] = np.minimum(d.bottom(), img.shape[0])

    rec = dlib.rectangle(bb[0], bb[1], bb[2], bb[3])
    shape = sp(img, rec)  # 获取landmark
    face_descriptor = facerec.compute_face_descriptor(img, shape)  # 使用resNet获取128维的人脸特征向量
    face_array = np.array(face_descriptor).reshape((1, 128))  # 转换成numpy中的数据结构

    # 显示人脸区域
    cv2.rectangle(img, (bb[0], bb[1]), (bb[2], bb[3]), (0, 255, 0), 2)
    cv2.waitKey(2)
    cropped = img[bb[1]:bb[3], bb[0]:bb[2], :]
    scaled = cv2.resize(cropped, (100, 100), interpolation=cv2.INTER_LINEAR)
    cv2.imwrite(os.path.join(FLAGS.detected_faces, path_img.split('\\')[-1]), scaled)
    cv2.imshow('image', img)
    cv2.waitKey(1000)

    return face_array

遍历face_repo文件夹下所有人的所有图片,调用上述方法进行检测:

def main():
    data = np.zeros((1, 128))  # 定义一个128维的空向量data
    label = []  # 定义空的list存放人脸的标签
    for file in os.listdir(FLAGS.input_faces):  # 遍历目录下的文件夹及文件
        path = os.path.join(FLAGS.input_faces, file)
        if os.path.isdir(path):     # 如果是目录
            feature_tmp = np.zeros((1, 128))
            label_name = file
            img_num = 0
            for image in os.listdir(path):
                if '.jpg' in image or '.png' in image:
                    img_num += 1
                    file_path = os.path.join(path, image)
                    print('current image: {}, current label: {}'.format(file_path, label_name))
                    feature_tmp += return_face_features(file_path)
            if img_num > 0:
                feature = feature_tmp / img_num
                data = np.concatenate((data, feature))  # 保存每个人的人脸特征
                label.append(label_name)  # 保存标签

    data = data[1:, :]  # 因为data的第一行是128维0向量,所以实际存储的时候从第二行开始
    np.savetxt(FLAGS.feature_dir, data, fmt='%f')  # 保存人脸特征向量合成的矩阵到本地
    label_file = open(FLAGS.label_dir, 'w')
    json.dump(label, label_file)  # 使用json保存list到本地
    label_file.close()
    cv2.destroyAllWindows()  # 关闭所有的窗口

该过程主要是检测单张图片中的人脸,并保存其人脸特征数据和其label。此时输入的照片中应只有一个人脸,以便将不同人的人脸数据记录下来,作为后续识别对比之用。在这里将检测到的人脸截取并保存到face_detect文件夹中,如下:

选择了五个人,每人各有几张照片,检测区域还可以。

 3、人脸识别

对于单张图片的识别过程如下:

def recognition(img):
    dets = detector(img, 1)
    bb = np.zeros(4, dtype=np.int32)
    for k, d in enumerate(dets):
        print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
            k, d.left(), d.top(), d.right(), d.bottom()))

        bb[0] = np.maximum(d.left(), 0)
        bb[1] = np.maximum(d.top(), 0)
        bb[2] = np.minimum(d.right(), img.shape[1])
        bb[3] = np.minimum(d.bottom(), img.shape[0])
        rec = dlib.rectangle(bb[0], bb[1], bb[2], bb[3])
        shape = sp(img, rec)
        face_descriptor = facerec.compute_face_descriptor(img, shape)

        class_pre = find_most_likely_face(face_descriptor)
        print(class_pre)
        cv2.rectangle(img, (rec.left(), rec.top()), (rec.right(), rec.bottom()), (0, 255, 0), 2)
        cv2.putText(img, class_pre, (rec.left(), rec.top()), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2, cv2.LINE_AA)

    cv2.imshow('image', img)
    cv2.waitKey()

检测图片中的人脸(可以有多个),针对每个人脸,将其和保存的人脸特征数据进行对比,选择距离最小的人脸特征,如果最小距离大于设定阈值,说明该人脸不属于已保存的任何一个人。

我随便找了几张包含刘诗诗和刘亦菲的照片,测试一下识别效果,其中几张结果如下:

测试结果发现效果很一般,尤其对于遮挡和侧脸。

4、可视化

可以使用tensorboard对数据进行可视化

2D效果如下:

图片数据太少,可视化效果不好

代码:https://github.com/buptlj/face

后续会介绍一下基于face_net的人脸识别,那个效果要好很多。

猜你喜欢

转载自blog.csdn.net/qiumokucao/article/details/81610628