✏️ Gemini Draw Diff Mask
Scribble on a photo, get an inpaint mask back
- clean_image
- drawn_image
- mask
- strokes
- preview
Gemini Draw Diff Mask turns a scribble into a mask. You give it a clean image and the same image with a shape drawn on it - a red circle, a highlight, an arrow, whatever color - and it compares the two, finds the drawn pixels, and returns them as a proper ComfyUI MASK. Draw a closed outline and it'll even fill the interior for you, which is a surprisingly elegant way to mark an inpaint region: paint a circle around the thing you want regenerated, and the mask is ready.
It's a local utility - no API, no key, runs instantly. The name says Gemini, but nothing about it touches Google; it's pure pixel diffing.
How it works
The mechanism is refreshingly honest: it subtracts the two images and thresholds the difference. A pixel counts as "drawn" when it's more than threshold away from the clean version (default 0.1 - lower is more sensitive, and the author's own note is to raise it if JPEG noise leaks through). Then it cleans the result up in a few passes.
- fill_region (default on) - fills the area enclosed by the drawing, turning an outline into a solid region. Off gives you just the strokes.
- close_gaps (default 3px) - bridges small breaks in a hand-drawn outline before filling, so an imperfect circle still fills as a circle. Only applies when
fill_regionis on. - min_area (default 16) - drops diff specks smaller than that many pixels: compression noise, stray dots.
- grow - expands the final mask outward by N pixels, e.g. to swallow the drawn line itself once you've filled.
- feather - softens the mask edge by N pixels with a Gaussian.
If you've ever hand-painted inpaint masks in an image editor and cursed the antialiased edges, this is the workflow-friendly version: draw, fill, grow a hair, feather, done.
The inputs that matter
The two required inputs are the whole deal: clean_image (the original, un-drawn photo) and drawn_image (the same picture with the mark on it). The one caveat buried in the tooltips is that they must be the same picture - the node is diffing pixels, so if you draw on a differently-resized or re-exported copy, the whole image diffs as "drawn." Same file, same dimensions.
Outputs are mask (the filled final mask - the one you wire into inpaint), strokes (just the raw strokes before filling, in case you want them separately), and preview (an IMAGE so you can eyeball what it detected without a separate preview node).
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
It's one of the rare nodes in this pack that works even if scipy is missing - it has a pure-torch fallback for the fill/closing steps, just slower and cruder. Still, install the requirements as-is and you'll get the scipy path. Restart ComfyUI and it's under AI/Image Analysis/Google.
Common failure: your "drawn" region comes out huge because JPEG artifacts or a subtle brightness shift across the whole frame crossed the threshold - that's the threshold too low, so raise it and drop min_area cleanup in. And if you draw in a program that adds a white border or letterboxing, trim it off first - the node will happily interpret a changed border as a giant drawn stroke.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| clean_image | IMAGE | The original, un-drawn image. | |
| drawn_image | IMAGE | The same image with a shape/mark drawn on it. Must be the same picture. | |
| thresholdopt | FLOAT | 0.100–1 | How different a pixel must be to count as 'drawn'. Lower = more sensitive. Raise it if JPEG noise leaks through. |
| fill_regionopt | BOOLEAN | true | ON: fill the area enclosed by the drawing (outline → solid). OFF: keep just the strokes. |
| close_gapsopt | INT | 30–128 | Bridge small breaks in the outline (in px) before filling, so an imperfect circle still fills. Only used when fill_region is ON. |
| min_areaopt | INT | 160–1000000 | Remove diff specks smaller than this many pixels (compression noise, stray dots). |
| growopt | INT | 00–256 | Expand the final mask outward by N px (e.g. to cover the drawn line itself when filling). |
| featheropt | INT | 00–256 | Soften the final mask edge by N px (Gaussian). |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |
| strokes | MASK | — |
| preview | IMAGE | — |