Nodes/ComfyUI CV/CV Detect Blobs
ComfyUI Node

CV Detect Blobs

The shape filters that threshold + findContours can't give you

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Detect Blobs
  • image
  • keypoints
  • points
  • sizes
  • responses
  • count
◄blob_colordark blobs on a light background►
◄min_area25►
◄max_area5000►
◄min_circularity0.00►
◄min_convexity0.00►
◄min_inertia0.00►
◄min_threshold50►
◄max_threshold220►
◄threshold_step10►
◄min_repeatability2►
◄min_distance10►

CV Detect Blobs finds compact bright-or-dark spots - cells, dots, holes, bubbles, fiducials, poker chips - and filters them by shape.

That last part is the whole reason to use it. You can absolutely write "threshold, findContours, circle-fit" by hand, and then you'll spend an afternoon reimplementing area, circularity, convexity and inertia ratio filters. cv2.SimpleBlobDetector has all four built in, and they're what let you say "count the round things between 25 and 5000 pixels and ignore everything else" in one node.

It's a cv2 class rather than a function, so there's no raw wrapper - that's why it's hand-written. And note the honest limit: it produces no descriptors. If you need to match the blobs across frames, run CV Compute Descriptors on the keypoints it emits.

How it works

It thresholds the image at many levels between min_threshold and max_threshold in threshold_step increments and keeps the connected regions that stay stable across consecutive levels - that run of stability is min_repeatability (default 2, meaning a blob has to show up at the next threshold too). Then the shape filters cull what's left. That multi-threshold sweep is why it's robust to uneven lighting in a way a single cv2.threshold never is: a blob doesn't have to be brighter than one magic number, it has to survive a range.

The inputs that matter

Required:

  • image - an IMAGE, MASK or NPARRAY; grayscaled internally.
  • blob_color - dark blobs on a light background or the reverse. Read the tooltip and believe it: this is the first thing to flip when count is 0, and it's the mistake everyone makes once.
  • min_area / max_area in pixels. Note max_area = 0 means no upper limit, not "no blobs".
  • min_circularity, min_convexity, min_inertia - each 0–1, each disabled at 0, which is the default. Circularity of 1.0 is a perfect circle, ~0.79 a square. Convexity is area over hull area, so crescents score low. Inertia ratio is short axis over long axis, so a thin streak scores near 0.

Optional, and the ones you'll actually tune when the defaults find nothing:

  • min_threshold / max_threshold / threshold_step - the sweep. A smaller step is more thorough and slower.
  • min_repeatability - how many consecutive thresholds a blob must survive.
  • min_distance - blobs closer than this get merged.

Outputs: keypoints (for CV Draw Keypoints or CV Compute Descriptors), points (Nx2 centres, for k-means, polar conversion, anything point-based), sizes (keypoint diameter), responses (detector strength - threshold it if you want only the strong ones), and count. Zero is a valid result, not an error.

Install

From comfyui_cv (bmad4ever/comfyui_cv). In ComfyUI Manager search "ComfyUI CV", or:

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

Dependency, pinned:

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

Python ≥ 3.12 and a V3-API ComfyUI. This one lives in the base cv2 API rather than a contrib module, but the contrib wheel is still the required install - mixing in a plain opencv-python wheel clobbers all four distributions' shared site-packages/cv2 and takes the contrib nodes with it. tools/repair_opencv_contrib.py --check / --apply is the repair.

Common issues

  • Count is 0 and it should not be. Flip blob_color first, then widen the threshold range, then drop min_repeatability to 1. In that order - it's almost always polarity.
  • Thousands of one-pixel specks. Raise min_area from its default 25, and raise threshold_step so the sweep is less jumpy.
  • It finds one blob where you see five. min_distance is merging them.
  • It finds blobs and also long smears. That's what min_inertia is for. Set it to ~0.5 and watch the streaks disappear.
  • It's slow. The sweep is (max - min) / step full-image threshold passes. On a 4K frame, narrow the range before you narrow the step.

If your targets are text-like rather than round - signs, letters, print at an angle - CV Detect MSER Regions is the better tool: MSER sweeps thresholds too but keeps stable regions regardless of shape, which is exactly what letters are.

Categoryimage/CV/features

Inputs (12)

NameTypeDefaultDescription
imageNPARRAY,IMAGEImage to search (converted to grayscale internally). 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.
blob_colorCOMBOdark blobs on a light backgroundPolarity of the blobs. Pick the wrong one and the detector returns nothing - this is the first thing to flip when count is 0.
min_areaFLOAT250–10000000Smallest blob area in PIXELS. 0 disables the lower bound. Raise it to ignore speckle noise.
max_areaFLOAT50000–10000000Largest blob area in pixels. 0 means NO upper limit (the area filter is then one-sided).
min_circularityFLOAT0.000–1Minimum 4*pi*area / perimeter^2: 1.0 is a perfect circle, ~0.79 a square. 0 disables the filter.
min_convexityFLOAT0.000–1Minimum area / convex-hull area: 1.0 is fully convex, lower values allow dents and crescents. 0 disables the filter.
min_inertiaFLOAT0.000–1Minimum inertia ratio (short axis / long axis): 1.0 is a circle, near 0 is a thin streak. 0 disables the filter - raise it to reject elongated smears.
min_thresholdoptFLOAT500–255First grayscale threshold of the sweep.
max_thresholdoptFLOAT2200–255Last grayscale threshold of the sweep.
threshold_stepoptFLOAT101–128Step between successive thresholds; smaller is more thorough and slower.
min_repeatabilityoptINT21–100A blob must appear at this many consecutive thresholds to be reported - the stability test.
min_distanceoptFLOAT100–10000Blobs closer together than this (pixels) are merged into one.

Outputs (5)

NameTypeDescription
keypointsCV_KEYPOINTScv2.KeyPoint list - draw with 'CV Draw Keypoints', or give them descriptors with 'CV Compute Descriptors' to feed 'CV Match Features'.
pointsNPARRAYNx2 float32 (x, y) centres - the point-set form for 'OpenCV Draw Points', k-means, polar conversion, ...
sizesNPARRAY(N,) float32 keypoint diameter in pixels.
responsesNPARRAY(N,) float32 detector strength per keypoint - threshold it to keep only the strong ones.
countINTHow many were found; 0 is a valid result, not an error.