人脸识别流程不在介绍,直接上代码,改下识别包和图片路径即可运行识别:

import cv2
import dlib
from skimage import io
import numpy as np
import redis
import datetime


# 要读取人脸图像文件的路径 / Path of cropped faces
path_images_from_camera = "/Users/a123456/software/opencvtxt/data/data_faces_from_camera/person_1/"

# Dlib 正向人脸检测器 / Use frontal face detector of Dlib
detector = dlib.get_frontal_face_detector()

# Dlib 人脸 landmark 特征点检测器 / Get face landmarks
predictor = dlib.shape_predictor('/Users/a123456/software/opencvtxt/Dlib/data/data_dlib/shape_predictor_68_face_landmarks.dat')

# Dlib Resnet 人脸识别模型,提取 128D 的特征矢量 / Use Dlib resnet50 model to get 128D face descriptor
face_reco_model = dlib.face_recognition_model_v1("/Users/a123456/software/opencvtxt/Dlib/data/data_dlib/dlib_face_recognition_resnet_model_v1.dat")

# 连接数据库redis,存放数据
def sava_redis_info(key, value):

    if not isinstance(value, list):
        print('数据类型错误')
        return

    r = redis.Redis(host='47.xxx.xx.xxx', port=6379, password='', db=1, decode_responses=True)
    # 对values进行处理
    end_info = str(value)[1:len(str(value))-1].replace(" ", "")
    r.lpush(key, end_info)
    r.expire(key, 3600)
    print("保存成功!")


# 连接数据库redis, 取出数据
def get_redis_info(key):
    r = redis.Redis(host='47.xxx.xxx.xxx', port=6379, password='', db=1, decode_responses=True)
    index_res = r.llen(key)
    if index_res == 0:
        print("数据不存在")
        return 0
    redis_list = r.lrange(key, 0, index_res)
    new_list = []
    for i in redis_list:
        new_list.append(list(i.split(",")))

    return new_list


# 计算图片到128d特征
def return_128d_features(path_img):
    img_rd = io.imread(path_img)

    # 判断图片中是否有人脸
    faces = detector(img_rd, 1)

    if len(faces) != 0:
        shape = predictor(img_rd, faces[0])
        face_descriptor = face_reco_model.compute_face_descriptor(img_rd, shape)
    else:
        print("未检测到人脸")
        return 0
    return face_descriptor

# 计算两个128D向量间的欧式距离
def return_euclidean_distance(feature_1, feature_2):
    feature_1 = np.array(feature_1)
    feature_2 = np.array(feature_2)
    dist = np.sqrt(np.sum(np.square(feature_1 - feature_2)))

    return dist


# 将视频变为一张张图片
def video_save_image(frame, save_path, image_name, frame_count):
    resize_frame = cv2.resize(frame, (576, 1024), interpolation=cv2.INTER_AREA)
    cv2.imwrite(save_path + "{}-{}.jpg".format(image_name, frame_count), resize_frame)


# 对视频进行处理
def video_dispose(video_path, key):
    """
    :param video_path: 视频路径
    :return:
    3 帧宽
    4 帧高
    """
    time1 = datetime.datetime.now()

    image = cv2.VideoCapture(video_path)
    # image.set(4, 480)  # 640x480
    # image.set(3, 640)  # 640x480

    image_num = 0
    image_num_no = 1

    try:
        # 只要视频不停止则一直捕获
        while (image.isOpened()):

            # 逐帧捕获
            is_success, frame = image.read()

            # 检测人脸
            faces = detector(frame, 0)

            # 按下q键则退出
            kk = cv2.waitKey(1)
            if kk == ord('q'):
                break

            # 如果检测到有人脸
            if len(faces) != 0:
                vector_list = []
                for i in range(len(faces)):
                    shape = predictor(frame, faces[i])
                    vector_list.append(face_reco_model.compute_face_descriptor(frame, shape))

                # 取出数据
                res_list = get_redis_info(key)
                redis_list_len = len(res_list)
                res_dist = 0

                # 计算欧式距离
                for i in res_list:
                    s_list = []
                    for m in i:
                        s_list.append(float(m))

                    res_dist = res_dist + return_euclidean_distance(s_list, list(vector_list))

                new_res_dist = res_dist / redis_list_len
                if new_res_dist <= 0.4:
                    image_num += 1

                    # 保存图片
                    # video_save_image(frame, path_images_from_camera, "video", image_num)

                    print("是同一个人,相似度为{}".format(1-float(new_res_dist)))
                else:
                    image_num_no += 1
                    print("不是同一个人,相似度为{}".format(1 - float(new_res_dist)))

    except Exception as e:
        time2 = datetime.datetime.now()
        print("视频结束!一共识别图片{}张!未识别图片{}张,耗时{}".format(image_num, image_num_no, time2-time1))


# 图片识别运行入口
def main(identification, path, type=2):

    # 1. 获取要识别图片对路径
    # path_images_from_camera = "/Users/a123456/software/opencvtxt/data/data_faces_from_camera/person_1/"
    # image_path = path_images_from_camera + path
    image_path = path

    # 2. 获取要识别图片对128d特征
    face_descriptor = return_128d_features(image_path)
    if not face_descriptor:
        return

    # 2.1 如果是保存特征值
    if type == 1:
        sava_redis_info(identification, list(face_descriptor))
        return

    # 2.2 获取数据库中存储的128d特征
    res_128d = get_redis_info(identification)
    redis_list_len = len(res_128d)
    res_dist = 0

    if not res_128d:
        return

    for i in res_128d:
        s_list = []
        for m in i:
            s_list.append(float(m))

        # 3. 计算两个128D向量间的欧式距离、
        res_dist = res_dist + return_euclidean_distance(list(face_descriptor), s_list)

    new_res_dist = res_dist / redis_list_len
    # 4. 判断是否是同一个人
    if new_res_dist <= 0.40:
        print("是同一个人,相似度为{}".format(1-float(new_res_dist)))
    else:
        print("不是同一个人,相似度为{}".format(1-float(new_res_dist)))


time1 = datetime.datetime.now()
main("13781972862", "img-1.jpg", type=2)
time2 = datetime.datetime.now()
print(time2-time1)
# video_dispose("/Users/a123456/software/opencvtxt/data/data_faces_from_camera/person_1/1633745580459094.mp4", "13781972862")

Dlib 人脸 landmark 特征点检测器和
Dlib Resnet 人脸识别模型,提取 128D 的特征矢量的库可以使用云盘下载:
链接: https://pan.baidu.com/s/1nQ6BTiWsOtlvB_Qoh3bqzA 
提取码: 69e1

这主要是使用dlib来实现的,效率不高,但是还可以!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐