Nodes/ComfyUI CV/CV Keep Largest Component
ComfyUI Node

CV Keep Largest Component

One blob, everything else gone

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Keep Largest Component
  • image
  • mask
  • area
  • found
◄connectivity8►

Your mask is a mess. The subject is there, but so are a dozen speckles of noise, a bit of stray background, and maybe a second thing moving in frame. You don't want the mess cleaned up by hand - you want the biggest blob and nothing else. CV Keep Largest Component runs cv2.connectedComponentsWithStats and keeps exactly one connected component: the one with the largest area. No probe point, no prompt, no threshold to tune.

That last bit is the whole personality of the node, and it's worth contrasting with its sibling. CV Select Component At Point keeps whatever blob covers a coordinate you supply - useful when you know where the thing is. This one just takes the biggest, which is the right call when you don't have a point and the subject is obviously dominant.

Inputs and outputs

image is the binary input - non-zero is foreground - typed as COMFY_MATCHTYPE_V3, which is the pack's way of saying "hand me an IMAGE or a MASK and I'll give the same type back," frame 0 of a batch either way. connectivity is the classic 4 vs 8: 8 also links diagonal pixels, 4 only direct neighbours. For organic subjects 8 is the default and the sensible one; drop to 4 when diagonal touching would wrongly fuse two separate objects.

Out you get mask (a 0/255 mask of the kept component, in your input's format), area (its pixel area, 0 if there was nothing), and found. That found flag is the honest part: an empty mask - no foreground at all - yields found=false and an empty mask rather than an exception. Gate a downstream branch on it and a failed segmentation becomes a route through your graph instead of a red node.

Where it belongs in a pipeline

It's the standard cleanup step before seeding a seeded segmentation: run CV GrabCut or a watershed with a single dominant blob as the seed and you stop paying for the noise. It's also a decent motion-isolation trick - thin out scattered differences and the one big mover survives. And it's the cheap answer to "which of these connected regions is the subject" when you've already thresholded and the answer is obviously the large one.

Where it's the wrong tool: multi-subject frames. If you have three faces and you keep the largest component, you silently deleted two of them and nothing in the graph will tell you. That's a job for CV Connected Components (Split Mask), which emits one mask per blob, or for CV Select Component At Point if you can say where each one is. "Largest" also isn't the same as "mine" - a connected shadow or a background streak can out-area your subject, and area is the only criterion here. Preview the mask before you build a workflow around it.

Install

ComfyUI Manager, search the pack title comfyui_cv (bmad4ever/comfyui_cv). Or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv

Restart ComfyUI. Two prerequisites: Python ≥ 3.12, and a ComfyUI recent enough for the V3 node API - this pack declares its nodes with io.ComfyNode/io.Schema and defines no NODE_CLASS_MAPPINGS, so a stale install won't load it. Its one dependency:

pip install "opencv-contrib-python-headless~=5.0.0.93"

The pin is the curated reference build, and the wheel has to stay contrib. All four OpenCV distributions share a single site-packages/cv2; install a non-contrib wheel over a contrib one and the contrib submodules are silently emptied, taking contrib nodes out of the node menu with nothing in the log. The pack includes tools/repair_opencv_contrib.py - --check to diagnose, --apply to repair.

Small traps

Wrong connectivity, fused blobs. If two objects that touch diagonally came out as one, set connectivity to 4.

You fed it a grayscale photo, not a mask. "Non-zero is foreground" is literal here. A hazy background means everything is one enormous component and you've kept the entire frame. Threshold first - the pack has nodes for it.

Silent no-op. If you get an unchanged image back, check whether there was only one component to begin with. The node is doing what you asked.

Standing caveat from the README, which applies to everything in this pack: heavy LLM assistance in the code, sample-tuned example workflows, updates unplanned, and an explicit recommendation not to trust it in production without reviewing the source. A connected-components node is small enough that you can read it in two minutes, and that's probably the right amount of diligence here.

Categoryimage/CV/contours

Inputs (2)

NameTypeDefaultDescription
imageCOMFY_MATCHTYPE_V3Binary image (or MASK); non-zero = foreground. The mask comes back in this input's format. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
connectivityCOMBO88 also connects diagonal pixels; 4 only direct neighbours.

Outputs (3)

NameTypeDescription
maskCOMFY_MATCHTYPE_V30/255 mask of the largest component, in the image input's format.
areaINTPixel area of the kept component (0 if none).
foundBOOLEAN—