import os import numpy as np import cv2 from PIL import Image # 确保正确导入Image类 from insightface.app import FaceAnalysis # 导入获取人脸信息的服务 from service.face_service import get_all_face_name_with_eigenvalue # 全局变量 _face_app = None _known_faces_embeddings = {} # 存储姓名到特征值的映射 _known_faces_names = [] # 存储所有已知姓名 def load_model(): """加载人脸识别模型及已知人脸特征库""" global _face_app, _known_faces_embeddings, _known_faces_names # 初始化InsightFace模型 try: _face_app = FaceAnalysis(name='buffalo_l', root=os.path.expanduser('~/.insightface')) _face_app.prepare(ctx_id=0, det_size=(640, 640)) except Exception as e: print(f"Face model load failed: {e}") return False # 从服务获取所有人脸姓名和特征值 try: face_data = get_all_face_name_with_eigenvalue() # 处理获取到的人脸数据 for person_name, eigenvalue_data in face_data.items(): # 处理特征值数据 - 兼容数组和字符串两种格式 if isinstance(eigenvalue_data, np.ndarray): # 如果已经是numpy数组,直接使用 eigenvalue = eigenvalue_data.astype(np.float32) elif isinstance(eigenvalue_data, str): # 清理字符串:移除方括号、换行符和多余空格 cleaned = eigenvalue_data.replace('[', '').replace(']', '').replace('\n', '').strip() # 按空格或逗号分割(处理可能的不同分隔符) values = [v for v in cleaned.split() if v] # 转换为数组 eigenvalue = np.array(list(map(float, values)), dtype=np.float32) else: # 不支持的类型 print(f"Unsupported eigenvalue type for {person_name}") continue # 归一化处理 norm = np.linalg.norm(eigenvalue) if norm != 0: eigenvalue = eigenvalue / norm _known_faces_embeddings[person_name] = eigenvalue _known_faces_names.append(person_name) except Exception as e: print(f"Error loading face data from service: {e}") return True if _face_app else False def detect(frame, threshold=0.4): """检测并识别人脸,返回结果元组(是否匹配到已知人脸, 结果字符串)""" global _face_app, _known_faces_embeddings, _known_faces_names if not _face_app or not _known_faces_names or frame is None: return (False, "未初始化或无效帧") try: faces = _face_app.get(frame) except Exception as e: print(f"Face detect error: {e}") return (False, f"检测错误: {str(e)}") result_parts = [] has_matched = False # 新增标记:是否有匹配到的已知人脸 for face in faces: # 特征归一化 embedding = face.embedding.astype(np.float32) norm = np.linalg.norm(embedding) if norm == 0: continue embedding = embedding / norm # 对比已知人脸 max_sim, best_name = -1.0, "Unknown" for name in _known_faces_names: known_emb = _known_faces_embeddings[name] sim = np.dot(embedding, known_emb) if sim > max_sim: max_sim = sim best_name = name # 判断匹配结果 is_match = max_sim >= threshold if is_match: has_matched = True # 只要有一个匹配成功,就标记为True bbox = face.bbox result_parts.append( f"{'匹配' if is_match else '不匹配'}: {best_name} (相似度: {max_sim:.2f}, 边界框: {bbox})" ) # 构建结果字符串 if not result_parts: result_str = "未检测到人脸" else: result_str = "; ".join(result_parts) # 第一个返回值改为:是否匹配到已知人脸 return (has_matched, result_str)