Nodes/ComfyUI CV/cv2.ximgproc.dtFilter
ComfyUI Node

cv2.ximgproc.dtFilter

Edge-preserving smoothing that doesn't care how big sigma is

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.ximgproc.dtFilter
  • guide
  • src
  • result
◄sigmaSpatial0.0000►
◄sigmaColor0.0000►
◄modeDTF_NC►
◄numIters3►

The bilateral filter's dirty secret is cost. Its quality knob - the spatial sigma - directly multiplies the work, so the settings that look best are the ones that take longest. The domain transform (Gastal & Oliveira, 2011) sidesteps this by transforming the image into a space where distances along an edge-aware curve become 1-D, then filtering that. The result: cost essentially independent of sigma, and a filter that looks a lot like a bilateral.

That's why dtFilter is the one to reach for when you need edge-preserving smoothing inside a loop - per-frame over a video, per-tile over a big upscale, in a batch. Where bilateralFilter gets expensive, this one stays flat.

Inputs

  • guide - "guided image (also called as joint image) with unsigned 8-bit or floating-point 32-bit depth and up to 4 channels". A match-type socket: IMAGE/MASK/NPARRAY in, same format out. Self-guided (guide = src) is plain smoothing; guide = a cleaner or structural image is joint filtering.
  • src - "filtering image with unsigned 8-bit or floating-point 32-bit depth and up to 4 channels".
  • sigmaSpatial - the spatial sigma, in pixels. This is the one that doesn't blow up your runtime. Bigger = broader smoothing.
  • sigmaColor - "similar to the sigma in the color space into bilateralFilter". It's in your data's units, which for a ComfyUI IMAGE means 8-bit 0–255 - think tens, not 0.1.
  • mode - one of DTF_NC (default, normalised convolution), DTF_RF (recursive filtering) or DTF_IC (interpolated convolution). The tooltip says they "correspond to three modes for filtering 2D signals in the article". Start on the default; DTF_RF is the cheap recursive one if you're pushing speed.
  • numIters (default 3) - the tooltip's own verdict is "3 is quite enough", and it's right. Each iteration sharpens the edge-awareness; past three you're paying for nothing.

Output is a single value echoing the guide's format.

The batch story, which is unusually good here

This node is one of the contrib filters the pack treats as per-frame batch safe, and for a specific reason worth knowing: when you feed a batch to both guide and src, frame i of the guide is paired with frame i of the source. So a 12-frame noise-reduction pass filters frame by frame in one node execution and comes back as a 12-frame batch - no unstack/restack dance. Pass the same batch to both sockets for self-guided smoothing, or two paired batches for genuine joint filtering.

Where it fits

Two jobs it's good at:

Denoise before upscaling. The single biggest quality win in any upscale is not amplifying noise. A domain-transform pass over the frames first keeps edges crisp while removing the grain an upscaler would happily turn into plastic.

Structure/detail separation. Subtract the smoothed version from the original (cv2_subtract) to get a detail layer, then recombine with cv2_addWeighted (the pack's filter sheet uses amount 1, offset −1, bias 128 to show the detail layer). Once separated you can sharpen the detail layer rather than the image, which is what most "professional sharpening" actually is.

And if you can't tell whether your settings helped: CV Quality Compare scores two images with SSIM and returns a per-pixel map of where they differ. Use it. Eyes prefer smoother; SSIM tells you which one kept the structure.

Sibling filters in the same module

guidedFilter (local linear fit; watch eps, it's a variance in squared units of your pixel scale), bilateralTextureFilter (texture-vs-structure), l0Smooth (flat regions, hard steps), fastGlobalSmootherFilter (global WLS), weightedMedianFilter (specular noise), rollingGuidanceFilter (scale-space), amFilter (adaptive manifold). The pack's 10_ximgproc_edge_aware_filters example runs six of them on the same photo with scores next to each - the fastest way to develop an intuition for which is which.

Installing it

Contrib module, inside ComfyUI CV. 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

  • Nothing happens. sigmaColor set for a 0–1 scale while the data is 0–255 (or the reverse). Confirm the scale with Inspect CV Data.
  • A halo along high-contrast edges. Too many iterations at a big spatial sigma. Back off numIters to 1 and see what changes.
  • Guide/source size mismatch. They have to match; if your guide came from a different branch of the graph, resize or crop one of them.
  • ximgproc empty in your menu. Contrib-only submodule and one shared site-packages/cv2 for all four opencv-python* wheels - a non-contrib install silently empties it. tools/repair_opencv_contrib.py --check in the pack repo diagnoses it.
Categoryimage/CV/low-level/ximgproc

Inputs (6)

NameTypeDefaultDescription
guideCOMFY_MATCHTYPE_V3guided image (also called as joint image) with unsigned 8-bit or floating-point 32-bit depth and up to 4 channels. 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.
srcNPARRAY,IMAGE,MASKfiltering image with unsigned 8-bit or floating-point 32-bit depth and up to 4 channels. 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.
sigmaSpatialFLOAT0.0000-1e+38–1e+38${\sigma}_H$ parameter in the original article, it's similar to the sigma in the coordinate space into bilateralFilter.
sigmaColorFLOAT0.0000-1e+38–1e+38${\sigma}_r$ parameter in the original article, it's similar to the sigma in the color space into bilateralFilter.
modeoptCOMBODTF_NCone form three modes DTF_NC, DTF_RF and DTF_IC which corresponds to three modes for filtering 2D signals in the article.
numItersoptINT3-2147483648–2147483647optional number of iterations used for filtering, 3 is quite enough. Preset to the OpenCV default (3).

Outputs (1)

NameTypeDescription
resultCOMFY_MATCHTYPE_V3Echoes the 'guide' input's format: an IMAGE link comes back as IMAGE, MASK as MASK, NPARRAY stays NPARRAY.