AlekseyCalvin commited on
Commit
441b0c8
·
verified ·
1 Parent(s): e14557b

Create utils.py

Browse files
Files changed (1) hide show
  1. utils.py +100 -0
utils.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import numexpr
4
+ import re
5
+ from PIL import Image
6
+
7
+ # --- Math Parsing ---
8
+ def parse_weight_string(string, max_frames):
9
+ """Parses schedule strings with math support (e.g., '0:(0.5), 50:(sin(t/10))')."""
10
+ string = re.sub(r'\s+', '', str(string))
11
+ keyframes = {}
12
+ parts = string.split(',')
13
+ for part in parts:
14
+ try:
15
+ if ':' not in part: continue
16
+ frame_str, val_str = part.split(':', 1)
17
+ keyframes[int(frame_str)] = val_str.strip('()')
18
+ except: continue
19
+ if 0 not in keyframes: keyframes[0] = "0"
20
+
21
+ sorted_frames = sorted(keyframes.keys())
22
+ series = np.zeros(int(max_frames))
23
+ for i in range(len(sorted_frames)):
24
+ f_start = sorted_frames[i]
25
+ f_end = sorted_frames[i+1] if i < len(sorted_frames)-1 else int(max_frames)
26
+ formula = keyframes[f_start]
27
+ for f in range(f_start, f_end):
28
+ t = f
29
+ try:
30
+ val = numexpr.evaluate(formula, local_dict={'t': t, 'pi': np.pi, 'sin': np.sin, 'cos': np.cos, 'tan': np.tan})
31
+ series[f] = float(val)
32
+ except:
33
+ try: series[f] = float(formula)
34
+ except: series[f] = series[f-1] if f > 0 else 0.0
35
+ return series
36
+
37
+ # --- Image Processing ---
38
+ def get_border_mode(mode_str):
39
+ return {
40
+ 'Reflect': cv2.BORDER_REFLECT_101,
41
+ 'Replicate': cv2.BORDER_REPLICATE,
42
+ 'Wrap': cv2.BORDER_WRAP,
43
+ 'Black': cv2.BORDER_CONSTANT
44
+ }.get(mode_str, cv2.BORDER_REFLECT_101)
45
+
46
+ def maintain_colors(prev_img, color_match_sample, mode='LAB'):
47
+ """Matches colors using LAB or HSV space to prevent drift."""
48
+ if mode == 'None' or prev_img is None or color_match_sample is None: return prev_img
49
+
50
+ prev_np = np.array(prev_img).astype(np.uint8)
51
+ sample_np = np.array(color_match_sample).astype(np.uint8)
52
+
53
+ if mode == 'LAB':
54
+ prev_lab = cv2.cvtColor(prev_np, cv2.COLOR_RGB2LAB)
55
+ sample_lab = cv2.cvtColor(sample_np, cv2.COLOR_RGB2LAB)
56
+ for i in range(3): # Match L, A, and B channels
57
+ avg_p = np.mean(prev_lab[:,:,i])
58
+ avg_s = np.mean(sample_lab[:,:,i])
59
+ prev_lab[:,:,i] = np.clip(prev_lab[:,:,i] - avg_p + avg_s, 0, 255)
60
+ return Image.fromarray(cv2.cvtColor(prev_lab, cv2.COLOR_LAB2RGB))
61
+
62
+ elif mode == 'HSV':
63
+ prev_hsv = cv2.cvtColor(prev_np, cv2.COLOR_RGB2HSV)
64
+ sample_hsv = cv2.cvtColor(sample_np, cv2.COLOR_RGB2HSV)
65
+ # Match Saturation and Value only, keep Hue
66
+ for i in [1, 2]:
67
+ avg_p = np.mean(prev_hsv[:,:,i])
68
+ avg_s = np.mean(sample_hsv[:,:,i])
69
+ prev_hsv[:,:,i] = np.clip(prev_hsv[:,:,i] - avg_p + avg_s, 0, 255)
70
+ return Image.fromarray(cv2.cvtColor(prev_hsv, cv2.COLOR_HSV2RGB))
71
+
72
+ return prev_img
73
+
74
+ def add_noise(img, noise_amt):
75
+ """Adds uniform noise for texture injection."""
76
+ if noise_amt <= 0 or img is None: return img
77
+ img_np = np.array(img).astype(np.float32)
78
+ noise = np.random.normal(0, noise_amt * 255, img_np.shape).astype(np.float32)
79
+ noisy_img = np.clip(img_np + noise, 0, 255).astype(np.uint8)
80
+ return Image.fromarray(noisy_img)
81
+
82
+ def anim_frame_warp_2d(prev_img_pil, args_dict, border_mode_str='Reflect'):
83
+ """Performs 2D affine transformation."""
84
+ if prev_img_pil is None: return None
85
+ cv2_img = np.array(prev_img_pil)
86
+ height, width = cv2_img.shape[:2]
87
+ center = (width // 2, height // 2)
88
+
89
+ angle = args_dict.get('angle', 0)
90
+ zoom = args_dict.get('zoom', 1.0)
91
+ tx = args_dict.get('translation_x', 0)
92
+ ty = args_dict.get('translation_y', 0)
93
+
94
+ trans_mat = cv2.getRotationMatrix2D(center, angle, zoom)
95
+ trans_mat[0, 2] += tx
96
+ trans_mat[1, 2] += ty
97
+
98
+ border_mode = get_border_mode(border_mode_str)
99
+ warped = cv2.warpAffine(cv2_img, trans_mat, (width, height), borderMode=border_mode)
100
+ return Image.fromarray(warped)