From d1e8fbab08fd41e59eeec30e8caa09992f09c557 Mon Sep 17 00:00:00 2001 From: harisreedhar Date: Mon, 16 Jun 2025 20:02:59 +0530 Subject: [PATCH] optimized pasteback --- facefusion/face_helper.py | 41 ++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/facefusion/face_helper.py b/facefusion/face_helper.py index 7db967a..9a48fc9 100644 --- a/facefusion/face_helper.py +++ b/facefusion/face_helper.py @@ -98,16 +98,39 @@ def warp_face_by_translation(temp_vision_frame : VisionFrame, translation : Tran return crop_vision_frame, affine_matrix -def paste_back(temp_vision_frame : VisionFrame, crop_vision_frame : VisionFrame, crop_mask : Mask, affine_matrix : Matrix) -> VisionFrame: - inverse_matrix = cv2.invertAffineTransform(affine_matrix) +def find_paste_region(temp_vision_frame : VisionFrame, crop_vision_frame : VisionFrame, affine_matrix : Matrix) -> Tuple[BoundingBox, Matrix]: temp_size = temp_vision_frame.shape[:2][::-1] - inverse_mask = cv2.warpAffine(crop_mask, inverse_matrix, temp_size).clip(0, 1) - inverse_vision_frame = cv2.warpAffine(crop_vision_frame, inverse_matrix, temp_size, borderMode = cv2.BORDER_REPLICATE) - paste_vision_frame = temp_vision_frame.copy() - paste_vision_frame[:, :, 0] = inverse_mask * inverse_vision_frame[:, :, 0] + (1 - inverse_mask) * temp_vision_frame[:, :, 0] - paste_vision_frame[:, :, 1] = inverse_mask * inverse_vision_frame[:, :, 1] + (1 - inverse_mask) * temp_vision_frame[:, :, 1] - paste_vision_frame[:, :, 2] = inverse_mask * inverse_vision_frame[:, :, 2] + (1 - inverse_mask) * temp_vision_frame[:, :, 2] - return paste_vision_frame + crop_size = crop_vision_frame.shape[:2][::-1] + inverse_matrix = cv2.invertAffineTransform(affine_matrix) + crop_corners = numpy.array([ [ 0, 0 ], [ crop_size[0], 0 ], [ crop_size[0], crop_size[1] ], [ 0, crop_size[1] ] ], dtype = numpy.float32) + paste_region_corners = transform_points(crop_corners, inverse_matrix) + min_corner = numpy.floor(paste_region_corners.min(axis = 0)).astype(int) + max_corner = numpy.ceil(paste_region_corners.max(axis = 0)).astype(int) + x_min, y_min = numpy.clip(min_corner, 0, temp_size) + x_max, y_max = numpy.clip(max_corner, 0, temp_size) + paste_region_bounding_box = numpy.array([ x_min, y_min, x_max, y_max ]) + paste_region_matrix = inverse_matrix.copy() + paste_region_matrix[0, 2] -= x_min + paste_region_matrix[1, 2] -= y_min + return paste_region_bounding_box, paste_region_matrix + + +def paste_back(temp_vision_frame : VisionFrame, crop_vision_frame : VisionFrame, crop_mask : Mask, affine_matrix : Matrix) -> VisionFrame: + paste_region_bounding_box, paste_region_matrix = find_paste_region(temp_vision_frame, crop_vision_frame, affine_matrix) + x_min, y_min, x_max, y_max = paste_region_bounding_box + paste_region_width = x_max - x_min + paste_region_height = y_max - y_min + + if paste_region_width > 0 and paste_region_height > 0: + paste_region_frame = temp_vision_frame[y_min:y_max, x_min:x_max] + paste_inverse_mask = cv2.warpAffine(crop_mask, paste_region_matrix, (paste_region_width, paste_region_height)).clip(0, 1)[:, :, None] + paste_inverse_region_frame = cv2.warpAffine(crop_vision_frame, paste_region_matrix, (paste_region_width, paste_region_height), borderMode = cv2.BORDER_REPLICATE) + paste_region_frame = paste_region_frame * (1 - paste_inverse_mask) + paste_inverse_region_frame * paste_inverse_mask + paste_vision_frame = temp_vision_frame.copy() + paste_vision_frame[y_min:y_max, x_min:x_max] = paste_region_frame.astype(temp_vision_frame.dtype) + return paste_vision_frame + + return temp_vision_frame @lru_cache(maxsize = None)