cv2.solveCubic
Real Roots of a Cubic, in Closed Form
- coeffs
- int
- nparray
Where does this curve cross zero? Which depth has this lens's distortion parameter pinned? At what scale does my fitted response curve hit a threshold? All three are cubic-root problems, and cv2.solveCubic is the closed-form solver OpenCV ships for them, available as a node in ComfyUI CV (bmad4ever/comfyui_cv).
It's a small, sharp tool with two inputs' worth of surface area (one input, really), and the interesting part for a node user is reading its two outputs correctly.
Inputs
coeffs - the equation coefficients, as an NPARRAY. It takes three or four elements:
- four elements:
a·x³ + b·x² + c·x + d = 0, in descending order. - three elements: the leading coefficient
ais assumed to be 1, sox³ + b·x² + c·x + d = 0.
That's the whole input. No IMAGE or MASK link is accepted here - this is numeric data, and the pack's raw wrappers are strict about that on purpose.
Where do coefficients come from in a graph? From cv2.fitLine or a polynomial fit upstream, from CV Array To Numbers / CV Numbers To Array if you compute them elsewhere, or straight from Parse Matrix / CV Scalar if you know them. The dtype should be float32 or float64.
Outputs, and how to read them
int- the number of real roots. OpenCV's documented range is-1(every real number is a root - the degenerate all-zero polynomial),0,1,2or3.nparray- the roots.
The trap is that the array always has three slots but only the first int of them are meaningful. Ignore the count, treat all three as roots, and you'll wire a phantom root into the rest of your graph - and it will be whatever happened to be in that slot, which is not a value you can predict or debug from the outside. Read the int first. That's not an OpenCV quirk to work around; it's the contract.
Install
Manager → search ComfyUI CV → install, 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 afterwards. Needs Python ≥ 3.12 and a recent ComfyUI on the V3 node API - the whole pack is a V3 rewrite. No model files involved.
Where people get burned
Coefficient order. OpenCV's convention here is highest-degree-first, and getting it backwards does not raise - it silently solves a different polynomial with perfectly plausible-looking roots. If your answer looks like noise, sanity-check the order before anything else: for 2x³ - 4x + 1, coeffs is [2, 0, -4, 1], zeros included.
The -1 case. It means "any real number is a root", not "one root at minus one". Branching on the count as a truthy/falsy value and treating -1 as success will send a garbage root downstream; treat -1 and 0 as failures for any normal use, and only 1..3 as usable.
Cubic only. A quartic or a quintic will not work here - that's cv2.solvePoly, which handles arbitrary degree by an iterative companion-matrix method (hence its maxIters field). Reach for solveCubic when the degree really is three, since closed form is exact and instant.
Roots are not filtered. Nothing here finds the root you meant. A cubic often has three real roots and you usually want the one in a physically meaningful range; the filtering is the part you build, whether that's a comparison node, an CV Array Statistic pass, or another cv2 node downstream.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| coeffs | NPARRAY | equation coefficients, an array of 3 or 4 elements. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| int | INT | — |
| nparray | NPARRAY | — |