cv2.ximgproc.edgePreservingFilter
Two nodes share this name and they are not the same algorithm
- src
- result
OpenCV has two functions called edgePreservingFilter. One lives in the photo module and takes a filter-type flag plus two sigmas; the other lives in ximgproc and takes a neighbourhood size d and a threshold. They are different algorithms with different parameters that happen to share a name - and this pack exposes both:
cv2_edgePreservingFilter- the photo-module one (RECURS_FILTER/NORMCONV_FILTER,sigma_s,sigma_r).cv2_ximgproc_edgePreservingFilter- this one (d,threshold).
The author calls this out explicitly as the reason contrib nodes keep their module prefix in their node id and display name: "two different functions that share a name, which is exactly why contrib nodes keep their module in the node id". If you've ever wondered why a ComfyUI node is awkwardly called cv2.ximgproc.something instead of something friendly, that's the answer - it prevents exactly this collision.
What this one does
ximgproc's edge-preserving filter is a local histogram filter. Instead of weighting neighbours by colour similarity the way a bilateral does, it looks at the histogram of each local neighbourhood and flattens it - which suppresses texture and small variations while leaving the strong boundaries that dominate a local histogram. It's the mechanism that makes it good at the "cartoon-ify"/"clean the plate" look, and the reason it has different knobs than you'd expect:
src- the image.IMAGE,MASKorNPARRAY; type-matched output.d- the filter size. The neighbourhood diameter. The pack's filter sheet uses 9 and 21 - larger means flatter, slower, and more prone to washing out fine structure.threshold- what counts as an edge worth preserving. The sheet runs 25 and 50; the higher you push it, the more gets treated as texture and smoothed away.
Output: one value echoing the input's format.
How it differs from the photo-module twin
The photo version is a fast bilateral-ish edge-preserving smoother built for the "look like a painting" family of effects (it sits next to pencilSketch and stylization in that module). It offers two filter modes - RECURS_FILTER (faster) and NORMCONV_FILTER (sharper, no normalisation artefacts) - plus a spatial sigma and a colour sigma. In the pack's filter sheet it runs d=60, sigma_s=0.4, which is a much broader, subtler smoothing than the histogram version's d=9/21, threshold=25/50.
Practical difference: the photo one behaves like a well-tuned bilateral and is the safer general-purpose choice. The ximgproc one produces flatter, more poster-like results at bold settings, which is either the look you want or a reason to walk away from it.
Using either properly
Two pieces of advice that apply to both nodes, and to every smoother:
Separate structure from detail rather than choosing between them. Subtract the smoothed image from the original (cv2_subtract) to isolate the detail layer, then recombine with cv2_addWeighted - the pack's example sheet does exactly this (amount 1, offset −1, bias 128) so you can see the detail layer on its own. Then you can decide how much of it to put back, which is the actual decision you were trying to make.
Score it. CV Quality Compare (SSIM) returns a score and a per-pixel map showing where two images disagree. That turns "this looks smoother, I think I like it" into "this preserved 0.94 structural similarity versus 0.89". The pack's 10_ximgproc_edge_aware_filters workflow is built around exactly this comparison, six filters deep, with a note on each explaining what it's meant to do.
Installing it
Contrib module, so contrib OpenCV is required. Manager → search ComfyUI CV, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
# restart ComfyUI
Python ≥3.12 and a recent V3-API ComfyUI.
What goes wrong
- You picked the other one. The most common problem with this node is that someone else's tutorial meant the
photo-module filter. Check whether the node in your graph saysximgproc. - Everything is posterised.
dtoo large. It's a histogram filter; a big window is a big quantisation. - Fine detail you wanted is gone.
thresholddecided it was texture. Lower it. ximgprocgroup missing from the menu. Contrib-only submodule, one sharedsite-packages/cv2across all fouropencv-python*distributions - a non-contrib wheel leaves them as empty stubs.tools/repair_opencv_contrib.py --checkreports it;--applyrepairs it.- Slow at large
d- local histograms over a big window on a 4K frame. Preview before batching.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| src | COMFY_MATCHTYPE_V3 | The image output(s) echo this input's format. 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. | |
| d | INT | 0-2147483648–2147483647 | - - - |
| threshold | FLOAT | 0.0000-1e+38–1e+38 | - - - |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| result | COMFY_MATCHTYPE_V3 | Echoes the 'src' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY. |