Dreamspire's picture
custom_nodes
f2dbf59
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:
@classmethod
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:
@classmethod
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:
@classmethod
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
@classmethod
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',
}