Nodes/ComfyUI CV/cv2.ft.FT12D_polynomial
ComfyUI Node

cv2.ft.FT12D_polynomial

Noise-robust gradients, from a fit instead of a difference kernel

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.ft.FT12D_polynomial
  • matrix
  • kernel
  • mask
  • nparray_0
  • nparray_1
  • nparray_2
  • nparray_3

cv2.ft.FT12D_polynomial is the analysis half of the fuzzy transform's F¹ family. Instead of smoothing an image and handing it back, it returns the terms of the local linear fit: the average value, and the average gradient in each direction. OpenCV's docs name them, and the names are better than most:

  • c00 - elements represent the average colour
  • c01 - elements represent the average horizontal gradient
  • c10 - elements represent the average vertical gradient
  • plus the components array itself

There are four NPARRAY outputs, and the schema labels them generically (nparray_0 … nparray_3). OpenCV's documentation gives you the names; the port doesn't, so check which is which on your first run instead of assuming - feed a horizontal ramp through it and only the horizontal-gradient output should light up. That five-second test saves a lot of confusion.

Why this is interesting

A Sobel gradient is a difference of neighbouring pixels, which means noise gets multiplied up right along with the signal. A local linear fit's slope is a regression over the whole window, so the noise averages out while the trend survives - that's the entire reason the F¹ transform exists in the literature, and it's a genuinely different trade from a Sobel or Scharr kernel. If you've ever tried to get a usable gradient field out of a noisy or heavily compressed source, you know why that matters.

Practical uses in a ComfyUI graph:

  • Texture energy and orientation. The two gradient maps give you direction without the high-frequency hiss a plain Sobel adds.
  • Compression-artifact and film-grain measurement. Grain is noise; a fitted gradient suppresses it, so what's left in the gradient maps is real structure. Handy when deciding how hard to denoise.
  • Smooth shading gradients for relighting-ish work and for building masks that follow illumination rather than edges.

Inputs

  • matrix - IMAGE, MASK or NPARRAY; an IMAGE arrives as a uint8 BGR frame and only frame 0 of a batch gets processed. The ft functions aren't frame-batch safe here.
  • kernel - required, from cv2.ft.createKernel, and its channel count must match the image. The radius is where all the cost lives: the kernel is (2r+1)², and the default radius of 0 is a degenerate 1×1.
  • mask - optional; non-zero = known, zero excludes a pixel from the fit.

Reading the outputs

The components and c00 are in your input's intensity range (0–255 for a uint8 IMAGE), so they preview like a picture. The gradients are the slope of the fit - per-pixel differences, so they're small numbers and they're signed. Preview a signed float map directly and the preview node's normalisation will make a subtle gradient field look like a wall of noise; normalise or take the magnitude first, or read the raw numbers with Inspect CV Data. If you want to go further with the coefficients, they're NPARRAYs and multiply perfectly well through the pack's cv2.gemm.

For a round trip - fit, then rebuild the image - pair it with FT12D_inverseFT using the same kernel.

Install

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. The ft module is contrib-only and all four OpenCV wheel flavours share one site-packages/cv2, so a plain opencv-python install can silently delete these nodes from the menu - tools/repair_opencv_contrib.py --check tells you if that's what happened. Python ≥ 3.12, V3-API ComfyUI, no downloads.

Where people get burned

  • Assuming the port order. The schema's output names are positional placeholders. Verify with a ramp.
  • Radius 0, i.e. a 1×1 kernel and an output that's basically your input.
  • Mask direction. Non-zero = known, as with every ft function here.
  • Reading a normalised gradient map as if it were data. The gradients are signed and small; the preview lies to you.
Categoryimage/CV/low-level/ft

Inputs (3)

NameTypeDefaultDescription
matrixNPARRAY,IMAGE,MASKInput array. 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.
kernelNPARRAY,IMAGE,MASKKernel used for processing. Function `ft::createKernel` can be used. 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.
maskoptNPARRAY,IMAGE,MASKMask can be used for unwanted area marking. The function computes components and its elements using predefined kernel and mask. 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.

Outputs (4)

NameTypeDescription
nparray_0NPARRAY—
nparray_1NPARRAY—
nparray_2NPARRAY—
nparray_3NPARRAY—