mirror of
https://github.com/justUmen/Bjornulf_custom_nodes.git
synced 2026-03-25 22:35:43 -03:00
v1.1.8
This commit is contained in:
@@ -17,12 +17,14 @@ class CombineBackgroundOverlay:
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_TYPES = ("IMAGE", "MASK")
|
||||
RETURN_NAMES = ("image", "mask")
|
||||
FUNCTION = "combine_background_overlay"
|
||||
CATEGORY = "Bjornulf"
|
||||
|
||||
def combine_background_overlay(self, background, overlay, horizontal_position, vertical_position, mask=None):
|
||||
results = []
|
||||
output_masks = []
|
||||
|
||||
# Process the first background image
|
||||
bg = background[0].cpu().numpy()
|
||||
@@ -45,7 +47,7 @@ class CombineBackgroundOverlay:
|
||||
else:
|
||||
ov_img = Image.fromarray(ov, 'RGB')
|
||||
|
||||
# Apply mask if provided
|
||||
# Apply mask if provided - INVERTED LOGIC: mask removes opacity
|
||||
if mask is not None:
|
||||
mask_idx = min(i, mask.shape[0] - 1)
|
||||
m = mask[mask_idx].cpu().numpy()
|
||||
@@ -56,15 +58,18 @@ class CombineBackgroundOverlay:
|
||||
if mask_img.size != ov_img.size:
|
||||
mask_img = mask_img.resize(ov_img.size, Image.LANCZOS)
|
||||
|
||||
# INVERT THE MASK - white areas in mask become transparent
|
||||
inverted_mask = Image.eval(mask_img, lambda x: 255 - x)
|
||||
|
||||
if ov_img.mode == 'RGBA':
|
||||
# Combine overlay’s alpha with mask
|
||||
# Combine overlay's alpha with inverted mask
|
||||
ov_alpha = np.array(ov_img.split()[3], dtype=np.float32) / 255.0
|
||||
mask_alpha = np.array(mask_img, dtype=np.float32) / 255.0
|
||||
effective_alpha = (ov_alpha * mask_alpha * 255).astype(np.uint8)
|
||||
inverted_mask_alpha = np.array(inverted_mask, dtype=np.float32) / 255.0
|
||||
effective_alpha = (ov_alpha * inverted_mask_alpha * 255).astype(np.uint8)
|
||||
ov_img.putalpha(Image.fromarray(effective_alpha, 'L'))
|
||||
else:
|
||||
# Use mask as alpha for RGB overlay
|
||||
ov_img.putalpha(mask_img)
|
||||
# Use inverted mask as alpha for RGB overlay
|
||||
ov_img.putalpha(inverted_mask)
|
||||
else:
|
||||
if ov_img.mode == 'RGB':
|
||||
# Add fully opaque alpha for RGB overlay
|
||||
@@ -82,26 +87,90 @@ class CombineBackgroundOverlay:
|
||||
result = Image.new('RGBA', bg_img.size, (0, 0, 0, 0))
|
||||
result.paste(bg_img, (0, 0))
|
||||
|
||||
# Paste overlay with alpha blending
|
||||
# Create output mask - start with background alpha or white
|
||||
if bg_has_alpha:
|
||||
output_mask_img = bg_img.split()[3].copy()
|
||||
else:
|
||||
output_mask_img = Image.new('L', bg_img.size, 255)
|
||||
|
||||
# Paste overlay directly on top (no alpha blending)
|
||||
if x + ov_img.width > 0 and y + ov_img.height > 0 and x < result.width and y < result.height:
|
||||
temp = Image.new('RGBA', result.size, (0, 0, 0, 0))
|
||||
temp.paste(ov_img, (x, y), ov_img)
|
||||
result = Image.alpha_composite(result.convert('RGBA'), temp)
|
||||
# Convert overlay to RGB if needed for direct paste
|
||||
if ov_img.mode == 'RGBA':
|
||||
ov_rgb = Image.new('RGB', ov_img.size, (255, 255, 255))
|
||||
ov_rgb.paste(ov_img, mask=ov_img.split()[3])
|
||||
ov_paste = ov_rgb
|
||||
paste_mask = ov_img.split()[3]
|
||||
else:
|
||||
ov_paste = ov_img
|
||||
paste_mask = None
|
||||
|
||||
# Apply input mask if provided - UPDATED LOGIC FOR INVERTED MASK
|
||||
if mask is not None:
|
||||
mask_idx = min(i, mask.shape[0] - 1)
|
||||
m = mask[mask_idx].cpu().numpy()
|
||||
m = np.clip(m * 255, 0, 255).astype(np.uint8)
|
||||
input_mask = Image.fromarray(m, 'L')
|
||||
if input_mask.size != ov_img.size:
|
||||
input_mask = input_mask.resize(ov_img.size, Image.LANCZOS)
|
||||
|
||||
# INVERT THE INPUT MASK
|
||||
inverted_input_mask = Image.eval(input_mask, lambda x: 255 - x)
|
||||
|
||||
if paste_mask is not None:
|
||||
# Combine overlay alpha with inverted input mask
|
||||
paste_mask_array = np.array(paste_mask, dtype=np.float32) / 255.0
|
||||
inverted_input_mask_array = np.array(inverted_input_mask, dtype=np.float32) / 255.0
|
||||
combined_mask_array = (paste_mask_array * inverted_input_mask_array * 255).astype(np.uint8)
|
||||
paste_mask = Image.fromarray(combined_mask_array, 'L')
|
||||
else:
|
||||
# Use inverted input mask directly
|
||||
paste_mask = inverted_input_mask
|
||||
|
||||
# Paste overlay directly onto result
|
||||
result.paste(ov_paste, (x, y), paste_mask)
|
||||
|
||||
# Update output mask
|
||||
if paste_mask is not None:
|
||||
temp_mask = Image.new('L', result.size, 0)
|
||||
temp_mask.paste(paste_mask, (x, y))
|
||||
|
||||
# Combine masks - overlay mask replaces background mask where it exists
|
||||
output_mask_array = np.array(output_mask_img, dtype=np.float32)
|
||||
temp_mask_array = np.array(temp_mask, dtype=np.float32)
|
||||
combined_mask_array = np.maximum(output_mask_array, temp_mask_array).astype(np.uint8)
|
||||
output_mask_img = Image.fromarray(combined_mask_array, 'L')
|
||||
else:
|
||||
# No mask - overlay covers background completely in paste area
|
||||
temp_mask = Image.new('L', result.size, 0)
|
||||
temp_mask.paste(Image.new('L', ov_paste.size, 255), (x, y))
|
||||
|
||||
output_mask_array = np.array(output_mask_img, dtype=np.float32)
|
||||
temp_mask_array = np.array(temp_mask, dtype=np.float32)
|
||||
combined_mask_array = np.maximum(output_mask_array, temp_mask_array).astype(np.uint8)
|
||||
output_mask_img = Image.fromarray(combined_mask_array, 'L')
|
||||
|
||||
# Convert result back to tensor
|
||||
result_np = np.array(result)
|
||||
if bg_has_alpha:
|
||||
result_tensor = torch.from_numpy(result_np).float() / 255.0
|
||||
else:
|
||||
# Convert RGBA to RGB, blending with white only where needed
|
||||
if result_np.shape[2] == 4:
|
||||
if result_np.shape[2] == 4:
|
||||
# Convert RGBA back to RGB if background was RGB
|
||||
if not bg_has_alpha:
|
||||
alpha = result_np[:, :, 3:4] / 255.0
|
||||
rgb = result_np[:, :, :3]
|
||||
white_bg = np.ones_like(rgb) * 255
|
||||
result_np = (rgb * alpha + white_bg * (1 - alpha)).astype(np.uint8)
|
||||
result_tensor = torch.from_numpy(result_np).float() / 255.0
|
||||
else:
|
||||
result_tensor = torch.from_numpy(result_np).float() / 255.0
|
||||
else:
|
||||
result_tensor = torch.from_numpy(result_np).float() / 255.0
|
||||
|
||||
# Convert output mask to tensor
|
||||
output_mask_tensor = torch.from_numpy(np.array(output_mask_img)).float() / 255.0
|
||||
|
||||
results.append(result_tensor)
|
||||
output_masks.append(output_mask_tensor)
|
||||
|
||||
final_result = torch.stack(results)
|
||||
return (final_result,)
|
||||
final_masks = torch.stack(output_masks)
|
||||
return (final_result, final_masks)
|
||||
Reference in New Issue
Block a user