Nodes/Mosaica/KMeans
ComfyUI Node

KMeans

Posterize any image into flat color regions — no model, no VRAM

By Mason-McGough·Created 2 years ago·Updated 2 years ago· 6
KMeans
  • image
  • image
  • label_image
  • lut
n_clusters8
color_space
use_pixel_distancefalse
max_iter100

Feed an image into KMeans and you get back a posterized version of it - every pixel collapsed onto a handful of flat, averaged colors, like a high-quality mosaic filter. It's the flagship node of the Mosaica pack, and it does the whole job without touching a diffusion model. No checkpoint, no VRAM, no sampling. Just scikit-learn chewing on pixels on your CPU.

This is one of those nodes that exists for a specific look rather than a pipeline step. Posterization, flat-color art, "label maps" for recoloring, mosaic-style textures - if that's what you're after, this is the fastest way to get there in ComfyUI.

How it works

KMeans flattens your image into a pile of pixels, then runs scikit-learn's KMeans clustering over them. The algorithm groups the pixels into n_clusters color families, finds the average color of each group, and paints every pixel with its group's average. That's the whole trick: it's why the result looks like a clean, flat-color poster instead of a blurry mess.

The node hands back three outputs, and you'll want different ones depending on what you're building:

  • image - the posterized result, ready to save or wire onward.
  • label_image - a single-channel image where every pixel holds its cluster index (0, 1, 2…), not a color. This is the "label map" the pack is named for.
  • lut - the lookup table: the averaged color for each cluster, in order.

The neat part is the split. image is the quick win, but label_image + lut is the real power, because you can recolor the label map with any LUT you like (see ApplyLUTToLabelImage).

The inputs that matter

There are four, and honestly only two of them need your attention:

  • n_clusters (default 8) - the number of colors/regions you want. This is the one you'll actually tune. Low numbers (3–6) give chunky, graphic posterization; high numbers start looking like a heavy paint filter. It's a 1–100 slider.
  • color_space - RGB or LAB. LAB is the pick here: it clusters on perceptual color distance, so regions come out closer to what your eye sees. RGB is raw and can smear visually-similar-but-digitally-different colors together. If you only try one thing, try LAB.
  • use_pixel_distance (default off) - when enabled, the node appends each pixel's x/y coordinates to its color before clustering. Two same-colored blobs in different parts of the frame stay separate instead of merging. Turn it on when the image has disconnected regions of the same color you want to keep apart.
  • max_iter (default 100) - clustering iterations. Leave it alone unless you're chasing edge cases.

Installing it

This pack installs like any other custom node:

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

Then restart ComfyUI. Or skip all that and use ComfyUI Manager - search for "Mosaica" and hit install. It pulls three Python dependencies (scikit-learn, opencv-python, matplotlib), all CPU-side, so there are no model files to download and nothing to drop in models/.

Where people get burned

The classic failure is picking an n_clusters that fights the image. Too few and a photo becomes unrecognizable mush; too many and the "mosaic" look disappears into near-photographic noise. The fix is to stop guessing and nudge the slider - it's fast enough to iterate.

If you're on a headless server and cv2 complains about libGL.so.1, that's the opencv-python vs opencv-python-headless clash that bites a lot of ComfyUI installs; swap in the headless wheel and this pack is happy.

One more honest note: this is a small hobby pack, last touched in 2024, with basically no community footprint. The code is short, readable, and self-contained, so what you see is what you get - it just works, and it won't surprise you.

CategoryMosaica/Analyze

Inputs (5)

NameTypeDefaultDescription
imageIMAGE
n_clustersINT81–100
color_spaceCOMBO2 options: RGB, LAB
use_pixel_distanceBOOLEANfalse
max_iterINT1001–1000

Outputs (3)

NameTypeDescription
imageIMAGE
label_imageIMAGE
lutIMAGE