Spaces:
Sleeping
Sleeping
| 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) |