File size: 1,738 Bytes
21c63ec
 
 
 
 
 
 
 
 
 
 
 
 
 
924970f
 
21c63ec
 
 
 
 
 
 
924970f
21c63ec
 
924970f
21c63ec
 
 
924970f
21c63ec
 
 
 
 
 
 
924970f
21c63ec
 
 
924970f
 
 
21c63ec
924970f
 
21c63ec
924970f
21c63ec
924970f
 
21c63ec
924970f
 
21c63ec
924970f
21c63ec
924970f
 
21c63ec
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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)