Nodes/Mosaica/Mean Shift
ComfyUI Node

Mean Shift

The posterizer that figures out its own color count

By Mason-McGough·Created 2 years ago·Updated 2 years ago· 6
Mean Shift
  • image
  • image
  • label_image
  • lut
bandwidth0.10
color_space
use_pixel_distancefalse
max_iter100

Mean Shift is the sibling of the Mosaica pack's KMeans node with one big difference: you don't tell it how many colors you want. It decides on its own. If KMeans is the "I know roughly how many flat regions I need" posterizer, this is the one you reach for when you just want the image segmented sensibly and you're not sure what the count should be.

Same family, same trio of outputs: image (the flat-color result), label_image (the single-channel label map), and lut (the averaged color per region). Same wiring, same LUT recolor trick downstream. The mechanism is where they part ways.

How it works

Instead of fixing the cluster count, mean shift looks at every pixel's neighborhood and drifts a "window" toward the densest color regions until it settles. Pixels that land in the same settlement become one label. The result is that the number of clusters falls out of the image's actual color distribution - dense, distinct color areas each claim their own label, and the count is whatever it is.

That convenience has a price, and the pack's own README says it plainly: mean shift is much slower than k-means, especially on images bigger than 512×512. That's not exaggeration. scikit-learn's mean shift has to work out distances between many points, and it crawls as the pixel count climbs. The author enables bin_seeding=True in the code to speed it up, but on a big render you will feel every megapixel.

The input that matters: bandwidth

The whole experience reduces to one slider:

  • bandwidth (default 0.1, range 0–1) - this is the radius of the "neighborhood" the algorithm drifts over. Smaller bandwidth = tighter regions = more clusters (and slower). Larger bandwidth = fewer, chunkier regions (and faster). The author's advice from the README: values in 0.0–0.15 tend to produce the best results. Start at 0.1, nudge down if you want finer detail, nudge up if you want a bolder poster look.

The other inputs are the same story as KMeans: color_space (RGB or LAB, and LAB is the better default for perceptual clustering), use_pixel_distance (adds pixel coordinates so same-colored blobs in different parts of the frame don't merge), and max_iter (default 100, usually fine untouched).

Installing and running it

Install the pack the usual way - ComfyUI Manager → search "Mosaica" → install, or:

cd ComfyUI/custom_nodes
git clone https://github.com/Mason-McGough/ComfyUI-Mosaica

then restart. Dependencies are scikit-learn, opencv-python, and matplotlib - all CPU-side, no model files, no VRAM. If cv2 fails to import on a server with libGL.so.1 errors, that's the classic opencv-python vs opencv-python-headless conflict; swap the wheel and you're fine.

The practical take

Mean shift gives nicer, more organic segmentation than k-means on the same image - region boundaries follow the actual color density instead of a forced count. But it's the node I'd reach for at 512×512 or below, then politely hand off to k-means once the image grows. If your workflow generates at 1024 or higher, downscale before the node (or use KMeans) unless you enjoy watching a progress bar. The look is worth a test render, but the slow ones stay slow - that's the trade built into the algorithm, not a bug in the node.

CategoryMosaica/Analyze

Inputs (5)

NameTypeDefaultDescription
imageIMAGE
bandwidthFLOAT0.100–1
color_spaceCOMBO2 options: RGB, LAB
use_pixel_distanceBOOLEANfalse
max_iterINT1001–1000

Outputs (3)

NameTypeDescription
imageIMAGE
label_imageIMAGE
lutIMAGE