from insightface.app import FaceAnalysis import numpy as np import torch INSIGHTFACE_DETECT_SIZE = 512 class FaceDetector: def __init__(self, device="cuda"): self.app = FaceAnalysis( allowed_modules=["detection", "landmark_2d_106"], root="checkpoints/auxiliary", providers=["CUDAExecutionProvider"], ) self.app.prepare(ctx_id=cuda_to_int(device), det_size=(INSIGHTFACE_DETECT_SIZE, INSIGHTFACE_DETECT_SIZE)) def __call__(self, frame, threshold=0.5): f_h, f_w, _ = frame.shape faces = self.app.get(frame) get_face_store = None max_size = 0 if len(faces) == 0: return None, None else: for face in faces: bbox = face.bbox.astype(np.int_).tolist() w, h = bbox[2] - bbox[0], bbox[3] - bbox[1] if w < 50 or h < 80: continue if w / h > 1.5 or w / h < 0.2: continue if face.det_score < threshold: continue size_now = w * h if size_now > max_size: max_size = size_now get_face_store = face if get_face_store is None: return None, None else: face = get_face_store lmk = np.round(face.landmark_2d_106).astype(np.int_) halk_face_coord = np.mean([lmk[74], lmk[73]], axis=0) # lmk[73] sub_lmk = lmk[LMK_ADAPT_ORIGIN_ORDER] halk_face_dist = np.max(sub_lmk[:, 1]) - halk_face_coord[1] upper_bond = halk_face_coord[1] - halk_face_dist # *0.94 x1, y1, x2, y2 = (np.min(sub_lmk[:, 0]), int(upper_bond), np.max(sub_lmk[:, 0]), np.max(sub_lmk[:, 1])) if y2 - y1 <= 0 or x2 - x1 <= 0 or x1 < 0: x1, y1, x2, y2 = face.bbox.astype(np.int_).tolist() y2 += int((x2 - x1) * 0.1) x1 -= int((x2 - x1) * 0.05) x2 += int((x2 - x1) * 0.05) x1 = max(0, x1) y1 = max(0, y1) x2 = min(f_w, x2) y2 = min(f_h, y2) return (x1, y1, x2, y2), lmk def cuda_to_int(cuda_str: str) -> int: """ Convert the string with format "cuda:X" to integer X. """ if cuda_str == "cuda": return 0 device = torch.device(cuda_str) if device.type != "cuda": raise ValueError(f"Device type must be 'cuda', got: {device.type}") return device.index LMK_ADAPT_ORIGIN_ORDER = [ 1, 10, 12, 14, 16, 3, 5, 7, 0, 23, 21, 19, 32, 30, 28, 26, 17, 43, 48, 49, 51, 50, 102, 103, 104, 105, 101, 73, 74, 86, ]