dikdimon commited on
Commit
4f9d1e7
·
verified ·
1 Parent(s): 1b3d396

Delete asymmetric-tiling-sd-webui-2.0/scripts/advanced_zoom_extension (1).py

Browse files
asymmetric-tiling-sd-webui-2.0/scripts/advanced_zoom_extension (1).py DELETED
@@ -1,516 +0,0 @@
1
- """
2
- ╔══════════════════════════════════════════════════════════════════════════════╗
3
- ║ ADVANCED ZOOM & PROXIMITY SYSTEM ║
4
- ║ Расширение для asymmetric_tiling_UNIFIED ║
5
- ╚══════════════════════════════════════════════════════════════════════════════╝
6
-
7
- НОВЫЕ ВОЗМОЖНОСТИ:
8
- ✅ Настоящий zoom слайдер от -5 (отдаление) до +5 (приближение)
9
- ✅ Отдаление БЕЗ изменения всей картинки (legacy stereo convergence метод)
10
- ✅ Множественные режимы blend для разных эффектов
11
- ✅ Комбинированные режимы (circular+reflect, polar+mirror и т.д.)
12
- """
13
-
14
- import torch
15
- import torch.nn.functional as F
16
- import math
17
- from enum import Enum
18
-
19
-
20
- # ═══════════════════════════════════════════════════════════════════════════
21
- # ZOOM MODES - Режимы отдаления/приближения
22
- # ═══════════════════════════════════════════════════════════════════════════
23
-
24
- class ZoomMode(Enum):
25
- """Режимы для zoom эффекта"""
26
- BLEND_TRANSITION = "blend_transition" # Смешивание режимов padding
27
- CONVERGENCE_SHIFT = "convergence_shift" # Shift-based zoom (без изменения всей картинки)
28
- GRID_WARP = "grid_warp" # Warp через grid_sample
29
- HYBRID = "hybrid" # Комбинация методов
30
-
31
-
32
- class BlendMode(Enum):
33
- """Режимы для Advanced Blend"""
34
- CIRCULAR_REFLECT = "circular_reflect" # Circular → Reflect
35
- CIRCULAR_CONSTANT = "circular_constant" # Circular → Constant (black)
36
- REFLECT_CONSTANT = "reflect_constant" # Reflect → Constant
37
- POLAR_CIRCULAR = "polar_circular" # Polar → Circular
38
- MIRROR_CIRCULAR = "mirror_circular" # Mirror → Circular
39
- ANISO_CIRCULAR = "aniso_circular" # Anisotropic → Circular
40
- CUSTOM = "custom" # Пользовательские режимы
41
-
42
-
43
- # ═══════════════════════════════════════════════════════════════════════════
44
- # CONVERGENCE ZOOM - Отдаление БЕЗ изменения всей картинки
45
- # ═══════════════════════════════════════════════════════════════════════════
46
-
47
- def apply_convergence_zoom(input_tensor, zoom_factor, convergence_point=0.5,
48
- depth_power=1.0, axis='horizontal'):
49
- """
50
- 🎯 LEGACY МЕТОД: Отдаление через shift без изменения всей картинки
51
-
52
- Этот метод НЕ меняет само изображение - он только создает
53
- иллюзию глубины через сдвиги на разных частях изображения.
54
-
55
- Args:
56
- input_tensor: [B, C, H, W]
57
- zoom_factor: -5.0 (сильное отдаление) ... 0 (нет эффекта) ... +5.0 (приближение)
58
- convergence_point: 0.0-1.0, точка схождения (где нет сдвига)
59
- depth_power: Кривая глубины (1.0 = линейно, >1 = более выражено)
60
- axis: 'horizontal', 'vertical', 'both'
61
-
62
- Returns:
63
- Тензор с примененным shift-based zoom
64
- """
65
- if abs(zoom_factor) < 0.01:
66
- return input_tensor
67
-
68
- b, c, h, w = input_tensor.shape
69
- device = input_tensor.device
70
- dtype = input_tensor.dtype
71
-
72
- # Нормализуем zoom_factor
73
- zoom_factor = max(-5.0, min(5.0, float(zoom_factor)))
74
-
75
- # Shift amount пропорционален размеру и zoom_factor
76
- # Отрицательный zoom = отдаление = больше shift
77
- max_shift_ratio = abs(zoom_factor) * 0.02 # 2% на единицу zoom
78
-
79
- result = input_tensor.clone()
80
-
81
- # === ГОРИЗОНТАЛЬНЫЙ SHIFT ===
82
- if axis in ('horizontal', 'both'):
83
- # Создаем depth map по гор��зонтали
84
- x_coords = torch.linspace(0.0, 1.0, w, device=device, dtype=dtype).view(1, 1, 1, w)
85
- depth_h = torch.abs(x_coords - convergence_point).expand(b, c, h, w)
86
-
87
- # Применяем depth power
88
- if abs(depth_power - 1.0) > 0.01:
89
- depth_h = torch.pow(depth_h, depth_power)
90
-
91
- # Вычисляем shift для каждого пикселя
92
- shift_amount_h = (depth_h * max_shift_ratio * w).clamp(-w//2, w//2)
93
-
94
- # Направление shift зависит от знака zoom
95
- # Отрицательный zoom (отдаление) = shift наружу от convergence point
96
- # Положительный zoom (приближение) = shift к convergence point
97
- direction = -1.0 if zoom_factor < 0 else 1.0
98
- shift_amount_h = shift_amount_h * direction
99
-
100
- # Применяем shift через roll (циклический для seamless)
101
- # Для более плавного эффекта используем weighted blend
102
- shift_pixels = int(shift_amount_h.mean().item())
103
- if shift_pixels != 0:
104
- shifted_h = torch.roll(result, shifts=shift_pixels, dims=3)
105
- # Blend с весами по depth map
106
- alpha_h = (depth_h * abs(zoom_factor) * 0.2).clamp(0.0, 1.0)
107
- result = result * (1.0 - alpha_h) + shifted_h * alpha_h
108
-
109
- # === ВЕРТИКАЛЬНЫЙ SHIFT ===
110
- if axis in ('vertical', 'both'):
111
- y_coords = torch.linspace(0.0, 1.0, h, device=device, dtype=dtype).view(1, 1, h, 1)
112
- depth_v = torch.abs(y_coords - convergence_point).expand(b, c, h, w)
113
-
114
- if abs(depth_power - 1.0) > 0.01:
115
- depth_v = torch.pow(depth_v, depth_power)
116
-
117
- shift_amount_v = (depth_v * max_shift_ratio * h).clamp(-h//2, h//2)
118
- direction = -1.0 if zoom_factor < 0 else 1.0
119
- shift_amount_v = shift_amount_v * direction
120
-
121
- shift_pixels = int(shift_amount_v.mean().item())
122
- if shift_pixels != 0:
123
- shifted_v = torch.roll(result, shifts=shift_pixels, dims=2)
124
- alpha_v = (depth_v * abs(zoom_factor) * 0.2).clamp(0.0, 1.0)
125
- result = result * (1.0 - alpha_v) + shifted_v * alpha_v
126
-
127
- return result
128
-
129
-
130
- # ═══════════════════════════════════════════════════════════════════════════
131
- # GRID WARP ZOOM - Приближение/отдаление через grid_sample
132
- # ═══════════════════════════════════════════════════════════════════════════
133
-
134
- def apply_grid_warp_zoom(input_tensor, zoom_factor, center_x=0.5, center_y=0.5,
135
- warp_power=1.0, interpolation='bilinear'):
136
- """
137
- 🔄 GRID WARP: Настоящий zoom через деформацию координат
138
-
139
- Args:
140
- input_tensor: [B, C, H, W]
141
- zoom_factor: -5.0 (отдаление) ... 0 ... +5.0 (приближение)
142
- center_x, center_y: Центр zoom (0.0-1.0)
143
- warp_power: Кривая деформации
144
- interpolation: 'bilinear' или 'nearest'
145
-
146
- Returns:
147
- Деформированный тензор
148
- """
149
- if abs(zoom_factor) < 0.01:
150
- return input_tensor
151
-
152
- b, c, h, w = input_tensor.shape
153
- device = input_tensor.device
154
- dtype = input_tensor.dtype
155
-
156
- # Конвертируем zoom_factor в scale factor
157
- # zoom_factor = -5: scale = 0.5 (видим 2x больше области)
158
- # zoom_factor = 0: scale = 1.0 (нет изменений)
159
- # zoom_factor = +5: scale = 2.0 (видим 0.5x области, приближение)
160
- scale = math.pow(2.0, zoom_factor / 5.0)
161
-
162
- # Создаем сетку координат
163
- y_coords = torch.linspace(-1.0, 1.0, h, device=device, dtype=dtype)
164
- x_coords = torch.linspace(-1.0, 1.0, w, device=device, dtype=dtype)
165
- grid_y, grid_x = torch.meshgrid(y_coords, x_coords, indexing='ij')
166
-
167
- # Центрируем относительно заданной точки
168
- center_x_norm = (center_x - 0.5) * 2.0
169
- center_y_norm = (center_y - 0.5) * 2.0
170
-
171
- grid_x = grid_x - center_x_norm
172
- grid_y = grid_y - center_y_norm
173
-
174
- # Применяем zoom (scale)
175
- # Для отдаления (zoom < 0): увеличиваем координаты = видим больше
176
- # Для приближения (zoom > 0): уменьшаем координаты = видим меньше
177
- grid_x = grid_x / scale
178
- grid_y = grid_y / scale
179
-
180
- # Опционально применяем warp power (для нелинейного zoom)
181
- if abs(warp_power - 1.0) > 0.01:
182
- radius = torch.sqrt(grid_x ** 2 + grid_y ** 2)
183
- angle = torch.atan2(grid_y, grid_x)
184
- radius_warped = torch.pow(radius.clamp(0.0, math.sqrt(2.0)), warp_power)
185
- grid_x = radius_warped * torch.cos(angle)
186
- grid_y = radius_warped * torch.sin(angle)
187
-
188
- # Возвращаем к центру
189
- grid_x = grid_x + center_x_norm
190
- grid_y = grid_y + center_y_norm
191
-
192
- # Собираем grid
193
- grid = torch.stack([grid_x, grid_y], dim=-1) # [H, W, 2]
194
- grid = grid.unsqueeze(0).expand(b, -1, -1, -1) # [B, H, W, 2]
195
-
196
- # Применяем grid_sample
197
- mode = 'bilinear' if interpolation == 'bilinear' else 'nearest'
198
- result = F.grid_sample(
199
- input_tensor, grid,
200
- mode=mode,
201
- padding_mode='border', # Можно изменить на 'zeros' или 'reflection'
202
- align_corners=True
203
- )
204
-
205
- return result
206
-
207
-
208
- # ═══════════════════════════════════════════════════════════════════════════
209
- # ADVANCED BLEND WITH MODES - Смешивание с разными режимами
210
- # ═══════════════════════════════════════════════════════════════════════════
211
-
212
- def get_blend_mode_tensors(input_tensor, pad_h, pad_w, blend_mode, params=None):
213
- """
214
- Получает два тензора для смешивания в зависимости от blend_mode
215
-
216
- Args:
217
- input_tensor: [B, C, H, W]
218
- pad_h, pad_w: Размеры padding
219
- blend_mode: BlendMode enum
220
- params: Дополнительные параметры для сложных режимов
221
-
222
- Returns:
223
- (tensor_simple, tensor_advanced) - два тензора для blend
224
- """
225
- params = params or {}
226
-
227
- if blend_mode == BlendMode.CIRCULAR_REFLECT.value:
228
- # Simple: circular, Advanced: reflect
229
- tensor_simple = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
230
- tensor_advanced = _safe_pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='reflect')
231
-
232
- elif blend_mode == BlendMode.CIRCULAR_CONSTANT.value:
233
- # Simple: constant (black), Advanced: circular
234
- tensor_simple = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='constant', value=0)
235
- tensor_advanced = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
236
-
237
- elif blend_mode == BlendMode.REFLECT_CONSTANT.value:
238
- # Simple: constant, Advanced: reflect
239
- tensor_simple = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='constant', value=0)
240
- tensor_advanced = _safe_pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='reflect')
241
-
242
- elif blend_mode == BlendMode.POLAR_CIRCULAR.value:
243
- # Simple: circular, Advanced: polar (требует импорта из основного файла)
244
- tensor_simple = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
245
- # Используем функцию из основного файла если доступна
246
- if 'compute_polar_padding' in params:
247
- tensor_advanced = params['compute_polar_padding'](input_tensor, pad_h, pad_w)
248
- else:
249
- # Fallback
250
- tensor_advanced = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
251
-
252
- elif blend_mode == BlendMode.MIRROR_CIRCULAR.value:
253
- # Simple: replicate (mirror-like), Advanced: circular
254
- tensor_simple = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='replicate')
255
- tensor_advanced = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
256
-
257
- elif blend_mode == BlendMode.ANISO_CIRCULAR.value:
258
- # Simple: circular, Advanced: anisotropic
259
- tensor_simple = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
260
- if 'compute_anisotropic_padding' in params:
261
- tensor_advanced = params['compute_anisotropic_padding'](
262
- input_tensor, pad_h, pad_w,
263
- params.get('aniso_angle', 45),
264
- params.get('aniso_angle2', None),
265
- params.get('aniso_mix', 1.0)
266
- )
267
- else:
268
- # Fallback
269
- tensor_advanced = _safe_pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='reflect')
270
-
271
- else: # Default / Custom
272
- tensor_simple = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='constant', value=0)
273
- tensor_advanced = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
274
-
275
- return tensor_simple, tensor_advanced
276
-
277
-
278
- def _safe_pad(x, pad, mode='reflect', value=0.0):
279
- """Safe wrapper для reflect mode"""
280
- if not isinstance(pad, (tuple, list)) or len(pad) != 4:
281
- return F.pad(x, pad, mode=mode, value=value) if mode == 'constant' else F.pad(x, pad, mode=mode)
282
-
283
- l, r, t, b = pad
284
- if mode == 'reflect':
285
- h = int(x.shape[-2])
286
- w = int(x.shape[-1])
287
- if (l >= w) or (r >= w) or (t >= h) or (b >= h):
288
- mode = 'replicate'
289
-
290
- if mode == 'constant':
291
- return F.pad(x, (l, r, t, b), mode=mode, value=value)
292
- return F.pad(x, (l, r, t, b), mode=mode)
293
-
294
-
295
- # ═══════════════════════════════════════════════════════════════════════════
296
- # UNIFIED ZOOM SYSTEM - Объединяет все методы
297
- # ═══════════════════════════════════════════════════════════════════════════
298
-
299
- def apply_unified_zoom(input_tensor, pad_h, pad_w, zoom_factor=0.0, zoom_mode='blend_transition',
300
- blend_mode='circular_reflect', **kwargs):
301
-
302
- # === ИСПРАВЛЕНИЕ: БЕЗОПАСНЫЙ НУЛЕВОЙ ЗУМ ===
303
- # Если зума нет (или он ничтожно мал), мы НЕ должны делать grid_sample,
304
- # так как он мылит картинку. Но мы ДОЛЖНЫ сделать паддинг.
305
- if abs(zoom_factor) < 0.001:
306
- # Импортируем функцию для обычного блендинга
307
- from improved_tiling_functions import compute_advanced_blend_padding
308
-
309
- # Разбираем blend_mode строку (например 'circular_reflect' -> 'circular', 'reflect')
310
- if isinstance(blend_mode, str):
311
- parts = blend_mode.split('_')
312
- # Если формат 'modeA_modeB' (например circular_reflect)
313
- if len(parts) >= 2:
314
- mode_simple = 'constant' if parts[1] == 'constant' else 'replicate' # упрощение
315
- mode_adv = parts[0] # 'circular', 'reflect', 'polar'
316
- else:
317
- mode_simple = 'replicate'
318
- mode_adv = parts[0]
319
- else:
320
- mode_simple = 'replicate'
321
- mode_adv = 'circular'
322
-
323
- # Вызываем быстрый и четкий метод
324
- return compute_advanced_blend_padding(
325
- input_tensor, pad_h, pad_w,
326
- mode_simple=mode_simple,
327
- mode_advanced=mode_adv,
328
- blend_strength=kwargs.get('blend_strength', 0.5), # Берем настройки из kwargs или дефолт
329
- # Остальные параметры можно добавить по необходимости
330
- )
331
- )
332
- """
333
- 🌟 UNIFIED ZOOM SYSTEM 🌟
334
-
335
- Объединяет все методы zoom в одну систему:
336
- - Blend Transition: Смешивание режимов padding
337
- - Convergence Shift: Отдаление без изменения всей картинки (legacy)
338
- - Grid Warp: Настоящий geometric zoom
339
- - Hybrid: Комбинация методов
340
-
341
- Args:
342
- input_tensor: [B, C, H, W]
343
- pad_h, pad_w: Padding размеры
344
- zoom_factor: -5.0 (далеко) ... 0 (нормально) ... +5.0 (близко)
345
- zoom_mode: 'blend_transition', 'convergence_shift', 'grid_warp', 'hybrid'
346
- blend_mode: Режим для blend (circular_reflect и т.д.)
347
- convergence_point: Точка схождения (0.0-1.0)
348
- depth_power: Кривая глубины
349
- blend_falloff: Кривая перехода
350
- blend_sharpness: Резкость перехода
351
- blend_width: Ширина зоны перехода
352
- extra_params: Дополнительные параметры
353
-
354
- Returns:
355
- Обработанный тензор с padding
356
- """
357
- extra_params = extra_params or {}
358
-
359
- # === РЕЖИМ 1: BLEND TRANSITION ===
360
- if zoom_mode == ZoomMode.BLEND_TRANSITION.value or zoom_mode == 'blend_transition':
361
- # Конвертируем zoom_factor (-5...+5) в blend_strength (0...1)
362
- # zoom = -5: strength = 0.0 (полностью simple mode)
363
- # zoom = 0: strength = 0.5 (смешивание)
364
- # zoom = +5: strength = 1.0 (полностью advanced mode)
365
- blend_strength = (zoom_factor + 5.0) / 10.0
366
- blend_strength = max(0.0, min(1.0, blend_strength))
367
-
368
- # Получаем два режима padding
369
- tensor_simple, tensor_advanced = get_blend_mode_tensors(
370
- input_tensor, pad_h, pad_w, blend_mode, extra_params
371
- )
372
-
373
- # Импортируем функцию из improved_tiling_functions если доступна
374
- try:
375
- from improved_tiling_functions import compute_advanced_blend_padding
376
- # Используем уже готовые тензоры
377
- if abs(blend_strength) < 0.001:
378
- result = tensor_simple
379
- elif blend_strength > 0.999:
380
- result = tensor_advanced
381
- else:
382
- # Создаем маску и смешиваем
383
- b, c, H, W = tensor_simple.shape
384
- h = H - 2 * pad_h
385
- w = W - 2 * pad_w
386
-
387
- if blend_width is None:
388
- blend_width = max(pad_h, pad_w)
389
-
390
- # Простое смешивание (можно улучшить)
391
- alpha = blend_strength
392
- result = tensor_simple * (1.0 - alpha) + tensor_advanced * alpha
393
- except ImportError:
394
- # Простой fallback
395
- alpha = blend_strength
396
- result = tensor_simple * (1.0 - alpha) + tensor_advanced * alpha
397
-
398
- return result
399
-
400
- # === РЕЖИМ 2: CONVERGENCE SHIFT (Legacy метод) ===
401
- elif zoom_mode == ZoomMode.CONVERGENCE_SHIFT.value or zoom_mode == 'convergence_shift':
402
- # Сначала применяем padding (простой circular)
403
- padded = F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
404
-
405
- # Затем применяем convergence zoom БЕЗ изменения изображения
406
- result = apply_convergence_zoom(
407
- padded,
408
- zoom_factor=zoom_factor,
409
- convergence_point=convergence_point,
410
- depth_power=depth_power,
411
- axis='both'
412
- )
413
-
414
- return result
415
-
416
- # === РЕЖИМ 3: GRID WARP ===
417
- elif zoom_mode == ZoomMode.GRID_WARP.value or zoom_mode == 'grid_warp':
418
- # Применяем grid warp zoom (истинный geometric zoom)
419
- warped = apply_grid_warp_zoom(
420
- input_tensor,
421
- zoom_factor=zoom_factor,
422
- center_x=convergence_point,
423
- center_y=0.5,
424
- warp_power=depth_power
425
- )
426
-
427
- # Затем padding на warped изображение
428
- result = F.pad(warped, (pad_w, pad_w, pad_h, pad_h), mode='circular')
429
-
430
- return result
431
-
432
- # === РЕЖИМ 4: HYBRID (Комбинация методов) ===
433
- elif zoom_mode == ZoomMode.HYBRID.value or zoom_mode == 'hybrid':
434
- # Комбинируем convergence shift (для краев) и blend transition (для seamless)
435
-
436
- # 1. Blend transition
437
- blend_strength = (zoom_factor + 5.0) / 10.0
438
- blend_strength = max(0.0, min(1.0, blend_strength))
439
-
440
- tensor_simple, tensor_advanced = get_blend_mode_tensors(
441
- input_tensor, pad_h, pad_w, blend_mode, extra_params
442
- )
443
-
444
- blended = tensor_simple * (1.0 - blend_strength) + tensor_advanced * blend_strength
445
-
446
- # 2. Convergence shift (слабо)
447
- result = apply_convergence_zoom(
448
- blended,
449
- zoom_factor=zoom_factor * 0.3, # Уменьшаем силу
450
- convergence_point=convergence_point,
451
- depth_power=depth_power,
452
- axis='horizontal'
453
- )
454
-
455
- return result
456
-
457
- # === DEFAULT: Обычный circular padding ===
458
- else:
459
- return F.pad(input_tensor, (pad_w, pad_w, pad_h, pad_h), mode='circular')
460
-
461
-
462
- # ═══════════════════════════════════════════════════════════════════════════
463
- # VALIDATION & HELPERS
464
- # ═══════════════════════════════════════════════════════════════════════════
465
-
466
- def validate_zoom_params(params):
467
- """Валидация параметров zoom"""
468
- return {
469
- 'zoom_factor': max(-5.0, min(5.0, float(params.get('zoom_factor', 0.0)))),
470
- 'zoom_mode': str(params.get('zoom_mode', 'blend_transition')),
471
- 'blend_mode': str(params.get('blend_mode', 'circular_reflect')),
472
- 'convergence_point': max(0.0, min(1.0, float(params.get('convergence_point', 0.5)))),
473
- 'depth_power': max(0.25, min(4.0, float(params.get('depth_power', 1.0)))),
474
- 'blend_falloff': str(params.get('blend_falloff', 'smoothstep')),
475
- 'blend_sharpness': max(0.1, min(5.0, float(params.get('blend_sharpness', 1.0)))),
476
- 'blend_width': int(params.get('blend_width', 0)) if params.get('blend_width') else None,
477
- }
478
-
479
-
480
- # ═══════════════════════════════════════════════════════════════════════════
481
- # TESTING
482
- # ═══════════════════════════════════════════════════════════════════════════
483
-
484
- if __name__ == "__main__":
485
- print("=" * 80)
486
- print("ADVANCED ZOOM & PROXIMITY SYSTEM - TEST")
487
- print("=" * 80)
488
-
489
- # Тест convergence zoom
490
- print("\n🎯 ТЕСТ CONVERGENCE ZOOM (Legacy Method):")
491
- x = torch.randn(1, 3, 64, 64)
492
-
493
- for zoom in [-3, -1, 0, 1, 3]:
494
- result = apply_convergence_zoom(x, zoom_factor=zoom)
495
- print(f" Zoom {zoom:+2d}: shape={result.shape}, mean={result.mean().item():.4f}")
496
-
497
- # Тест grid warp zoom
498
- print("\n🔄 ТЕСТ GRID WARP ZOOM:")
499
- for zoom in [-3, -1, 0, 1, 3]:
500
- result = apply_grid_warp_zoom(x, zoom_factor=zoom)
501
- print(f" Zoom {zoom:+2d}: shape={result.shape}, mean={result.mean().item():.4f}")
502
-
503
- # Тест unified zoom
504
- print("\n🌟 ТЕСТ UNIFIED ZOOM SYSTEM:")
505
- for zoom in [-5, -2, 0, 2, 5]:
506
- result = apply_unified_zoom(
507
- x, pad_h=8, pad_w=8,
508
- zoom_factor=zoom,
509
- zoom_mode='blend_transition',
510
- blend_mode='circular_reflect'
511
- )
512
- print(f" Zoom {zoom:+2d}: shape={result.shape}, mean={result.mean().item():.4f}")
513
-
514
- print("\n" + "=" * 80)
515
- print("✅ ВСЕ ТЕСТЫ ПРОЙДЕНЫ")
516
- print("=" * 80)