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

cv2.ximgproc.fourierDescriptor

Compare shapes that are rotated, rescaled or just drawn sloppier

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.ximgproc.fourierDescriptor
  • src
  • nparray
◄nbElt-1►
◄nbFD-1►

Here's a problem the diffusion toolbox cheerfully ignores: you have two outlines and you want to know whether they're the same shape, not the same pixels. One is rotated 30°, one is 20% bigger, one was drawn by a human with a mouse. Pixel-difference says "completely different"; matchShapes gives you a single number you can't interrogate. Fourier descriptors give you a compact signature you can truncate, transform, and compare - and this node is the entry point to that pipeline.

Practical uses in a ComfyUI graph: matching a silhouette against a reference (logo, icon, product shape, a hand-drawn guide), smoothing a ragged contour down to its essential geometry, or checking that a generated object kept the shape of the mask you conditioned on.

How it works

The contour's points are treated as a complex sequence (x + iy), resampled to a fixed number of points, and Fourier-transformed. The low-frequency coefficients describe the gross shape; the high-frequency ones describe the wobble. Keep the first dozen or two and you have a rotation-, scale- and translation-tolerant fingerprint of the silhouette - rotation shows up as a phase shift, which is exactly the stuff you can ignore or measure.

Two inputs to set:

  • src - a contour as (N, 1, 2) points. Contours in this pack travel on their own socket type, so bridge with CV Contour To Points (CV_CONTOURS → NPARRAY) before this node. The author's tooltip describes exactly that: "contour as (N,1,2) points".
  • nbElt (-1) - resample the contour to this many points first. -1 keeps the contour's own count. Set it explicitly the moment you're comparing two contours: descriptors computed from different point counts aren't comparable, and the pack's contourSampling wrapper exists for exactly this resampling job.
  • nbFD (-1) - how many coefficients to keep, -1 for all. Fewer equals coarser shape. This is your detail slider: 10 gives you a blob, 100 gives you the wiggles back.

Output is one NPARRAY, a small float array of descriptors. It's not an image and never will be - if you feed it to CV Array → Image you'll get a meaningless picture. Use Inspect CV Data to see its size, then send it to transformFD or compare two of them with a distance wrapper.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv

Restart, or install ComfyUI CV from ComfyUI Manager. Python ≥3.12, a recent V3-API ComfyUI, opencv-contrib-python-headless~=5.0.0.93. No models, no downloads. fourierDescriptor is contrib, so it only shows up in a contrib OpenCV install - a plain opencv-python wheel sitting on top silently empties the contrib submodules and the node disappears. tools/repair_opencv_contrib.py --check will name the problem.

Common issues

Garbage descriptors. Almost always a contour that isn't a closed, consistently-ordered point loop - a raw edge list from a Canny pass, say, rather than something findContours produced. Contours first, descriptors second.

Comparing descriptors with different nbElt. They'll be different lengths and the comparison is meaningless. Fix nbElt on both sides.

Losing the shape you cared about. Truncating nbFD is a low-pass filter on geometry: fine corners go first. If your distinction between "spanner" and "hammer" lives in the thin handle, keep more coefficients.

Orientation is not handled here. Descriptors are tolerant of rotation only in the sense that the rotation is expressed in the phases; if you need two shapes aligned before comparison, normalize them first - that's what PeiLinNormalization in this same module is for, and it's the step most people skip.

It's an auto-generated wrapper. The pack ships ~470 of these, generated from the cv2 type stubs and explicitly uncurated - the README warns that edge cases and argument handling are yours, that updates aren't promised, and that the author doesn't consider the library production-ready without your own review. Fine for a graph you're babysitting; read the source before you build a product on it.

Categoryimage/CV/low-level/ximgproc

Inputs (3)

NameTypeDefaultDescription
srcNPARRAY,IMAGE,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.
nbEltoptINT-1-2147483648–2147483647 - - - Preset to the OpenCV default (-1).
nbFDoptINT-1-2147483648–2147483647 - - - Preset to the OpenCV default (-1).

Outputs (1)

NameTypeDescription
nparrayNPARRAY—