import cv2 import numpy as np from PIL import Image def get_border(mode): return { 'Reflect': cv2.BORDER_REFLECT_101, 'Replicate': cv2.BORDER_REPLICATE, 'Wrap': cv2.BORDER_WRAP, 'Black': cv2.BORDER_CONSTANT }.get(mode, cv2.BORDER_REFLECT_101) def anim_frame_warp(prev_img, angle, zoom, tx, ty, border_mode): """ True Perspective/Homography Warp. Simulates camera movement (FOV) via Matrix math. """ if prev_img is None: return None cv_img = np.array(prev_img) height, width = cv_img.shape[:2] center_x, center_y = width // 2, height // 2 # 1. Initialize 3x3 Identity matrix = np.identity(3) # 2. Translation (Pan) matrix[0, 2] = tx matrix[1, 2] = ty # 3. Rotation rot_rad = np.radians(angle) rot_mat = np.identity(3) rot_mat[0, 0] = np.cos(rot_rad) rot_mat[0, 1] = -np.sin(rot_rad) rot_mat[1, 0] = np.sin(rot_rad) rot_mat[1, 1] = np.cos(rot_rad) # Center Offset center_mat = np.identity(3) center_mat[0, 2] = -center_x center_mat[1, 2] = -center_y inv_center = np.identity(3) inv_center[0, 2] = center_x inv_center[1, 2] = center_y # Apply Rotation around center matrix = inv_center @ rot_mat @ center_mat @ matrix # 4. Zoom (Scale) scale_mat = np.identity(3) scale_mat[0, 0] = zoom scale_mat[1, 1] = zoom # Apply Scale around center matrix = inv_center @ scale_mat @ center_mat @ matrix # 5. Warp Perspective result = cv2.warpPerspective( cv_img, matrix, (width, height), borderMode=get_border(border_mode), flags=cv2.INTER_LINEAR ) return Image.fromarray(result)