233 lines
7.8 KiB
Markdown
233 lines
7.8 KiB
Markdown
|
|
# Documentation
|
|
- Class name: ImageEffectsLensChromaticAberration
|
|
- Category: image/effects/lens
|
|
- Output node: False
|
|
- Repo Ref: https://github.com/comfyanonymous/ComfyUI
|
|
|
|
此节点应用色差效果到图像上,模拟光线通过镜头时的色散现象,创造出具有视觉特色的色彩边缘效果。它通过添加艺术性或真实的镜头瑕疵来增强视觉内容,常用于赋予图像更动态或复古的外观。
|
|
|
|
# Input types
|
|
## Required
|
|
- images
|
|
- 将应用色差效果的输入图像。这个参数对于定义将要进行变换的基础内容至关重要。
|
|
- Comfy dtype: IMAGE
|
|
- Python dtype: torch.Tensor
|
|
- shift
|
|
- 确定模拟色差效果的像素偏移量,影响颜色通道的位移程度。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
- method
|
|
- 指定在应用色差效果时处理边缘像素的方法,确保效果在整个图像上一致应用。
|
|
- Comfy dtype: COMBO[STRING]
|
|
- Python dtype: str
|
|
- shift_type
|
|
- 定义应用于色差效果的偏移类型,影响颜色通道位移的方向和性质。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
- mixing_type
|
|
- 控制原始和偏移颜色通道的混合方式,影响色差效果的整体强度和外观。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
- transpose
|
|
- 决定在应用色差效果之前是否以及如何转置图像,影响效果的方向。
|
|
- Comfy dtype: COMBO[STRING]
|
|
- Python dtype: str
|
|
- colors
|
|
- 选择要偏移的颜色通道,直接影响色差效果的颜色组成。
|
|
- Comfy dtype: COMBO[STRING]
|
|
- Python dtype: str
|
|
- lens_curvy
|
|
- 调整镜头效果的曲率,修改色差在图像上的显著程度。
|
|
- Comfy dtype: FLOAT
|
|
- Python dtype: float
|
|
|
|
# Output types
|
|
- image
|
|
- 应用了色差效果的转换后图像,展示了对原始内容添加的视觉增强或艺术效果。
|
|
- Comfy dtype: IMAGE
|
|
- Python dtype: torch.Tensor
|
|
|
|
|
|
## Usage tips
|
|
- Infra type: `GPU`
|
|
- Common nodes: unknown
|
|
|
|
|
|
## Source code
|
|
```python
|
|
class ImageEffectsLensChromaticAberration:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"images": ("IMAGE",),
|
|
"shift": ("INT", {
|
|
"default": 10,
|
|
"step": 1,
|
|
}),
|
|
"method": (["reflect", "edge", "constant"],),
|
|
"shift_type": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 4,
|
|
"step": 1,
|
|
}),
|
|
"mixing_type": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 4,
|
|
"step": 1,
|
|
}),
|
|
"transpose": (["none", "rotate", "reflect"],),
|
|
"colors": (["rb", "rg", "gb"],),
|
|
"lens_curvy": ("FLOAT", {
|
|
"default": 1.0,
|
|
"max": 15.0,
|
|
"step": 0.1,
|
|
}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "node"
|
|
CATEGORY = "image/effects/lens"
|
|
|
|
def node(self, images, shift, method, shift_type, mixing_type, transpose, colors, lens_curvy):
|
|
# noinspection PyUnboundLocalVariable
|
|
def apply(image):
|
|
img = image.clone().detach()
|
|
|
|
if transpose == "rotate":
|
|
img = img.permute(1, 0, 2)
|
|
elif transpose == "none" or transpose == "reflect":
|
|
pass
|
|
else:
|
|
raise ValueError("Not existing reverse.")
|
|
|
|
r, g, b = img[:, :, 0:3].split(1, 2)
|
|
height, width = img[:, :, 0].shape
|
|
|
|
def get_space(size, min_val, max_val):
|
|
size += shift * 2
|
|
|
|
if min_val == max_val:
|
|
return torch.linspace(min_val, max_val, size)
|
|
else:
|
|
return radialspace_1D(size, lens_curvy, 1.0, min_val, max_val)
|
|
|
|
if shift_type == 1:
|
|
f_shifts = get_space(height, -shift, shift)
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = get_space(width, -shift, shift)
|
|
elif shift_type == 2:
|
|
f_shifts = get_space(height, 0, shift)
|
|
f_shifts = torch.flip(f_shifts, dims=(0,))
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = get_space(width, 0, shift)
|
|
t_shifts = torch.flip(t_shifts, dims=(0,))
|
|
elif shift_type == 3:
|
|
f_shifts = get_space(height, 0, shift)
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = get_space(width, 0, shift)
|
|
elif shift_type == 4:
|
|
f_shifts = get_space(height, shift, shift)
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = get_space(width, shift, shift)
|
|
else:
|
|
raise ValueError("Not existing shift_type.")
|
|
|
|
if mixing_type == 1:
|
|
f_shifts = f_shifts
|
|
s_shifts = -f_shifts
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = t_shifts
|
|
c_shifts = -t_shifts
|
|
elif mixing_type == 2:
|
|
f_shifts = -f_shifts
|
|
s_shifts = f_shifts
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = -t_shifts
|
|
c_shifts = t_shifts
|
|
elif mixing_type == 3:
|
|
f_shifts = f_shifts
|
|
s_shifts = f_shifts
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = t_shifts
|
|
c_shifts = t_shifts
|
|
elif mixing_type == 4:
|
|
f_shifts = -f_shifts
|
|
s_shifts = -f_shifts
|
|
|
|
if transpose == "reflect":
|
|
t_shifts = -t_shifts
|
|
c_shifts = -t_shifts
|
|
else:
|
|
raise ValueError("Not existing mixing_type.")
|
|
|
|
if colors == "rb":
|
|
def cat(f_value, s_value):
|
|
return torch.cat([f_value, g, s_value], 2)
|
|
|
|
f = r
|
|
s = b
|
|
elif colors == "rg":
|
|
def cat(f_value, s_value):
|
|
return torch.cat([f_value, s_value, b], 2)
|
|
|
|
f = r
|
|
s = g
|
|
elif colors == "gb":
|
|
def cat(f_value, s_value):
|
|
return torch.cat([r, f_value, s_value], 2)
|
|
|
|
f = g
|
|
s = b
|
|
else:
|
|
raise ValueError("Not existing colors.")
|
|
|
|
f_pad = F.pad(f.squeeze(), [shift, shift], padding_mode=method).unsqueeze(2)
|
|
s_pad = F.pad(s.squeeze(), [shift, shift], padding_mode=method).unsqueeze(2)
|
|
|
|
f_shifted = torch.zeros_like(f_pad)
|
|
s_shifted = torch.zeros_like(s_pad)
|
|
|
|
for i in range(height + (shift * 2)):
|
|
f_shifted[i] = torch.roll(f_pad[i], shifts=int(f_shifts[i]), dims=0)
|
|
s_shifted[i] = torch.roll(s_pad[i], shifts=int(s_shifts[i]), dims=0)
|
|
|
|
if transpose == "reflect":
|
|
for i in range(width + (shift * 2)):
|
|
f_shifted[:, i] = torch.roll(f_shifted[:, i], shifts=int(t_shifts[i]), dims=0)
|
|
s_shifted[:, i] = torch.roll(s_shifted[:, i], shifts=int(c_shifts[i]), dims=0)
|
|
|
|
f_result = f_shifted[shift:-shift, shift:-shift, :]
|
|
s_result = s_shifted[shift:-shift, shift:-shift, :]
|
|
|
|
img[:, :, 0:3] = cat(f_result, s_result)
|
|
|
|
if transpose == "rotate":
|
|
img = img.permute(1, 0, 2)
|
|
elif transpose == "none" or transpose == "reflect":
|
|
pass
|
|
else:
|
|
raise ValueError("Not existing reverse.")
|
|
|
|
return img
|
|
|
|
return (torch.stack([
|
|
apply(images[i]) for i in range(len(images))
|
|
]),)
|
|
|
|
```
|