π Gemini Mask Crop & Resize
Crop per mask, then fit every tile onto the same canvas
- image
- masks
- cropped_batch
- cropped_alphas
- bbox_info
Gemini Mask Crop & Resize does what Gemini Mask Crop does - cut one crop per mask out of an image - and then goes one step further: it fits every crop onto the same-sized target canvas. That's the answer to a specific pain: crops from different masks come out at wildly different aspect ratios, and a model or node downstream wants a uniform tile. This node normalizes them without distorting anything.
It's local, no API, no key. In the AI/Image Analysis/Google menu like its sibling utilities.
How it works
Same core as Mask Crop: tight bounding box per mask, bbox_padding for context, apply_mask to optionally zero the background (keep it off for the same reason as the sibling - refinement models want context). The difference is the destination. Each crop is scaled to fit inside a canvas of target_width Γ target_height with its aspect ratio preserved, padded to fill the rest. The padding color is pad_color as an RGB string like 0, 0, 0. upscale_method (nearest-exact, bilinear, bicubic, area) picks the interpolation for that fit.
Two subtle controls worth knowing:
- divisible_by (default 2) rounds the target canvas down to a multiple, which matters when the tiles feed a model with a divisibility requirement or a node like
ImageResizeKJv2that shares the convention. - The canvas is a fit, not a crop-to-fill - nothing gets cut off, gaps just get padding. If you need crops to fill the tile (overlapping the edges), that's a different node; this one is the "keep everything, pad the rest" version.
Outputs
- cropped_batch - one IMAGE batch, every crop at
target_widthΓtarget_height. Uniform, model-ready. - cropped_alphas - the matching alpha masks for each tile.
- bbox_info - JSON of the crop rectangles, if you need the source geometry for stitching back.
Note the output difference vs. Mask Crop: this node emits a batch and alphas, not a native-size list. If your refinement node iterates a list (Gemini Batch Refine does), you'll want Mask Crop's images_list instead - or feed this batch to something that accepts a uniform batch directly. Grab the wrong one and you'll get a shape error, which is really just the engine telling you which lane you're in.
When to reach for it
Use Crop & Resize when the downstream stage demands a fixed canvas - feeding a model with a set input size, building a grid, or normalizing mixed crops before they hit a batch-processing node. Use plain Mask Crop when you want to preserve native resolution and let a list-capable node iterate. The one to reach for is dictated by your next node, not by taste.
Install
Pack-wide install: ComfyUI Manager search "ComfyUI_Gemini", or clone and pip:
cd ComfyUI/custom_nodes
git clone https://github.com/aarnoatchi/ComfyUI_Gemini
pip install -r ComfyUI_Gemini/requirements.txt
No extra dependencies for this node beyond what the pack already pulls in (google-genai, python-dotenv, scipy - the first two exist because the pack's API half needs them). Restart, and it's under AI/Image Analysis/Google. If tiles come back with odd margins, check divisible_by against your target - a target of 2048 with divisible_by 64 rounds to 2048, but a target of 2050 would quietly round down to 2048 and your padding math shifts by two pixels. It's the kind of silent detail that only shows up when you compare tiles side by side.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Original full-resolution image. Single-batch (1, H, W, 3); batch[0] is used. | |
| masks | MASK | Batched masks (N, H, W). One image segment is cropped + resized per mask. | |
| target_widthopt | INT | 20481β8192 | Width of the output canvas each crop is fitted into (aspect preserved, padded). |
| target_heightopt | INT | 20481β8192 | Height of the output canvas each crop is fitted into (aspect preserved, padded). |
| upscale_methodopt | COMBO | nearest-exact | Interpolation used when resizing each crop to the target canvas. |
| pad_coloropt | STRING | 0, 0, 0 | RGB 0-255 fill for the padding around each fitted crop, e.g. '0, 0, 0' for black. |
| divisible_byopt | INT | 21β256 | Round the target canvas down to a multiple of this (matches ImageResizeKJv2). |
| bbox_paddingopt | INT | 00β512 | Pixels of context to include around each mask's tight bbox before cropping. |
| apply_maskopt | BOOLEAN | false | If true, zero pixels outside the silhouette within each crop before resizing. Default False keeps the bbox tile intact β most refinement models want context. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| cropped_batch | IMAGE | β |
| cropped_alphas | MASK | β |
| bbox_info | STRING | β |