Apply Meanshift Filter
Flatten Noise Without Blurring the Lines
- image
- image
"Apply Meanshift Filter" (class ImageMeanshiftFilter) is a one-trick node: it smooths away grain, texture, and color noise while keeping the edges intact. It's the classic computer-vision mean-shift filter from OpenCV wrapped in a tiny ComfyUI package - one node, four inputs, one output. No model downloads, no API calls, nothing to tune beyond two numbers. If you've ever wanted that clean flat-illustration look, or wanted a quieter image before it hits an upscaler, this is the node.
Let's be honest about what you're getting. The whole repo is one file, one commit, no README, and it surfaces in searches as comfyui_meanshift_filter. Zero install base, zero fanfare - it reads like a personal utility the author (Yiheng) published in 2024 and moved on from. That's fine. The code is short enough to read in one sitting, and it does exactly what it claims.
What it's doing under the hood
Mean-shift filtering is an edge-preserving smoother. For every pixel, it repeatedly averages the pixels in a spatial neighborhood that are also within a color distance of it, shifting toward the densest cluster of similar colors until it converges. Pixels with similar colors get pulled into flat regions; boundaries where color changes sharply stay put. The result reads as "de-noised and flattened," not blurred - unlike a Gaussian blur, which smears the whole image.
Two OpenCV functions do the work depending on your toggle: cv2.pyrMeanShiftFiltering on CPU, cv2.cuda.meanShiftFiltering on GPU. The node converts ComfyUI's tensor to a PIL image, filters it, and converts back. It loops over batch frames too, so it handles image batches and video frame sequences without complaint.
The inputs that matter
image- the IMAGE tensor you want cleaned, straight off a VAE Decode or an image load.sp- the spatial window radius in pixels (default 20). How big a neighborhood each pixel looks at. Crank it too high and the filter gets slow and heavy-handed.sr- the color-distance threshold (default 20). This is the one that controls the look. Highersrpulls more colors into the same region, so you get more posterization - turn it way up and a photo becomes a flat-color painting.use_cuda- defaultFalse. Leave it. We'll get to why.
The output is a single image (a normal IMAGE tensor), so it plugs straight into a Save Image, a VAE Encode for an img2img pass, or another filter downstream.
Where you'd actually put it
Three spots I'd reach for it. Right after VAE decode as a cleanup pass before a detail-focused upscaler - you don't want the upscaler amplifying grain you were planning to smooth anyway. Before a ControlNet preprocessor, where flat regions give you cleaner depth or segmentation maps. And anywhere you want that painted, flat-shaded aesthetic. It's also handy between img2img passes to kill residual artifacts without spending another diffusion pass on it.
Installing it
The repo has no requirements.txt, which is the one real trap. ComfyUI Manager can find the pack (search "comfyui_meanshift_filter"), and the manual route is the usual:
cd ComfyUI/custom_nodes
git clone https://github.com/githubYiheng/comfyui_meanshift_filter
Then restart ComfyUI. But nothing auto-installs its Python dependency. The node needs cv2 (OpenCV), and base ComfyUI doesn't ship it - so if the node doesn't show up in your menu, install it yourself into your venv or portable python:
pip install opencv-python
numpy, Pillow, and torch are already there.
The gotchas
The big one: use_cuda is a trap on stock installs. The opencv-python you get from pip has no CUDA support, so cv2.cuda simply doesn't exist - flip the toggle on and the node throws AttributeError: module 'cv2' has no attribute 'cuda'. Using it requires an OpenCV built with CUDA from source, and that's a chore that's not worth it for a filter this fast on CPU. Leave the toggle off and move on.
Second, sp and sr interact. Bump both and every region flattens toward a single color - great for a cartoon look, terrible if you wanted to keep skin texture. Start at the defaults (20/20) and nudge only sr. And on very large images the pyramid filter gets sluggish at high sp; downscale before filtering if your graph starts to crawl.
That's the whole node. Modest, unglamorous, and it does one thing well.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| sp | INT | 20 | — |
| sr | INT | 20 | — |
| use_cuda | BOOLEAN | false | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |