LayerUtility: RestoreCropBox¶
Documentation¶
- Class name:
LayerUtility: RestoreCropBox
- Category:
😺dzNodes/LayerUtility
- Output node:
False
The RestoreCropBox node is designed to reintegrate a previously cropped image back into its original background, optionally utilizing an inversion mask and a specific crop box to accurately place the cropped image. This functionality is crucial for image editing tasks where maintaining the original context of the image is necessary after modifications.
Input types¶
Required¶
background_image
- The original image from which a portion was cropped. This image serves as the canvas where the cropped image will be placed back.
- Comfy dtype:
IMAGE
- Python dtype:
IMAGE
croped_image
- The cropped portion of the image that needs to be restored onto the original background.
- Comfy dtype:
IMAGE
- Python dtype:
IMAGE
invert_mask
- A boolean flag indicating whether the mask used for cropping should be inverted during the restoration process.
- Comfy dtype:
BOOLEAN
- Python dtype:
BOOLEAN
crop_box
- Defines the specific area (box) on the background image where the cropped image will be placed.
- Comfy dtype:
BOX
- Python dtype:
BOX
Optional¶
croped_mask
- An optional mask that was used during the cropping process. It can be utilized for more precise restoration.
- Comfy dtype:
MASK
- Python dtype:
MASK
Output types¶
image
- Comfy dtype:
IMAGE
- The resulting image after the cropped image has been restored onto the original background.
- Python dtype:
IMAGE
- Comfy dtype:
mask
- Comfy dtype:
MASK
- The mask used during the restoration process, which can be useful for further image processing steps.
- Python dtype:
MASK
- Comfy dtype:
Usage tips¶
- Infra type:
CPU
- Common nodes: unknown
Source code¶
class RestoreCropBox:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(self):
return {
"required": {
"background_image": ("IMAGE", ),
"croped_image": ("IMAGE",),
"invert_mask": ("BOOLEAN", {"default": False}), # 反转mask#
"crop_box": ("BOX",),
},
"optional": {
"croped_mask": ("MASK",),
}
}
RETURN_TYPES = ("IMAGE", "MASK", )
RETURN_NAMES = ("image", "mask", )
FUNCTION = 'restore_crop_box'
CATEGORY = '😺dzNodes/LayerUtility'
def restore_crop_box(self, background_image, croped_image, invert_mask, crop_box,
croped_mask=None
):
b_images = []
l_images = []
l_masks = []
ret_images = []
ret_masks = []
for b in background_image:
b_images.append(torch.unsqueeze(b, 0))
for l in croped_image:
l_images.append(torch.unsqueeze(l, 0))
m = tensor2pil(l)
if m.mode == 'RGBA':
l_masks.append(m.split()[-1])
else:
l_masks.append(Image.new('L', size=m.size, color='white'))
if croped_mask is not None:
if croped_mask.dim() == 2:
croped_mask = torch.unsqueeze(croped_mask, 0)
l_masks = []
for m in croped_mask:
if invert_mask:
m = 1 - m
l_masks.append(tensor2pil(torch.unsqueeze(m, 0)).convert('L'))
max_batch = max(len(b_images), len(l_images), len(l_masks))
for i in range(max_batch):
background_image = b_images[i] if i < len(b_images) else b_images[-1]
croped_image = l_images[i] if i < len(l_images) else l_images[-1]
_mask = l_masks[i] if i < len(l_masks) else l_masks[-1]
_canvas = tensor2pil(background_image).convert('RGB')
_layer = tensor2pil(croped_image).convert('RGB')
ret_mask = Image.new('L', size=_canvas.size, color='black')
_canvas.paste(_layer, box=tuple(crop_box), mask=_mask)
ret_mask.paste(_mask, box=tuple(crop_box))
ret_images.append(pil2tensor(_canvas))
ret_masks.append(image2mask(ret_mask))
log(f"{NODE_NAME} Processed {len(ret_images)} image(s).", message_type='finish')
return (torch.cat(ret_images, dim=0), torch.cat(ret_masks, dim=0),)