import cv2 import numpy as np import os import sys from contextlib import contextmanager import warnings # Suppress warnings warnings.filterwarnings("ignore") try: from insightface.app import FaceAnalysis INSIGHTFACE_AVAILABLE = True except ImportError: INSIGHTFACE_AVAILABLE = False app = None @contextmanager def suppress_stdout_stderr(): """A context manager that redirects stdout and stderr to devnull""" with open(os.devnull, "w") as devnull: old_stdout = sys.stdout old_stderr = sys.stderr sys.stdout = devnull sys.stderr = devnull try: yield finally: sys.stdout = old_stdout sys.stderr = old_stderr def init_insightface(): """Explicit initialization if needed outside import.""" global app if not INSIGHTFACE_AVAILABLE: raise ImportError("InsightFace not installed. Please install it.") if app is None: # Provider options to reduce logging if possible (often needs env var) # But redirection is safer for C++ logs providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] try: import onnxruntime as ort available = ort.get_available_providers() print(f"InsightFace: Available ONNX Providers: {available}") if 'CUDAExecutionProvider' not in available: print("WARNING: CUDAExecutionProvider not found. InsightFace will likely run on CPU.") print("To fix, install onnxruntime-gpu: pip install onnxruntime-gpu") except Exception as e: print(f"InsightFace: Could not check available providers: {e}") with suppress_stdout_stderr(): app = FaceAnalysis(name='buffalo_l', providers=providers) app.prepare(ctx_id=0, det_size=(640, 640)) return app def detect_faces_insightface(frame): """ Detect faces using InsightFace. Returns a list of dicts with 'bbox' and 'kps'. bbox is [x1, y1, x2, y2], kps is 5 keypoints (eyes, nose, mouth corners). """ global app if app is None: init_insightface() faces = app.get(frame) results = [] for face in faces: # Convert bbox to int bbox = face.bbox.astype(int) res = { 'bbox': bbox, # [x1, y1, x2, y2] 'kps': face.kps, 'det_score': face.det_score } if hasattr(face, 'landmark_2d_106') and face.landmark_2d_106 is not None: res['landmark_2d_106'] = face.landmark_2d_106 if hasattr(face, 'landmark_3d_68') and face.landmark_3d_68 is not None: res['landmark_3d_68'] = face.landmark_3d_68 results.append(res) return results def crop_and_resize_insightface(frame, face_bbox, target_width=1080, target_height=1920): """ Crops and resizes the frame to target dimensions centered on the face_bbox. face_bbox: [x1, y1, x2, y2] """ h, w, _ = frame.shape x1, y1, x2, y2 = face_bbox face_center_x = (x1 + x2) // 2 face_center_y = (y1 + y2) // 2 # Calculate crop area based on target aspect ratio and face position # We want to keep the face roughly in the upper-middle or center? # Usually center for simple implementation, or slightly upper for "talking head". # Logic similar to one_face.py but adapted # Determine the scaling factor to ensure the crop covers the target height # Ideally we want the height of the video to match the target height after resize # But usually we source from landscape (16:9) to portrait (9:16). # We need to crop a 9:16 area from the source. # Calculate source crop height/width maintaining 9:16 ratio # Trying to maximize height usage of the source frame usually. # Let's say we want to use the full height of the source if possible source_h = h source_w = int(source_h * (target_width / target_height)) if source_w > w: # If the calculated width is wider than the source image, we are limited by width source_w = w source_h = int(source_w * (target_height / target_width)) # Calculate top-left corner of the crop crop_x1 = face_center_x - (source_w // 2) crop_y1 = face_center_y - (source_h // 2) # Center vertically on face # Adjust to stay within bounds if crop_x1 < 0: crop_x1 = 0 elif crop_x1 + source_w > w: crop_x1 = w - source_w if crop_y1 < 0: crop_y1 = 0 elif crop_y1 + source_h > h: crop_y1 = h - source_h crop_x2 = crop_x1 + source_w crop_y2 = crop_y1 + source_h # Crop cropped = frame[crop_y1:crop_y2, crop_x1:crop_x2] # Resize to final target result = cv2.resize(cropped, (target_width, target_height), interpolation=cv2.INTER_LINEAR) return result if __name__ == "__main__": # Test block print("Testing InsightFace...") # Create a dummy image or try to load one if available, but for now just print config print("InsightFace initialized.")