ViralCutterPRO / scripts /one_face.py
RafaG's picture
Upload 24 files
1496c35 verified
import cv2
import numpy as np
import os
import subprocess
import mediapipe as mp
def crop_and_resize_single_face(frame, face):
frame_height, frame_width = frame.shape[:2]
x, y, w, h = face
face_center_x = x + w // 2
face_center_y = y + h // 2
# Cálculo da proporção desejada (9:16)
target_aspect_ratio = 9 / 16
# Cálculo da área de corte para evitar barras pretas
if frame_width / frame_height > target_aspect_ratio:
new_width = int(frame_height * target_aspect_ratio)
new_height = frame_height
else:
new_width = frame_width
new_height = int(frame_width / target_aspect_ratio)
# Garantir que o corte esteja dentro dos limites
crop_x = max(0, min(face_center_x - new_width // 2, frame_width - new_width))
crop_y = max(0, min(face_center_y - new_height // 2, frame_height - new_height))
crop_x2 = crop_x + new_width
crop_y2 = crop_y + new_height
# Recorte e redimensionamento para 1080x1920 (9:16)
crop_img = frame[crop_y:crop_y2, crop_x:crop_x2]
resized = cv2.resize(crop_img, (1080, 1920), interpolation=cv2.INTER_AREA)
return resized
def resize_with_padding(frame):
frame_height, frame_width = frame.shape[:2]
target_aspect_ratio = 9 / 16
if frame_width / frame_height > target_aspect_ratio:
new_width = frame_width
new_height = int(frame_width / target_aspect_ratio)
else:
new_height = frame_height
new_width = int(frame_height * target_aspect_ratio)
# Criação de uma tela preta
result = np.zeros((new_height, new_width, 3), dtype=np.uint8)
# Cálculo das margens
pad_top = (new_height - frame_height) // 2
pad_left = (new_width - frame_width) // 2
# Colocar o frame original na tela
result[pad_top:pad_top+frame_height, pad_left:pad_left+frame_width] = frame
# Redimensionar para as dimensões finais
return cv2.resize(result, (1080, 1920), interpolation=cv2.INTER_AREA)
def detect_face_or_body(frame, face_detection, face_mesh, pose):
# Converter a imagem para RGB
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Processar a detecção de rosto
results_face_detection = face_detection.process(frame_rgb)
results_face_mesh = face_mesh.process(frame_rgb)
results_pose = pose.process(frame_rgb)
detections = []
# Usar a detecção de rosto se disponível
if results_face_detection.detections:
# Usar o primeiro rosto detectado
detection = results_face_detection.detections[0]
bbox = detection.location_data.relative_bounding_box
x_min = int(bbox.xmin * frame.shape[1])
y_min = int(bbox.ymin * frame.shape[0])
width = int(bbox.width * frame.shape[1])
height = int(bbox.height * frame.shape[0])
detections.append((x_min, y_min, width, height))
# Usar landmarks do face mesh se disponível
if results_face_mesh.multi_face_landmarks:
landmarks = results_face_mesh.multi_face_landmarks[0].landmark
# Coordenadas do rosto baseadas nos pontos-chave (landmarks)
x_coords = [int(landmark.x * frame.shape[1]) for landmark in landmarks]
y_coords = [int(landmark.y * frame.shape[0]) for landmark in landmarks]
x_min, x_max = min(x_coords), max(x_coords)
y_min, y_max = min(y_coords), max(y_coords)
width = x_max - x_min
height = y_max - y_min
detections.append((x_min, y_min, width, height))
# Se nenhum rosto for detectado, usar a pose para estimar o corpo
if results_pose.pose_landmarks:
x_coords = [lmk.x for lmk in results_pose.pose_landmarks.landmark]
y_coords = [lmk.y for lmk in results_pose.pose_landmarks.landmark]
x_min = int(min(x_coords) * frame.shape[1])
x_max = int(max(x_coords) * frame.shape[1])
y_min = int(min(y_coords) * frame.shape[0])
y_max = int(max(y_coords) * frame.shape[0])
width = x_max - x_min
height = y_max - y_min
detections.append((x_min, y_min, width, height))
# Se nada for detectado, retornar uma lista vazia
return detections if detections else None
def crop_center_zoom(frame):
"""
Crops the center of the frame to fill 9:16 aspect ratio (Zoom effect).
"""
frame_height, frame_width = frame.shape[:2]
target_aspect_ratio = 9 / 16
# Calculate crop dimensions to FILL the target ratio
if frame_width / frame_height > target_aspect_ratio:
# Source is wider than target (e.g. 16:9 source, 9:16 target) -> Crop Width
new_width = int(frame_height * target_aspect_ratio)
new_height = frame_height
else:
# Source is taller than target -> Crop Height
new_width = frame_width
new_height = int(frame_width / target_aspect_ratio)
start_x = (frame_width - new_width) // 2
start_y = (frame_height - new_height) // 2
# Ensure bounds
start_x = max(0, start_x)
start_y = max(0, start_y)
crop_img = frame[start_y:start_y+new_height, start_x:start_x+new_width]
# Resize to final 1080x1920
return cv2.resize(crop_img, (1080, 1920), interpolation=cv2.INTER_AREA)