5.2 KiB
5.2 KiB
Documentation
- Class name: ImageTransformByNormalizedAmplitude
- Category: KJNodes/audio
- Output node: False
ImageTransformByNormalizedAmplitude 节点根据归一化的振幅值对图像应用变换,动态调整诸如缩放比例等方面。它设计用于根据音频驱动的振幅数据调整批量图像的大小,从而实现创意性的视听同步效果。
Input types
Required
- normalized_amp
- 归一化振幅值数组,每个值对应批次中的一张图像,用于确定变换的比例。
- Comfy dtype: NORMALIZED_AMPLITUDE
- Python dtype: numpy.ndarray
- zoom_scale
- 缩放因子,决定了基于振幅值图像缩放的程度。
- Comfy dtype: FLOAT
- Python dtype: float
- x_offset
- 缩放后应用于图像的水平偏移量,允许进行位置调整。
- Comfy dtype: INT
- Python dtype: int
- y_offset
- 缩放后应用于图像的垂直偏移量,允许进行位置调整。
- Comfy dtype: INT
- Python dtype: int
- cumulative
- 布尔值,指示缩放效果是否应在批次中的图像间累积。
- Comfy dtype: BOOLEAN
- Python dtype: bool
- image
- 待变换的图像批次,每张图像的变换受其对应振幅值的影响。
- Comfy dtype: IMAGE
- Python dtype: torch.Tensor
Output types
- image
- 变换后的图像,每张图像都根据其对应的归一化振幅值、缩放比例和位置偏移进行了调整。
- Comfy dtype: IMAGE
- Python dtype: List[torch.Tensor]
Usage tips
- Infra type:
CPU - Common nodes: unknown
Source code
class ImageTransformByNormalizedAmplitude:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"normalized_amp": ("NORMALIZED_AMPLITUDE",),
"zoom_scale": ("FLOAT", { "default": 0.0, "min": -1.0, "max": 1.0, "step": 0.001, "display": "number" }),
"x_offset": ("INT", { "default": 0, "min": (1 -MAX_RESOLUTION), "max": MAX_RESOLUTION, "step": 1, "display": "number" }),
"y_offset": ("INT", { "default": 0, "min": (1 -MAX_RESOLUTION), "max": MAX_RESOLUTION, "step": 1, "display": "number" }),
"cumulative": ("BOOLEAN", { "default": False }),
"image": ("IMAGE",),
}}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "amptransform"
CATEGORY = "KJNodes/audio"
DESCRIPTION = """
Works as a bridge to the AudioScheduler -nodes:
https://github.com/a1lazydog/ComfyUI-AudioScheduler
Transforms image based on the normalized amplitude.
"""
def amptransform(self, image, normalized_amp, zoom_scale, cumulative, x_offset, y_offset):
# Ensure normalized_amp is an array and within the range [0, 1]
normalized_amp = np.clip(normalized_amp, 0.0, 1.0)
transformed_images = []
# Initialize the cumulative zoom factor
prev_amp = 0.0
for i in range(image.shape[0]):
img = image[i] # Get the i-th image in the batch
amp = normalized_amp[i] # Get the corresponding amplitude value
# Incrementally increase the cumulative zoom factor
if cumulative:
prev_amp += amp
amp += prev_amp
# Convert the image tensor from BxHxWxC to CxHxW format expected by torchvision
img = img.permute(2, 0, 1)
# Convert PyTorch tensor to PIL Image for processing
pil_img = TF.to_pil_image(img)
# Calculate the crop size based on the amplitude
width, height = pil_img.size
crop_size = int(min(width, height) * (1 - amp * zoom_scale))
crop_size = max(crop_size, 1)
# Calculate the crop box coordinates (centered crop)
left = (width - crop_size) // 2
top = (height - crop_size) // 2
right = (width + crop_size) // 2
bottom = (height + crop_size) // 2
# Crop and resize back to original size
cropped_img = TF.crop(pil_img, top, left, crop_size, crop_size)
resized_img = TF.resize(cropped_img, (height, width))
# Convert back to tensor in CxHxW format
tensor_img = TF.to_tensor(resized_img)
# Convert the tensor back to BxHxWxC format
tensor_img = tensor_img.permute(1, 2, 0)
# Offset the image based on the amplitude
offset_amp = amp * 10 # Calculate the offset magnitude based on the amplitude
shift_x = min(x_offset * offset_amp, img.shape[1] - 1) # Calculate the shift in x direction
shift_y = min(y_offset * offset_amp, img.shape[0] - 1) # Calculate the shift in y direction
# Apply the offset to the image tensor
if shift_x != 0:
tensor_img = torch.roll(tensor_img, shifts=int(shift_x), dims=1)
if shift_y != 0:
tensor_img = torch.roll(tensor_img, shifts=int(shift_y), dims=0)
# Add to the list
transformed_images.append(tensor_img)
# Stack all transformed images into a batch
transformed_batch = torch.stack(transformed_images)
return (transformed_batch,)