100 lines
3.6 KiB
Python
100 lines
3.6 KiB
Python
# WanSeamlessFlow/visualization.py
|
|
|
|
from typing import Optional, List
|
|
from .blending import BlendFunctions
|
|
|
|
def create_transition_visualization(
|
|
num_frames: int,
|
|
num_prompts: int,
|
|
blend_width: int,
|
|
blend_method: str = "linear",
|
|
show_blend_zones: bool = True,
|
|
frame_markers: Optional[List[str]] = None
|
|
) -> str:
|
|
"""
|
|
Create a textual visualization of prompt transitions.
|
|
|
|
Args:
|
|
num_frames: Total number of frames
|
|
num_prompts: Number of prompts
|
|
blend_width: Width of transition zone
|
|
blend_method: Type of interpolation curve
|
|
show_blend_zones: Whether to highlight blend zones
|
|
frame_markers: Custom frame markers
|
|
|
|
Returns:
|
|
String visualization
|
|
"""
|
|
# Use default frame markers if not provided
|
|
if frame_markers is None:
|
|
frame_markers = ["╶"] * num_frames
|
|
|
|
# Nothing to visualize for edge cases
|
|
if blend_width == 0 or num_prompts <= 1:
|
|
return "No blend zones configured or only one prompt available."
|
|
|
|
# Calculate section size
|
|
section_size = num_frames / num_prompts
|
|
|
|
# Build visualization
|
|
visualization = []
|
|
visualization.append(f"Transition visualization for {num_frames} frames with {num_prompts} prompts")
|
|
visualization.append(f"Section size: {section_size:.1f} frames, Blend width: {blend_width} frames, Method: {blend_method}")
|
|
visualization.append("")
|
|
|
|
# Mark section boundaries
|
|
for i in range(1, num_prompts):
|
|
boundary = int(i * section_size)
|
|
if boundary < num_frames:
|
|
frame_markers[boundary] = "┃" # Section boundary
|
|
|
|
# Mark blend zones if requested
|
|
if show_blend_zones and blend_width > 0:
|
|
# Get the blend function
|
|
blend_func = getattr(BlendFunctions, blend_method, BlendFunctions.linear)
|
|
|
|
for i in range(1, num_prompts):
|
|
boundary = int(i * section_size)
|
|
zone_start = max(0, boundary - blend_width)
|
|
zone_end = min(num_frames-1, boundary + blend_width - 1)
|
|
|
|
# Mark the blend zone
|
|
for j in range(zone_start, zone_end + 1):
|
|
if j != boundary: # Don't overwrite section boundary
|
|
# Calculate raw blend ratio
|
|
distance = abs(j - boundary)
|
|
raw_ratio = 1.0 - (distance / blend_width)
|
|
|
|
# Apply the selected curve
|
|
blend_ratio = blend_func(raw_ratio)
|
|
|
|
# Use different characters based on blend ratio
|
|
if blend_ratio > 0.75:
|
|
frame_markers[j] = "▓"
|
|
elif blend_ratio > 0.5:
|
|
frame_markers[j] = "▒"
|
|
elif blend_ratio > 0.25:
|
|
frame_markers[j] = "░"
|
|
else:
|
|
frame_markers[j] = "·"
|
|
|
|
# Create the visualization string
|
|
vis_line = "".join(frame_markers)
|
|
chunk_size = 80
|
|
|
|
# Split into chunks for readability
|
|
for i in range(0, len(vis_line), chunk_size):
|
|
chunk = vis_line[i:i+chunk_size]
|
|
frame_start = i
|
|
frame_end = min(i+chunk_size-1, num_frames-1)
|
|
visualization.append(f"{frame_start:4d} {chunk} {frame_end:4d}")
|
|
|
|
# Add legend
|
|
visualization.append("")
|
|
visualization.append("Legend:")
|
|
visualization.append("┃ - Section boundary")
|
|
if show_blend_zones:
|
|
visualization.append("▓▒░· - Blend zone (▓=strongest blend)")
|
|
visualization.append("╶ - Regular frame")
|
|
|
|
return "\n".join(visualization) |