You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MediaPipe人脸检测后,如何实现人脸识别及特征匹配?

解决方案:人脸特征匹配与跨库结合实现人脸识别

一、基于MediaPipe Face Mesh特征的匹配方案

你当前保存的是单用户50帧的人脸关键点(landmarks),直接用单帧特征与50个样本匹配会存在误差,优化步骤如下:

  1. 预存特征预处理
    采集完成后,对该用户的50组landmarks取均值,得到该用户的基准特征向量(将三维关键点扁平化成长一维数组),替换原有的保存方式,以此降低单帧波动带来的匹配误差。

  2. 实时特征匹配逻辑
    实时流中提取当前人脸的Face Mesh特征,同样扁平化后,与所有预存的用户基准特征计算相似度:

    • 欧氏距离:距离越小,特征相似度越高,可设置阈值(如0.05,需根据实际测试调整)
    • 余弦相似度:值越接近1,特征相似度越高,阈值可设为0.95左右
  3. 代码修改示例
    修改capture_faces函数中保存特征的部分:

    # 将人脸关键点保存为子文件夹中的pickle文件(改为保存平均特征)
    import numpy as np
    avg_landmarks = np.mean(face_landmarks_list, axis=0).flatten()  # 扁平化为一维数组
    pickle_file_path = os.path.join(save_path, f"{name}_avg_landmarks.pkl")
    with open(pickle_file_path, "wb") as f:
        pickle.dump({"name": name, "avg_landmarks": avg_landmarks}, f)
    

    在实时流循环中添加匹配逻辑:

    # 加载所有预存用户的平均特征
    def load_all_user_features():
        user_features = []
        for root, dirs, files in os.walk(SAVE_DIR):
            for file in files:
                if file.endswith("_avg_landmarks.pkl"):
                    with open(os.path.join(root, file), "rb") as f:
                        data = pickle.load(f)
                        user_features.append(data)
        return user_features
    
    # 初始化时加载特征
    user_features = load_all_user_features()
    
    # 实时匹配函数
    def match_face(current_landmarks, user_features, threshold=0.05):
        current_flat = np.array(current_landmarks).flatten()
        min_dist = float('inf')
        matched_name = "未知人员"
        for user in user_features:
            dist = np.linalg.norm(current_flat - user["avg_landmarks"])
            if dist < min_dist and dist < threshold:
                min_dist = dist
                matched_name = user["name"]
        return matched_name
    
    # 在实时流的人脸检测部分添加匹配
    if results.detections:
        for detection in results.detections:
            # ... 原有的bbox计算代码 ...
            # 裁剪人脸区域
            face_frame = frame[ymin:ymin + height, xmin:xmin + width]
            frame_rgb_face = cv2.cvtColor(face_frame, cv2.COLOR_BGR2RGB)
            # 提取实时Face Mesh特征
            with mp_face_mesh.FaceMesh(static_image_mode=True, max_num_faces=1, min_detection_confidence=0.5) as face_mesh:
                mesh_results = face_mesh.process(frame_rgb_face)
                if mesh_results.multi_face_landmarks:
                    landmarks = [list((lm.x, lm.y, lm.z)) for lm in mesh_results.multi_face_landmarks[0].landmark]
                    matched_name = match_face(landmarks, user_features)
                else:
                    matched_name = "未知人员"
            # 绘制文字
            cv2.putText(frame, matched_name, (xmin, ymin - 10), font, 0.9, (0, 0, 255) if matched_name == "未知人员" else (0, 255, 0), 2, cv2.LINE_AA)
    

二、结合DeepFace/OpenCV实现更高准确率的人脸识别

MediaPipe的Face Mesh特征更偏向人脸姿态分析,并非专门为识别优化,结合DeepFace或OpenCV能获得更好的识别效果:

1. 结合DeepFace方案

DeepFace封装了多个预训练人脸识别模型(如VGG-Face、Facenet),可以用MediaPipe做实时人脸检测,裁剪出人脸后交给DeepFace提取特征并匹配:

  • 安装DeepFace:pip install deepface
  • 修改代码逻辑:
    from deepface import DeepFace
    
    # 采集时为用户生成DeepFace基准特征
    def save_deepface_features(name, save_path):
        # 取该用户的一张清晰人脸图像(比如第25帧)
        sample_img_path = os.path.join(save_path, "face_24.jpg")
        # 提取特征
        embedding = DeepFace.represent(img_path=sample_img_path, model_name="Facenet")[0]["embedding"]
        # 保存特征
        with open(os.path.join(save_path, f"{name}_deepface_embedding.pkl"), "wb") as f:
            pickle.dump({"name": name, "embedding": embedding}, f)
    
    # 在capture_faces函数末尾调用
    save_deepface_features(name, save_path)
    
    # 实时匹配
    def match_deepface(current_face_img, user_features, threshold=0.6):
        current_embedding = DeepFace.represent(img_path=current_face_img, model_name="Facenet")[0]["embedding"]
        min_dist = float('inf')
        matched_name = "未知人员"
        for user in user_features:
            dist = np.linalg.norm(np.array(current_embedding) - np.array(user["embedding"]))
            if dist < min_dist and dist < threshold:
                min_dist = dist
                matched_name = user["name"]
        return matched_name
    
    # 实时流中使用
    # 裁剪得到face_frame后,直接传入匹配函数
    matched_name = match_deepface(face_frame, deepface_user_features)
    

2. 结合OpenCV人脸识别方案

OpenCV提供了LBPH、EigenFace、FisherFace三种人脸识别器,适合轻量场景:

  • 训练阶段:收集用户人脸图像,用cv2.face.LBPHFaceRecognizer_create()训练模型
  • 实时阶段:检测人脸后,将裁剪区域转为灰度图,输入模型预测

三、注意事项

  • 阈值需要根据实际场景测试调整,不同光线、姿态下阈值可能不同
  • 实时匹配时,建议每N帧做一次匹配(比如每5帧),减少计算开销
  • 若用户数量较多,可以考虑用KNN或聚类算法优化匹配速度

内容的提问来源于stack exchange,提问作者Chamod Abeyrathne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:32:31