第一次来这里,我是 python 新手,并尝试使用 python 调整 ComfyUI 节点的图像大小
import torch
import torchvision.transforms.functional as TF
from PIL import Image
class ImageResize:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
"height": ("INT", {"min": 1}),
"width": ("INT", {"min": 1}),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "resize_image"
CATEGORY = "ImageProcessing"
def resize_image(self, image, height, width):
input_image = image
resized_image = TF.resize(input_image, (height, width))
return (resized_image,)
使用上面的,当我调整高度时,宽度发生变化,当我调整宽度时,
int of 1 显示无法处理此数据类型:(1, 1, 1), |u1
int of 2 显示黑白图像
int of 3 显示全彩图像
int of 4 显示暗淡的彩色图像
5 或更高会抛出与 1 相同的错误,最后一个值递增到 5 或更高,即:无法处理此数据类型:(1, 1, 5), |u1
我做错了什么?
不知道为什么高度调整宽度和宽度做完全不同的事情
这里的问题是
torchvision
和 ComfyUI
在处理图像数据时使用不同的内存布局。将彩色图像表示为多维数组时,有两种常用的方法:在 [H, W, C]
、PIL
和 opencv
等库中使用的通道后格式(图像数组的形状为 tensorflow
)以及通道优先格式([C, H, W]
) 主要由 torch
和 torchvision
使用。
如果我们查看 LoadImage 的实现,我们会看到图像是用
PIL.Image.open
打开的,因此生成的数组将采用通道最后格式。在您的自定义节点中,您正在使用 torchvision
的 resize 运算符,它期望其输入为通道优先。
调整大小操作本身只是一种插值,可以处理任意形状的输入。然而,在您的情况下,当您传递内存布局错误的图像时,尝试更改高度将更改宽度,而尝试更改宽度将更改channels。因此,您看到的奇怪颜色 - 将“宽度”调整为 4 会向图像添加一个 Alpha 通道,使其显得暗淡。
为了获得所需的行为,您需要修改图像以匹配预期的输入形状
torchvision.Resize
,例如将数组转置为通道优先。
# note that this example expects images to always have a batch
# dimension and a colour channel
def resize_image(self, image, height, width):
# [B, H, W, C] -> [B, C, H, W]
input_image = image.permute((0, 3, 1, 2))
resized_image = TF.resize(input_image, (height, width))
# [B, C, H, W] -> [B, H, W, C]
resized_image = resized_image.permute((0, 2, 3, 1))
return (resized_image,)
这是一个很好的例子,为什么在提问时应该提供完整堆栈跟踪,因为根本问题不在于节点的实现,而在于
ComfyUI
和torchvision
处理图像的方式存在差异。