Nodes/ComfyUI-Gemini-Spatial/Gemini Spatial to Bboxes
ComfyUI Node

Gemini Spatial to Bboxes

Turn Gemini's boxes into real masks you can inpaint and detail with

By nova452·Created 3 months ago·Updated 3 months ago· 0
Gemini Spatial to Bboxes
  • image
  • mask
  • masks
  • bboxes_json
  • match_count
json_output[]
labelhead
drop_size0.0

This is the node that makes the pack useful. GeminiSpatialNode hands you a pile of JSON saying "the dog is at coordinates 120,80,340,290" - which is neat but doesn't do anything on its own. Feed that JSON here, along with the image, and you get actual ComfyUI masks and clean pixel-space bounding boxes you can wire into inpainting, detailing, or region conditioning.

Think of it as the missing adapter between a vision model's words and ComfyUI's mask machinery. The whole auto-detailing loop - detect a region, re-render it, paste it back - normally needs a local detector like GroundingDINO or a YOLO plus SAM to build masks. This node replaces the entire detection stage with one API call that's already happened upstream, then does the same box-to-mask conversion locally, for free, on your GPU or lack thereof.

How it works

The node parses the JSON (it tolerates markdown fences, so a ```json-wrapped response works), flattens it into a list of detections, and filters for whatever label you care about. It converts each box from Gemini's 0–1000 normalized space into pixel coordinates using your image's actual dimensions, then builds:

  • mask - a single mask that's the union of every matching box. One region, one mask.
  • masks - a batched tensor of individual masks, one per box. For "process each of these five faces separately" workflows.
  • bboxes_json - the boxes in pixel space as [{"x1","y1","x2","y2","width","height","label"}]. This is the exact format GeminiSpatialBboxToCoordsNode expects next.
  • match_count - an INT telling you how many boxes survived filtering. The single most useful output for debugging.

The inputs

  • json_output - paste or wire in the json_output from GeminiSpatialNode. Default "[]", multiline.
  • image - used only for its dimensions. The masks are full-image-size, so it needs to know how big the picture is.
  • label - a comma-separated substring filter against the label each detection carries. Default "head", which hints at the author's use case. If Gemini wrote "dog", you match with dog. Put multiple comma-separated labels in to catch variations.
  • drop_size - a percentage (0–100) of total image area; any box smaller than that gets dropped. Default 0 = keep everything. This is your "ignore the speck in the corner" dial.

Wiring it in

The mask and masks outputs plug straight into anything that takes a MASK - a SetLatentNoiseMask for inpaint, a detailer that accepts a mask input, or a mask-to-SEGS converter if you want to feed the Impact Pack's DetailerForEach loop and get the full detect-crop-render-paste pipeline. Because you're driving it from Gemini instead of a trained detector, you can target things YOLO never learned - "the red umbrella", "the middle person" - the whole point of promptable masking.

Troubleshooting

  • match_count is 0 - your label doesn't substring-match anything Gemini wrote back. Look at the raw json_output first; the labels there are the truth. Case and spacing count.
  • Everything got dropped - drop_size too aggressive. Remember it's a percentage of image area, not pixels.
  • Boxes feel too tight - a known property of grounding boxes generally: they hug the object, so pad the mask a bit before a detail pass or the edges of your re-render will show. The same caveat applies whether the box came from GroundingDINO, Qwen-VL, or this pack.

One gotcha: this node can't fix a bad detection. If Gemini placed the box wrong, you're masking the wrong spot, and no amount of node fiddling changes that - that's what the annotated_image preview upstream is for.

CategoryGemini/Spatial

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
json_outputSTRING[]
labelSTRINGhead
drop_sizeFLOAT0.00–100

Outputs (4)

NameTypeDescription
maskMASK
masksMASK
bboxes_jsonSTRING
match_countINT