Spaces:
Running
Running
import cv2 | |
import numpy as np | |
from insightface.utils import face_align | |
from face_parsing.swap import swap_regions | |
from utils import add_logo_to_image | |
swap_options_list = [ | |
"All face", | |
"Age less than", | |
"Age greater than", | |
"All Male", | |
"All Female", | |
"Specific Face", | |
] | |
def swap_face(whole_img, target_face, source_face, models): | |
inswapper = models.get("swap") | |
face_enhancer = models.get("enhance", None) | |
face_parser = models.get("face_parser", None) | |
fe_enable = models.get("enhance_sett", False) | |
bgr_fake, M = inswapper.get(whole_img, target_face, source_face, paste_back=False) | |
image_size = 128 if not fe_enable else 512 | |
aimg, _ = face_align.norm_crop2(whole_img, target_face.kps, image_size=image_size) | |
if face_parser is not None: | |
fp_enable, includes, smooth_mask, blur_amount = models.get("face_parser_sett") | |
if fp_enable: | |
bgr_fake = swap_regions( | |
bgr_fake, aimg, face_parser, smooth_mask, includes=includes, blur=blur_amount | |
) | |
if fe_enable: | |
_, bgr_fake, _ = face_enhancer.enhance( | |
bgr_fake, paste_back=True, has_aligned=True | |
) | |
bgr_fake = bgr_fake[0] | |
M /= 0.25 | |
IM = cv2.invertAffineTransform(M) | |
img_white = np.full((aimg.shape[0], aimg.shape[1]), 255, dtype=np.float32) | |
bgr_fake = cv2.warpAffine( | |
bgr_fake, IM, (whole_img.shape[1], whole_img.shape[0]), borderValue=0.0 | |
) | |
img_white = cv2.warpAffine( | |
img_white, IM, (whole_img.shape[1], whole_img.shape[0]), borderValue=0.0 | |
) | |
img_white[img_white > 20] = 255 | |
img_mask = img_white | |
mask_h_inds, mask_w_inds = np.where(img_mask == 255) | |
mask_h = np.max(mask_h_inds) - np.min(mask_h_inds) | |
mask_w = np.max(mask_w_inds) - np.min(mask_w_inds) | |
mask_size = int(np.sqrt(mask_h * mask_w)) | |
k = max(mask_size // 10, 10) | |
img_mask = cv2.erode(img_mask, np.ones((k, k), np.uint8), iterations=1) | |
k = max(mask_size // 20, 5) | |
kernel_size = (k, k) | |
blur_size = tuple(2 * i + 1 for i in kernel_size) | |
img_mask = cv2.GaussianBlur(img_mask, blur_size, 0) / 255 | |
img_mask = np.reshape(img_mask, [img_mask.shape[0], img_mask.shape[1], 1]) | |
fake_merged = img_mask * bgr_fake + (1 - img_mask) * whole_img.astype(np.float32) | |
fake_merged = add_logo_to_image(fake_merged.astype("uint8")) | |
return fake_merged | |
def swap_face_with_condition( | |
whole_img, target_faces, source_face, condition, age, models | |
): | |
swapped = whole_img.copy() | |
for target_face in target_faces: | |
if condition == "All face": | |
swapped = swap_face(swapped, target_face, source_face, models) | |
elif condition == "Age less than" and target_face["age"] < age: | |
swapped = swap_face(swapped, target_face, source_face, models) | |
elif condition == "Age greater than" and target_face["age"] > age: | |
swapped = swap_face(swapped, target_face, source_face, models) | |
elif condition == "All Male" and target_face["gender"] == 1: | |
swapped = swap_face(swapped, target_face, source_face, models) | |
elif condition == "All Female" and target_face["gender"] == 0: | |
swapped = swap_face(swapped, target_face, source_face, models) | |
return swapped | |
def swap_specific(source_specifics, target_faces, whole_img, models, threshold=0.6): | |
swapped = whole_img.copy() | |
for source_face, specific_face in source_specifics: | |
specific_embed = specific_face["embedding"] | |
specific_embed /= np.linalg.norm(specific_embed) | |
for target_face in target_faces: | |
target_embed = target_face["embedding"] | |
target_embed /= np.linalg.norm(target_embed) | |
cosine_distance = 1 - np.dot(specific_embed, target_embed) | |
if cosine_distance > threshold: | |
continue | |
swapped = swap_face(swapped, target_face, source_face, models) | |
return swapped | |