import torch from typing import Optional, List import numpy from insightface.app import FaceAnalysis from insightface.app.common import Face import numpy as np SIMILAR_FACE_DISTANCE: float = 0.45 # < 0.4 同一人 0.4 -0.6 大概是同一人 >0.6 不是同一个 class FaceAnalyser: def __init__(self): self.device = self._select_device() self._analyser = FaceAnalysis(name='buffalo_l', root='./', providers=['CUDAExecutionProvider' if self.device == 'cuda' else 'CPUExecutionProvider']) self._analyser.prepare(ctx_id=0, det_size=(640, 640)) def _select_device(self): if torch.cuda.is_available(): return 'cuda' elif torch.backends.mps.is_available(): return 'mps' else: return 'cpu' def get_many_faces(self,frame: np.ndarray) -> Optional[List[Face]]: try: return self._analyser.get(frame) except Exception as e: print(f"{e}") return None def get_one_face(self,frame: np.ndarray, position: int = 0) -> Optional[Face]: many_faces = self.get_many_faces(frame) if many_faces: try: return many_faces[position] except IndexError: return many_faces[-1] return None def find_similar_face(self,frame: np.ndarray, reference_face: Face) -> Optional[Face]: many_faces = self.get_many_faces(frame) if many_faces: for face in many_faces: if hasattr(face, 'normed_embedding') and hasattr(reference_face, 'normed_embedding'): distance = numpy.sum(numpy.square(face.normed_embedding - reference_face.normed_embedding)) if distance < SIMILAR_FACE_DISTANCE: return face return None