OpenCV pyrMeanShiftFiltering_0
Flatten an image into poster-like color blobs with OpenCV mean shift
- src
- dst
- nparray
This is the node you reach for when you want a photo to stop looking like a photo. pyrMeanShiftFiltering is OpenCV's edge-preserving "flattening" filter: it collapses nearby pixels into big flat regions of nearly-identical color while keeping the hard edges between them. Run it on a portrait and you get a stylized, almost watercolor or posterized look that survives a normal img2img pass far better than raw noise. It's also the classic pre-step for segmentation - find the big blobs first, then let everything else work on a clean, low-entropy image.
The name is a mouthful, so unpack it: mean shift looks at each pixel and replaces it with the average of its neighbors, but only neighbors that are both spatially close and similar in color. Repeat that a few times and smooth gradients collapse into plateaus while actual boundaries (where color changes hard) stay put. The result is a cartoon-ish flat image with intact edges. That's the whole trick.
What you actually set
Like every node in this pack, this one speaks nparray, not ComfyUI IMAGE. So the wiring is Image2Nparray in front, Nparrays2Image after - the pack's two conversion nodes do the RGB↔BGR and tensor↔numpy dance for you. Inside, the inputs that matter:
src- yourNPARRAYimage, BGR and 0–255 uint8 afterImage2Nparray.sp(spatial radius) andsr(color radius) - the two tuning knobs.spis how far out (in pixels) the filter looks;sris how big a color difference still counts as "the same". Smallsp/sr≈ subtle smoothing; crank both up (think 20–40) and you get the strong flat-poster look.maxLevel- how many pyramid levels to use.0keeps it simple;1gives a noticeably cleaner result for the same radii.termcrit- a Python-literal string for OpenCV'sTermCriteria, written(type, maxCount, epsilon).(3, 10, 1)is the sane default: type 3 means "stop after 10 iterations OR when the change is under 1", whichever comes first.
dst is an optional out-parameter - leave it unplugged, per the README's "avoid the optional out-parameters" advice.
Wiring and gotchas
termcrit is parsed with ast.literal_eval, so if the syntax is wrong you'll get an invalid syntax (<unknown>, line 0) error and the node will sit there smug. Use a tuple: (3, 10, 1).
You'll also notice pyrMeanShiftFiltering_1 sitting right next to this one in the menu. They're the same function, same inputs, same output - the generator couldn't tell the two OpenCV overloads apart. Pick either; nothing changes.
Install
No models, no weights, no downloads. The pack is just auto-generated wrappers around OpenCV, so the only real dependency is OpenCV itself (plus numpy/torch, which ComfyUI already has):
cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui
pip install opencv-contrib-python
Or just search "OpenCV" in ComfyUI Manager. Restart, and the nodes appear under image/OpenCV. If install throws Cannot import name 'guidedFilter' from 'cv2.ximgproc', you have a conflicting OpenCV install - known issue, fix by aligning your opencv-contrib-python versions (see the LayerStyle issue the README links).
One more thing: the pack only handles batch_size==1 images, so if your workflow feeds a batch, drop an ImageFromBatch (length=1) in front. Then flatten away.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| src | NPARRAY | — | |
| sp | FLOAT | — | |
| sr | FLOAT | — | |
| maxLevel | INT | — | |
| termcrit | STRING | — | |
| dstopt | NPARRAY | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |