File size: 4,627 Bytes
f8944c1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | # ComfyUI Custom Node: Remove up to 13 images from a batch "at once"
# - Takes a batch (IMAGE)
# - Takes 13 index inputs
# - Removes all specified indices simultaneously (no shifting issues)
# - Index = -1 means "do not remove anything" (ignored)
#
# Save as:
# ComfyUI/custom_nodes/batch_remove_13_indices/__init__.py
# Restart ComfyUI, then find under: "Batch/Index"
import torch
class BatchRemoveImagesAt13Indices:
"""
Remove multiple images from a batch at once.
Notes:
- Indices are 0-based.
- Any index == -1 is ignored (meaning: remove nothing for that slot).
- Out-of-range indices are ignored (with a console warning).
- Duplicate indices are fine (removed once).
- If removal would produce an empty batch, this node raises an error.
"""
@classmethod
def INPUT_TYPES(cls):
# 13 separate INT inputs, defaulting to -1
idx_cfg = {"default": -1, "min": -1, "max": 10**9}
return {
"required": {
"images": ("IMAGE",),
"remove_index_01": ("INT", idx_cfg),
"remove_index_02": ("INT", idx_cfg),
"remove_index_03": ("INT", idx_cfg),
"remove_index_04": ("INT", idx_cfg),
"remove_index_05": ("INT", idx_cfg),
"remove_index_06": ("INT", idx_cfg),
"remove_index_07": ("INT", idx_cfg),
"remove_index_08": ("INT", idx_cfg),
"remove_index_09": ("INT", idx_cfg),
"remove_index_10": ("INT", idx_cfg),
"remove_index_11": ("INT", idx_cfg),
"remove_index_12": ("INT", idx_cfg),
"remove_index_13": ("INT", idx_cfg),
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("images",)
FUNCTION = "remove"
CATEGORY = "Batch/Index"
def remove(
self,
images,
remove_index_01,
remove_index_02,
remove_index_03,
remove_index_04,
remove_index_05,
remove_index_06,
remove_index_07,
remove_index_08,
remove_index_09,
remove_index_10,
remove_index_11,
remove_index_12,
remove_index_13,
):
if not torch.is_tensor(images):
raise TypeError("Expected 'images' to be a torch Tensor (ComfyUI IMAGE type).")
if images.ndim != 4:
raise ValueError(f"Expected 'images' with shape [B,H,W,C], got ndim={images.ndim}.")
b = int(images.shape[0])
if b <= 0:
raise ValueError("Input batch is empty.")
raw_indices = [
remove_index_01, remove_index_02, remove_index_03, remove_index_04, remove_index_05,
remove_index_06, remove_index_07, remove_index_08, remove_index_09, remove_index_10,
remove_index_11, remove_index_12, remove_index_13,
]
# Build a set of indices to remove (simultaneous removal)
remove_set = set()
for idx in raw_indices:
idx = int(idx)
# Sentinel: -1 means "do not remove"
if idx == -1:
continue
# Disallow other negative indices (since -1 is reserved)
if idx < -1:
print(f"[BatchRemove13] Ignoring invalid negative index {idx} (only -1 is allowed).")
continue
# Ignore out-of-range indices rather than clamping (clamping could remove the wrong image)
if idx < 0 or idx >= b:
print(f"[BatchRemove13] Ignoring out-of-range index {idx} for batch size {b}.")
continue
remove_set.add(idx)
# If nothing to remove, return original batch unchanged
if not remove_set:
return (images,)
if len(remove_set) >= b:
raise ValueError(
f"Removal would produce an empty batch (batch size {b}, requested removals {len(remove_set)})."
)
# Keep mask (True = keep, False = remove)
keep_mask = torch.ones((b,), dtype=torch.bool, device=images.device)
remove_idx = torch.tensor(sorted(remove_set), dtype=torch.long, device=images.device)
keep_mask[remove_idx] = False
out = images[keep_mask]
return (out,)
NODE_CLASS_MAPPINGS = {
"BatchRemoveImagesAt13Indices": BatchRemoveImagesAt13Indices,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"BatchRemoveImagesAt13Indices": "Batch: Remove 13 Indices (At Once)",
} |