基于insightface模型实现人脸检测和比对的工作记录

300 阅读2分钟

研究了人脸识别,人脸识别分为人脸检测和人脸比对,模型选用insightface训练的模型

下载模型到本地使用,关于使用本地模型文件参考快速InsightFace和InsightFace Paddle学习与实践 - 知乎 (zhihu.com) 修改文件

work/insightface/python-package/insightface/app/face_analysis.py
work/insightface/python-package/insightface/app/mask_renderer.py
work/insightface/python-package/insightface/model_zoo/model_zoo.py

class FaceAnalysis:
    def __init__(self, name=DEFAULT_MP_NAME, root='~/work/.insightface', allowed_modules=None, **kwargs):

文件位置参考C:\Users\CT080120\work.insightface\models\buffalo_l.zip

检测和比对应用实现参考基于insightface实现的人脸识别和人脸注册-腾讯云开发者社区-腾讯云 (tencent.com)

pip install insightface
pip install onnxruntime

核心

import cv2

import numpy as np
from insightface.app import FaceAnalysis
from sklearn import preprocessing

def det(src):
    app = FaceAnalysis('buffalo_l', allowed_modules=['detection'])
    app.prepare(ctx_id=-1, det_size=(640, 640))
    img = cv2.imread(src)
    faces = app.get(img)
    rimg = app.draw_on(img, faces)
    cv2.imwrite("./t1_output.jpg", rimg)
    return faces


def reco():
    app = FaceAnalysis('buffalo_l', allowed_modules=['detection', 'recognition'])
    app.prepare(ctx_id=-1, det_size=(640, 640))
    img = cv2.imread("./hezhao.png")
    faces = app.get(img)

    results = list()
    for face in faces:
        result = dict()
        # 获取人脸属性
        result["bbox"] = np.array(face.bbox).astype(np.int32).tolist()
        # 开始人脸识别
        embedding = np.array(face.embedding).reshape((1, -1))
        embedding = preprocessing.normalize(embedding)
        results.append(result)


if __name__ == '__main__':
    det("./danren.png")
    # reco()

完整 FaceRecognition.py

import os
from random import choice

import cv2
import insightface

import numpy as np
from sklearn import preprocessing

from DeployConfig import DeployConfig


class FaceRecognition:
    def __init__(self, conf_file):
        self.config = DeployConfig(conf_file)
        # 加载人脸识别模型
        self.model = insightface.app.FaceAnalysis('buffalo_l', allowed_modules=['detection', 'recognition'])
        self.model.prepare(ctx_id=self.config.gpu_id, det_thresh=self.config.nms)
        # 人脸库的人脸特征
        self.faces_embedding = list()
        # 加载人脸库中的人脸
        self.load_faces(self.config.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_id = 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_id": user_id,
                    "feature": embedding
                })

    @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):
        faces = self.model.get(image)
        if len(faces) != 1:
            return None
        # 判断人脸是否存在
        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.config.threshold)
            if r:
                is_exits = True
        if is_exits:
            return None
        old_user_id = [d["user_id"] for d in self.faces_embedding]
        user_id = self.get_user_id(old_user_id)
        # 符合注册条件保存图片,同时把特征添加到人脸特征库中
        cv2.imencode('.png', image)[1].tofile(os.path.join(self.config.face_db, '%s.png' % user_id))
        self.faces_embedding.append({
            "user_id": user_id,
            "feature": embedding
        })
        return user_id

    def get_user_id(self, old_user_id):
        print(old_user_id)
        while True:
            user_id = "".join([choice("0123456789ABCDEF") for i in range(8)])
            if user_id not in old_user_id:
                break
        return user_id

    def recognition(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()
            # 开始人脸识别
            embedding = np.array(face.embedding).reshape((1, -1))
            embedding = preprocessing.normalize(embedding)
            result["user_id"] = "unknown"
            for com_face in self.faces_embedding:
                r = self.feature_compare(embedding, com_face["feature"], self.config.threshold)
                if r:
                    result["user_id"] = com_face["user_id"]
            results.append(result)
        return results


if __name__ == '__main__':
    img = cv2.imread("danren.png")
    img2 = cv2.imread("hezhao.png")

    face_recognition = FaceRecognition("config.yaml")
    user_id = face_recognition.recognition(img2)
    print(user_id)

DeployConfig.py

import os
import yaml


# Deploy Configuration File Parser
class DeployConfig:
    def __init__(self, conf_file):
        if not os.path.exists(conf_file):
            raise Exception('Config file path [%s] invalid!' % conf_file)

        with open(conf_file) as fp:
            configs = yaml.load(fp, Loader=yaml.FullLoader)
            deploy_conf = configs["FACE"]
            # 正数为GPU的ID,负数为使用CPU
            self.gpu_id = deploy_conf["GPU_ID"]
            self.face_db = deploy_conf["FACE_DB"]
            self.threshold = deploy_conf["THRESHOLD"]
            self.nms = deploy_conf["NMS"]

config.yaml

FACE:
  GPU_ID: -1
  FACE_DB: "face_db"
  THRESHOLD: 1.24
  NMS: 0.50