Spaces:
Runtime error
Runtime error
import torch | |
from PIL import Image, ImageFilter, ImageOps | |
from comfy.utils import common_upscale | |
from .utils.image_convert import np2tensor, tensor2mask | |
from .utils.mask_utils import blur_mask, combine_mask, expand_mask, fill_holes, grow_mask, invert_mask | |
_CATEGORY = 'fnodes/masks' | |
class OutlineMask: | |
def INPUT_TYPES(cls): | |
return { | |
'required': { | |
'mask': ('MASK',), | |
'outline_width': ( | |
'INT', | |
{'default': 10, 'min': 1, 'max': 16384, 'step': 1}, | |
), | |
'tapered_corners': ('BOOLEAN', {'default': True}), | |
} | |
} | |
RETURN_TYPES = ('MASK',) | |
FUNCTION = 'execute' | |
CATEGORY = _CATEGORY | |
DESCRIPTION = '给遮罩添加轮廓线' | |
def execute(self, mask, outline_width, tapered_corners): | |
m1 = grow_mask(mask, outline_width, tapered_corners) | |
m2 = grow_mask(mask, -outline_width, tapered_corners) | |
m3 = combine_mask(m1, m2, 0, 0) | |
return (m3,) | |
class CreateBlurredEdgeMask: | |
def INPUT_TYPES(cls): | |
return { | |
'required': { | |
'width': ('INT', {'default': 1024, 'min': 0, 'max': 14096, 'step': 1}), | |
'height': ('INT', {'default': 1024, 'min': 0, 'max': 14096, 'step': 1}), | |
'border': ('INT', {'default': 0, 'min': 0, 'max': 4096, 'step': 1}), | |
'border_percent': ( | |
'FLOAT', | |
{'default': 0.05, 'min': 0.0, 'max': 2.0, 'step': 0.01}, | |
), | |
'blur_radius': ( | |
'INT', | |
{'default': 10, 'min': 0, 'max': 4096, 'step': 1}, | |
), | |
'blur_radius_percent': ( | |
'FLOAT', | |
{'default': 0.00, 'min': 0.0, 'max': 2.0, 'step': 0.01}, | |
), | |
}, | |
'optional': { | |
'image': ('IMAGE', {'tooltips': '如果未提供图像,将使用输入的宽度和高度创建一个白色图像。'}), | |
}, | |
} | |
RETURN_TYPES = ('MASK',) | |
FUNCTION = 'execute' | |
CATEGORY = _CATEGORY | |
DESCRIPTION = '根据指定图片创建模糊遮罩' | |
def execute(self, width, height, border, border_percent, blur_radius, blur_radius_percent, image=None): | |
if image is not None: | |
_, height, width, _ = image.shape | |
# 计算边框宽度 | |
border_width = int(min(width, height) * border_percent + border) | |
# 计算内部图像的尺寸 | |
inner_width = width - 2 * border_width | |
inner_height = height - 2 * border_width | |
# 创建内部白色图像 | |
inner_image = Image.new('RGB', (inner_width, inner_height), 'white') | |
# 扩展图像,添加黑色边框 | |
image_with_border = ImageOps.expand(inner_image, border=border_width, fill='black') | |
# 计算模糊半径 | |
blur_radius = int(min(width, height) * blur_radius_percent + blur_radius) | |
# 应用高斯模糊 | |
blurred_image = image_with_border.filter(ImageFilter.GaussianBlur(radius=blur_radius)) | |
# 转换为张量 | |
blurred_tensor = np2tensor(blurred_image) | |
blurred_image = blurred_tensor.unsqueeze(0) | |
return (tensor2mask(blurred_image),) | |
class MaskChange: | |
def INPUT_TYPES(cls): | |
return { | |
'required': { | |
'mask': ('MASK',), | |
'grow': ('INT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 1}), | |
'grow_percent': ( | |
'FLOAT', | |
{'default': 0.00, 'min': 0.00, 'max': 2.0, 'step': 0.01}, | |
), | |
'grow_tapered': ('BOOLEAN', {'default': False}), | |
'blur': ('INT', {'default': 0, 'min': 0, 'max': 4096, 'step': 1}), | |
'fill': ('BOOLEAN', {'default': False}), | |
}, | |
} | |
RETURN_TYPES = ('MASK', 'MASK') | |
RETURN_NAMES = ('mask', 'inverted_mask') | |
FUNCTION = 'execute' | |
CATEGORY = _CATEGORY | |
DESCRIPTION = '修改和处理遮罩' | |
def execute(self, mask, grow, grow_percent, grow_tapered, blur, fill): | |
grow_count = int(grow_percent * max(mask.shape)) + grow | |
if grow_count > 0: | |
mask = expand_mask(mask, grow_count, grow_tapered) | |
if fill: | |
mask = fill_holes(mask) | |
if blur > 0: | |
mask = blur_mask(mask, blur) | |
# mask = mask.squeeze(0).unsqueeze(-1) | |
return (mask, invert_mask(mask)) | |
class Depth2Mask: | |
def __init__(self): | |
pass | |
def INPUT_TYPES(cls): | |
return { | |
'required': { | |
'image_depth': ('IMAGE',), | |
'depth': ( | |
'FLOAT', | |
{'default': 0.2, 'min': 0.0, 'max': 1.0, 'step': 0.01, 'round': 0.001, 'display': 'number'}, | |
), | |
}, | |
} | |
RETURN_TYPES = ('MASK', 'MASK') | |
RETURN_NAMES = ('mask', 'mask_inverted') | |
FUNCTION = 'execute' | |
CATEGORY = _CATEGORY | |
DESCRIPTION = '将深度图像转换为遮罩' | |
def execute(self, image_depth, depth): | |
def upscale(image, upscale_method, width, height): | |
samples = image.movedim(-1, 1) | |
s = common_upscale(samples, width, height, upscale_method, 'disabled') | |
s = s.movedim(1, -1) | |
return (s,) | |
bs, height, width = image_depth.size()[0], image_depth.size()[1], image_depth.size()[2] | |
mask1 = torch.zeros((bs, height, width)) | |
image_depth = upscale(image_depth, 'lanczos', width, height)[0] | |
mask1 = (image_depth[..., 0] < depth).float() | |
return mask1, 1.0 - mask1 | |
MASK_CLASS_MAPPINGS = { | |
'OutlineMask-': OutlineMask, | |
'CreateBlurredEdgeMask-': CreateBlurredEdgeMask, | |
'MaskChange-': MaskChange, | |
'Depth2Mask-': Depth2Mask, | |
} | |
MASK_NAME_MAPPINGS = { | |
'OutlineMask-': 'Outline Mask', | |
'CreateBlurredEdgeMask-': 'Create Blurred Edge Mask', | |
'MaskChange-': 'Mask Change', | |
'Depth2Mask-': 'Depth to Mask', | |
} | |