python 人脸识别项目insightface

一、项目简介

InsightFace是一个用于2D和3D人脸分析的集成Python库。 InsightFace 有效地实现了各种最先进的人脸识别、人脸检测和人脸对齐算法,并针对训练和部署进行了优化。

项目地址:https://github.com/deepinsight/insightface

 截止本博文发布日,项目Star数达20k。

二、项目安装

环境:ubuntu18 cuda11.7

1、安装insightface

pip install insightface

2、安装onnxruntime

GPU:

pip install onnxruntime-gpu

CPU:

pip install onnxruntime

三、项目运行

1、官方示例

import cv2
import numpy as np
import insightface
from insightface.app import FaceAnalysis
from insightface.data import get_image as ins_get_image
 
app = FaceAnalysis(root='./',allowed_modules=['detection'],providers=['CUDAExecutionProvider', 'CPUExecutionProvider'],download=False)
app.prepare(ctx_id=0, det_size=(640, 640))
img = ins_get_image('t1')  #不用带后缀,图片放到./insightface/python-package/insightface/data/images
faces = app.get(img)
print("faces::::", faces)
print("len:", len(faces))
rimg = app.draw_on(img, faces)
cv2.imwrite("./ldh_out put.jpg", rimg)
cv2.imshow("frame", rimg)
if cv2.waitKey(0) & 0xFF == ord('Q'):
    cv2.destroyAllWindows()

运行后,会自动从github下载模型到当前项目models目录下,也可以手动下载,放置models目录

其中包含了检测人脸特征landmark、检测人脸、检测性别年龄、检测人脸特征embedding等模型。

运行结果:

 2、人脸识别demo

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

博主已经写的很详细了,而且可以拿来直接用,已测试。 

3、从摄像头获取视频进行人脸识别

import os
 
import cv2
import insightface
import numpy as np
from sklearn import preprocessing
import time
import uuid
 
class FaceRecognition:
    def __init__(self, gpu_id=0, face_db='face_db', threshold=1.24, det_thresh=0.7, 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
                })
 
    # 人脸识别
    # 通过欧氏距离来对比人脸库中的人脸特征,默认如何它们的欧氏距离小于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)
            face_info = {}
            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"]
            face_info["user_name"] = user_name
            # 获取人脸属性
            face_info["bbox"] = np.array(face.bbox).astype(np.int32).tolist()
            results.append(face_info)
        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 face_recognitio_webcam():
    # 获取视频流
    video_capture = cv2.VideoCapture("rtsp://admin:mima@192.168.*.*/h264/ch1/main/av_stream")
    # 加载人脸库
    face_recognitio = FaceRecognition(face_db='known_people')
    dump_frame = 5  # 跳4帧
    count_frame = 1
    while True:
        # 抓取一帧视频
        ret, frame = video_capture.read()
        count_frame += 1
        if count_frame % dump_frame != 0:
            pass
        else:
            # 人脸识别
            #beginTime = time.time()
            results = face_recognitio.recognition(frame)
            for face_info in results:
                name = face_info['user_name']
                print(f"识别结果:{name}")
                top = face_info['bbox'][1]
                right = face_info['bbox'][2]
                bottom = face_info['bbox'][3]
                left = face_info['bbox'][0]
                pic_name = "face_imgs/"+ name + str(uuid.uuid1()) +".jpg"
                
                # 在脸周围画一个框
                cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
                # 在脸下面画一个带名字的标签
                cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
                font = cv2.FONT_HERSHEY_DUPLEX
                cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
                cv2.imwrite(pic_name, frame)  # 并把图片保存到路径的文件夹
                print('save face pic :',pic_name)
                
            #print(f'face_recognitio Done. ({time.time() - beginTime:.3f}s)') # 打印时间
        cv2.imshow('Video', cv2.resize(frame,(1280,720)))
        # Hit 'q' on the keyboard to quit!
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
 
if __name__ == '__main__':
    face_recognitio_webcam()

四、项目运行中问题记录

警告:

/home/ubuntu/anaconda3/envs/pytorch/lib/python3.8/site-packages/insightface/utils/transform.py:68: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
  P = np.linalg.lstsq(X_homo, Y)[0].T # Affine matrix. 3 x 4

解决:定位到该代码段,改为 P = np.linalg.lstsq(X_homo, Y,rcond=None)[0].T 或者 P = np.linalg.lstsq(X_homo, Y,rcond=-1)[0].T。