基于insightface实现的人脸识别和人脸注册

为了方便,写一个类完成所有的识别流程,开始编写人脸识别和人脸注册工具类,使用`insightface.app.FaceAnalysis()`可以获取模型对象,这里包含了三个模型,首先是人脸检测模型,然后是人脸特征提取模型,和最后的性别年龄识别模型。使用`model.prepare()`可以配置`ctx_id`指定使用哪一块GPU,如果是负数则是使用CPU执行预测,`det_thresh`配置的是人

本教程的人脸识别是使用的是insightface库进行开发的,该库使用的框架为ONNX,使用的是Anaconda环境。

代码地址:点击下载

安装环境

  1. 安装insightface ,安装命令如下。
python -m pip install Cython insightface==0.6.2 -i https://mirror.baidu.com/pypi/simple
  1. 安装onnxruntime-gpu,命令如下。
python -m pip install onnxruntime-gpu -i https://mirror.baidu.com/pypi/simple
  1. 安装cudatoolkit,命令如下。
conda install cudatoolkit=11.3 cudnn --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/

人脸识别和人脸注册

为了方便,写一个类完成所有的识别流程,开始编写人脸识别和人脸注册工具类,使用insightface.app.FaceAnalysis()可以获取模型对象,这里包含了三个模型,首先是人脸检测模型,然后是人脸特征提取模型,和最后的性别年龄识别模型。使用model.prepare()可以配置ctx_id指定使用哪一块GPU,如果是负数则是使用CPU执行预测,det_thresh配置的是人脸检测的阈值。load_faces()函数是加载人脸库中的人脸,用于之后的人脸识别对比。

import os

import cv2
import insightface
import numpy as np
from sklearn import preprocessing


class FaceRecognition:
    def __init__(self, gpu_id=0, face_db='face_db', threshold=1.24, det_thresh=0.50, det_size=(640, 640)):
        """
        人脸识别工具类
        :param gpu_id: 正数为GPU的ID,负数为使用CPU
        :param face_db: 人脸库文件夹
        :param threshold: 人脸识别阈值
        :param det_thresh: 检测阈值
        :param det_size: 检测模型图片大小
        """
        self.gpu_id = gpu_id
        self.face_db = face_db
        self.threshold = threshold
        self.det_thresh = det_thresh
        self.det_size = det_size

        # 加载人脸识别模型,当allowed_modules=['detection', 'recognition']时,只单纯检测和识别
        self.model = insightface.app.FaceAnalysis(root='./',
                                                  allowed_modules=None,
                                                  providers=['CUDAExecutionProvider'])
        self.model.prepare(ctx_id=self.gpu_id, det_thresh=self.det_thresh, det_size=self.det_size)
        # 人脸库的人脸特征
        self.faces_embedding = list()
        # 加载人脸库中的人脸
        self.load_faces(self.face_db)

    # 加载人脸库中的人脸
    def load_faces(self, face_db_path):
        if not os.path.exists(face_db_path):
            os.makedirs(face_db_path)
        for root, dirs, files in os.walk(face_db_path):
            for file in files:
                input_image = cv2.imdecode(np.fromfile(os.path.join(root, file), dtype=np.uint8), 1)
                user_name = file.split(".")[0]
                face = self.model.get(input_image)[0]
                embedding = np.array(face.embedding).reshape((1, -1))
                embedding = preprocessing.normalize(embedding)
                self.faces_embedding.append({
                    "user_name": user_name,
                    "feature": embedding
                })

接下来编写recognition()函数实现人脸识别,首先获取每张人脸的特征embedding,其中使用人脸识别的就是通过欧氏距离来对比人脸库中的人脸特征,默认如何它们的欧氏距离小于1.24,我们就可以认为他们是同一个人。

def recognition(self, image):
        faces = self.model.get(image)
        results = list()
        for face in faces:
            # 开始人脸识别
            embedding = np.array(face.embedding).reshape((1, -1))
            embedding = preprocessing.normalize(embedding)
            user_name = "unknown"
            for com_face in self.faces_embedding:
                r = self.feature_compare(embedding, com_face["feature"], self.threshold)
                if r:
                    user_name = com_face["user_name"]
            results.append(user_name)
        return results

上面使用到的欧氏距离计算方式如下。

@staticmethod
    def feature_compare(feature1, feature2, threshold):
        diff = np.subtract(feature1, feature2)
        dist = np.sum(np.square(diff), 1)
        if dist < threshold:
            return True
        else:
            return False

人脸注册方式如下,通过传入一张照片,首先要判断照片中的人脸只有一张,然后开始提取该人脸的特征值,再次比较要注册的人脸是否已经存在人脸库中了,否之就包人脸特征添加到人脸库中并保存图片到本地。通过命名包只包含一个人脸的图片放在face_db文件夹中也可以实现。

def register(self, image, user_name):
        faces = self.model.get(image)
        if len(faces) != 1:
            return '图片检测不到人脸'
        # 判断人脸是否存在
        embedding = np.array(faces[0].embedding).reshape((1, -1))
        embedding = preprocessing.normalize(embedding)
        is_exits = False
        for com_face in self.faces_embedding:
            r = self.feature_compare(embedding, com_face["feature"], self.threshold)
            if r:
                is_exits = True
        if is_exits:
            return '该用户已存在'
        # 符合注册条件保存图片,同时把特征添加到人脸特征库中
        cv2.imencode('.png', image)[1].tofile(os.path.join(self.face_db, '%s.png' % user_name))
        self.faces_embedding.append({
            "user_name": user_name,
            "feature": embedding
        })
        return "success"

这里还提供了通用的人脸检测函数,通过调用detect()函数可以获取图像中每张人脸框坐标bbox,人脸五个关键点kps,人脸3D关键点landmark_3d_68,人脸2D关键点landmark_2d_106,人脸姿态pose,性别gender,年龄age,人脸特征embedding

def detect(self, image):
        faces = self.model.get(image)
        results = list()
        for face in faces:
            result = dict()
            # 获取人脸属性
            result["bbox"] = np.array(face.bbox).astype(np.int32).tolist()
            result["kps"] = np.array(face.kps).astype(np.int32).tolist()
            result["landmark_3d_68"] = np.array(face.landmark_3d_68).astype(np.int32).tolist()
            result["landmark_2d_106"] = np.array(face.landmark_2d_106).astype(np.int32).tolist()
            result["pose"] = np.array(face.pose).astype(np.int32).tolist()
            result["age"] = face.age
            gender = '男'
            if face.gender == 0:
                gender = '女'
            result["gender"] = gender
            # 开始人脸识别
            embedding = np.array(face.embedding).reshape((1, -1))
            embedding = preprocessing.normalize(embedding)
            result["embedding"] = embedding
            results.append(result)
        return results

使用

全部功能都实现了,使用如下,首先是进行人脸注册。

if __name__ == '__main__':
    img = cv2.imdecode(np.fromfile('迪丽热巴.jpg', dtype=np.uint8), -1)
    face_recognitio = FaceRecognition()
    # 人脸注册
    result = face_recognitio.register(img, user_name='迪丽热巴')
    print(result)

人脸识别,通过传入一张图片,可以输出每张人脸对应的用户名。

if __name__ == '__main__':
    img = cv2.imdecode(np.fromfile('迪丽热巴.jpg', dtype=np.uint8), -1)
    face_recognitio = FaceRecognition()
    results = face_recognitio.recognition(img)
    for result in results:
        print("识别结果:{}".format(result))

人脸通用检测,可以获取每张人脸的各种属性。

if __name__ == '__main__':
    img = cv2.imdecode(np.fromfile('迪丽热巴.jpg', dtype=np.uint8), -1)
    face_recognitio = FaceRecognition()

    results = face_recognitio.detect(img)
    for result in results:
        print('人脸框坐标:{}'.format(result["bbox"]))
        print('人脸五个关键点:{}'.format(result["kps"]))
        print('人脸3D关键点:{}'.format(result["landmark_3d_68"]))
        print('人脸2D关键点:{}'.format(result["landmark_2d_106"]))
        print('人脸姿态:{}'.format(result["pose"]))
        print('年龄:{}'.format(result["age"]))
        print('性别:{}'.format(result["gender"]))

全部代码

import os

import cv2
import insightface
import numpy as np
from sklearn import preprocessing


class FaceRecognition:
    def __init__(self, gpu_id=0, face_db='face_db', threshold=1.24, det_thresh=0.50, det_size=(640, 640)):
        """
        人脸识别工具类
        :param gpu_id: 正数为GPU的ID,负数为使用CPU
        :param face_db: 人脸库文件夹
        :param threshold: 人脸识别阈值
        :param det_thresh: 检测阈值
        :param det_size: 检测模型图片大小
        """
        self.gpu_id = gpu_id
        self.face_db = face_db
        self.threshold = threshold
        self.det_thresh = det_thresh
        self.det_size = det_size

        # 加载人脸识别模型,当allowed_modules=['detection', 'recognition']时,只单纯检测和识别
        self.model = insightface.app.FaceAnalysis(root='./',
                                                  allowed_modules=None,
                                                  providers=['CUDAExecutionProvider'])
        self.model.prepare(ctx_id=self.gpu_id, det_thresh=self.det_thresh, det_size=self.det_size)
        # 人脸库的人脸特征
        self.faces_embedding = list()
        # 加载人脸库中的人脸
        self.load_faces(self.face_db)

    # 加载人脸库中的人脸
    def load_faces(self, face_db_path):
        if not os.path.exists(face_db_path):
            os.makedirs(face_db_path)
        for root, dirs, files in os.walk(face_db_path):
            for file in files:
                input_image = cv2.imdecode(np.fromfile(os.path.join(root, file), dtype=np.uint8), 1)
                user_name = file.split(".")[0]
                face = self.model.get(input_image)[0]
                embedding = np.array(face.embedding).reshape((1, -1))
                embedding = preprocessing.normalize(embedding)
                self.faces_embedding.append({
                    "user_name": user_name,
                    "feature": embedding
                })

    # 人脸识别
    def recognition(self, image):
        faces = self.model.get(image)
        results = list()
        for face in faces:
            # 开始人脸识别
            embedding = np.array(face.embedding).reshape((1, -1))
            embedding = preprocessing.normalize(embedding)
            user_name = "unknown"
            for com_face in self.faces_embedding:
                r = self.feature_compare(embedding, com_face["feature"], self.threshold)
                if r:
                    user_name = com_face["user_name"]
            results.append(user_name)
        return results

    @staticmethod
    def feature_compare(feature1, feature2, threshold):
        diff = np.subtract(feature1, feature2)
        dist = np.sum(np.square(diff), 1)
        if dist < threshold:
            return True
        else:
            return False

    def register(self, image, user_name):
        faces = self.model.get(image)
        if len(faces) != 1:
            return '图片检测不到人脸'
        # 判断人脸是否存在
        embedding = np.array(faces[0].embedding).reshape((1, -1))
        embedding = preprocessing.normalize(embedding)
        is_exits = False
        for com_face in self.faces_embedding:
            r = self.feature_compare(embedding, com_face["feature"], self.threshold)
            if r:
                is_exits = True
        if is_exits:
            return '该用户已存在'
        # 符合注册条件保存图片,同时把特征添加到人脸特征库中
        cv2.imencode('.png', image)[1].tofile(os.path.join(self.face_db, '%s.png' % user_name))
        self.faces_embedding.append({
            "user_name": user_name,
            "feature": embedding
        })
        return "success"

    # 检测人脸
    def detect(self, image):
        faces = self.model.get(image)
        results = list()
        for face in faces:
            result = dict()
            # 获取人脸属性
            result["bbox"] = np.array(face.bbox).astype(np.int32).tolist()
            result["kps"] = np.array(face.kps).astype(np.int32).tolist()
            result["landmark_3d_68"] = np.array(face.landmark_3d_68).astype(np.int32).tolist()
            result["landmark_2d_106"] = np.array(face.landmark_2d_106).astype(np.int32).tolist()
            result["pose"] = np.array(face.pose).astype(np.int32).tolist()
            result["age"] = face.age
            gender = '男'
            if face.gender == 0:
                gender = '女'
            result["gender"] = gender
            # 开始人脸识别
            embedding = np.array(face.embedding).reshape((1, -1))
            embedding = preprocessing.normalize(embedding)
            result["embedding"] = embedding
            results.append(result)
        return results


if __name__ == '__main__':
    img = cv2.imdecode(np.fromfile('迪丽热巴.jpg', dtype=np.uint8), -1)
    face_recognitio = FaceRecognition()
    # 人脸注册
    result = face_recognitio.register(img, user_name='迪丽热巴')
    print(result)

    # 人脸识别
    results = face_recognitio.recognition(img)
    for result in results:
        print("识别结果:{}".format(result))

    results = face_recognitio.detect(img)
    for result in results:
        print('人脸框坐标:{}'.format(result["bbox"]))
        print('人脸五个关键点:{}'.format(result["kps"]))
        print('人脸3D关键点:{}'.format(result["landmark_3d_68"]))
        print('人脸2D关键点:{}'.format(result["landmark_2d_106"]))
        print('人脸姿态:{}'.format(result["pose"]))
        print('年龄:{}'.format(result["age"]))
        print('性别:{}'.format(result["gender"]))

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Insightface是一个基于MXNet的深度学习框架,专门用于人脸识别人脸分析任务。下面是使用Insightface进行人脸识别的步骤: 1. 安装Insightface包:可以使用pip install insightface来安装。 2. 准备人脸数据集:需要准备一个包含人脸图像和对应标签的数据集,可以使用自己的数据集或者使用公开数据集。 3. 加载预训练模型:Insightface提供了多个预训练模型,可以根据自己的需求选择相应的模型进行加载。 4. 进行人脸检测和对齐:使用Insightface提供的人脸检测和对齐函数,将输入图像中的人脸进行检测和对齐,生成对齐后的人脸图像。 5. 提取人脸特征:使用预训练模型提取对齐后的人脸图像的特征向量。 6. 进行人脸识别:将提取的特征向量与已知的人脸特征向量进行比对,计算相似度,从而进行人脸识别。 7. 输出识别结果:根据相似度大小,可以得出最终的识别结果,输出对应的标签或者人名。 可以使用以下代码实现基本的人脸识别功能: ``` import cv2 import numpy as np import insightface # 加载预训练模型 model = insightface.model_zoo.get_model('arcface_r100_v1') # 加载数据集 dataset = insightface.utils.face_dataset.load_facebank('./data') # 创建人脸检测器和对齐器 detector = insightface.model_zoo.get_model('retinaface_r50_v1') alignment = insightface.model_zoo.get_model('arcface_r100_v1') # 加载测试图像 img = cv2.imread('./test.jpg') # 进行人脸检测和对齐 faces = detector.detect(img) aligned = [] for face in faces: bbox, landmarks = face aligned_face = alignment.align(img, bbox, landmarks) aligned.append(aligned_face) # 提取特征向量 features = [] for face in aligned: feature = model.get_embedding(face) features.append(feature) # 进行人脸识别 similarities = [] for feature in features: similarity = [] for db_feature in dataset['feature']: score = np.dot(feature, db_feature) / (np.linalg.norm(feature) * np.linalg.norm(db_feature)) similarity.append(score) similarities.append(similarity) # 输出识别结果 for i, similarity in enumerate(similarities): max_index = np.argmax(similarity) max_score = similarity[max_index] if max_score > 0.8: print('Person %d: %s' % (i, dataset['name'][max_index])) else: print('Person %d: Unknown' % i) ``` 需要注意的是,以上代码仅为基本的人脸识别流程,并没有考虑实际应用中可能遇到的各种问题,如光照、姿态、遮挡等。在实际应用中需要根据具体需求进行相应的优化和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值