Nodes/opencv-comfyui/OpenCV grabCut_1
ComfyUI Node

OpenCV grabCut_1

Cutting a subject out of a photo, 1990s-style, with OpenCV grabCut

By geroldmeisinger·Created about a year ago·Updated about a year ago· 35
OpenCV grabCut_1
  • img
  • mask
  • bgdModel
  • fgdModel
  • nparray_0
  • nparray_1
  • nparray_2
rect
iterCount
mode

grabCut_1 is the OpenCV classic for pulling a foreground object out of a photo, wrapped as a node. It's the deterministic, no-model download - no BiRefNet, no SAM - graph-cut segmentation that's been in OpenCV for a decade and a half. If your subject sits inside a known rectangle and you want a mask without loading any weights, this is what you reach for.

Worth saying up front where it sits relative to the modern stack. The ML background-removal nodes the community actually recommends - BiRefNet, InSPyReNet - will beat grabCut on hair, fur, and semi-transparency every single time. grabCut is the different trade: zero VRAM, zero downloads, fully deterministic, and perfectly fine for a subject with clean edges inside a box you can define. It's also one of the rare segmentation options that runs happily on a single CPU core. Different tool, different job.

How it works

GrabCut takes your image plus a rough rectangle around the foreground and iteratively models "definitely background", "probably background", "probably foreground", and "definitely foreground" using color statistics plus a graph cut. Run it a few iterations and you get a labeled mask back. The mask input is where you're told the answer lives - with mode = 0 (GC_INIT_WITH_RECT) the rectangle drives everything and the mask is ignored.

The inputs that matter

  • img - your nparray (convert with Image2Nparray first; Comfy's IMAGE tensor won't feed it directly).
  • rect - a STRING literal for the rectangle, e.g. [100, 100, 300, 300] as x, y, width, height. This is one of those ast.parse() composite params, so type it as a Python literal. Wrong syntax gets you invalid syntax (<unknown>, line 0).
  • mask - an all-zero uint8 array of the same size as the image when using rect mode.
  • bgdModel, fgdModel - the two internal 1×65 float64 buffers grabCut keeps between iterations. Here's the dragon: this auto-generated node lists them as required, so you have to wire something in. In raw OpenCV you'd pass np.zeros((1,65), np.float64).
  • iterCount - iterations; 5 is a fine starting point.
  • mode - 0 for init-with-rect, 1 for init-with-mask.

Three outputs: nparray_0 is the resulting mask (0/2 = background, 1/3 = foreground), and nparray_1/nparray_2 are the updated bgdModel and fgdModel. If you run grabCut iteratively, feed those back in on the next pass.

Installing it

Same as every node in this pack - install the whole pack:

cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui

or search "OpenCV" in ComfyUI Manager. Then make sure OpenCV is present:

pip install opencv-contrib-python

No model files to fetch. That's the whole install.

Gotchas

Where people get burned: the required model buffers are the awkward part - most Comfy users don't have a node handy that emits a zeroed float64 array, so this node is genuinely fiddly compared to one-click ML cutouts. And remember the pack is auto-generated, so it's "ugly and complex" by the author's own admission. It works - but it's a scalpel, not a button.

You also can't feed a grayscale 8UC1 image to grabCut and expect a color segmentation - it wants the 3-channel image. If OpenCV complains about image type, check your cvtColor step.

Categoryimage/OpenCV

Inputs (7)

NameTypeDefaultDescription
imgNPARRAY
maskNPARRAY
rectSTRING
bgdModelNPARRAY
fgdModelNPARRAY
iterCountINT
modeINT

Outputs (3)

NameTypeDescription
nparray_0NPARRAY
nparray_1NPARRAY
nparray_2NPARRAY