Crop Mask Holes
The background-cropping node with the mouthful of a name
- mask
- image
- cropped_masks
- cropped_images
- crop_boxes
The name is absurd - "QuantizedPadded" tells you nothing - but the job is genuinely useful. You've got a binary mask, and the mask's connected regions each represent something you want to process separately. This node crops each of those regions out, and it's opinionated about how: every crop's dimensions get rounded up to a multiple of an alignment value, and any overflow past the image edge gets padded with edge replication.
Why "holes"? In the pack's panel world, the white background regions between panels are the holes you want to regenerate or clean up. The node's own description spells it out: "Crop all holes (background regions) in a binary mask and corresponding areas in an optional image." So the classic use is: you detected or built panels, converted them to a mask, and now you want to generate each panel's content - or its background - as separate, model-friendly crops.
How it works
It's straightforward computer vision. The mask is binarized, then cv2.connectedComponentsWithStats finds every connected blob. Each blob becomes a crop box, which is expanded so its width and height are multiples of align_multiple (the expansion is centered, then clamped to image bounds). If clamping means the box would extend past the edge, the crop is padded using OpenCV-style BORDER_REPLICATE - edge pixels copied outward - so every returned crop is exactly the aligned size, no smaller, no holes.
If you pass in an optional image, the same boxes crop the image in parallel, so you get mask and pixels that line up perfectly.
The inputs and outputs that matter
mask- the binary mask whose regions you want to crop.align_multiple- default 16. This is the number that makes crops "quantized." 16 is a sensible default because it keeps crops friendly to latent-space and video pipelines, where dimensions divisible by 8 or 16 avoid misalignment headaches.image- optional; crop the corresponding pixels at the same time.
Outputs, all as lists, all in the same order:
cropped_masks- one mask per region.cropped_images- the matching pixel crops (if you gave it an image).crop_boxes- theBBOXes, in original image coordinates, so you can paste crops back exactly where they came from.
That last list is the one beginners forget. Keep it - it's what lets you composite results back onto the page.
Installing it
Part of comfyui-panels - install via ComfyUI Manager (search "comfyui-panels") or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_panels
Restart, let Manager pull in shapely, matplotlib, and opencv-python. No models. The pack's workflows folder includes a "Crop Mask Holes node example" workflow worth loading to see it wired up.
Where people get burned
The mask and image dimensions must match - the node explicitly raises "Mask and image size mismatch" otherwise. And remember the mask is treated as binary: anything above zero is foreground, so a soft antialiased mask will crop differently than a hard one. If your crops come out shifted or padded unexpectedly, check that the mask isn't flipped or offset relative to the image before blaming the alignment.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| align_multiple | INT | 161–512 | — |
| imageopt | IMAGE | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| cropped_masks | MASK | — |
| cropped_images | IMAGE | — |
| crop_boxes | BBOX | — |