cv2.fitEllipseAMS
For when your ellipse points aren't evenly spread
- points
- ellipse
Same job as cv2.fitEllipse - five numbers describing the ellipse through a point set - different estimator. fitEllipseAMS is OpenCV's approximate mean-square method: instead of minimising geometric distance the way the classic fit does, it works with an AMS formulation that behaves better when your points are unevenly sampled. If your blob is half-occluded, if your contour is denser on one side because of lighting, or if you clicked fourteen points on a rim and most of them happen to be on the same arc, this is the variant that stops the fit from swinging.
It ships in ComfyUI CV (bmad4ever), the pack wrapping OpenCV 5.0 as ComfyUI nodes - ~470 generated cv2.* wrappers plus curated high-level nodes. These low-level wrappers carry OpenCV's own signature and nothing else, which is why there's no "method" dropdown: the three ellipse fits are three nodes, and you pick by wiring.
Inputs and outputs
Exactly the same shape as its two siblings:
points- NPARRAY only, per the tooltip, i.e. a data array rather than an image. Nx1x2 or 1xNx2 floats, at least five of them. CV Contour To Points converts a contour into one; CV Annotate Points lets you click them; CV Reshape Array fixes up a hand-built array.ellipseout - aCV_ROTATED_RECT, nested as((cx, cy), (w, h), angle). The author's tooltip names the consumers:cv2.ellipse's box,cv2.boxPoints,cv2.rotatedRectangleIntersection. For something you can look at, CV Draw Ellipses takes Nx5 ellipses.
Note the socket type. Because CV_ROTATED_RECT is its own connection type, the value can't be quietly re-typed as a list of five numbers on the way to the next node - and cv2 itself insists on the nesting (boxPoints raises "Expected sequence length 3, got 5" if you hand it the flat spelling), which is exactly why the pack gave it a type.
When it actually beats the others
Method differences on a clean, well-distributed contour are small - sub-pixel on typical blob sizes, and invisible once you draw it. What changes is the degenerate cases:
- Classic
cv2.fitEllipseis the fast least-squares default. Cluster the points on one arc and it can return a degenerate or wildly oversized rect without complaining. Great for full rings, bad for partial ones. fitEllipseAMS(this one) is the middle ground: it handles uneven sampling of the same underlying shape better, so a half-occluded rim still gives you a sane centre and orientation.fitEllipseDirectuses the direct least-squares formulation and is guaranteed to hand back a genuine ellipse - the one to reach for when the fit has to be stable rather than fast, e.g. in a loop over hundreds of detections.
My honest take: for one-off measurement, run all three on the same points and compare. If the answers diverge by a lot, the data is the problem - no estimator will save a point set that's mostly noise. If they agree, ship the fast one.
Install
ComfyUI Manager → search ComfyUI CV, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install -r comfyui_cv/requirements.txt
Python ≥3.12 and a recent ComfyUI on the V3 node API; restart after. The dependency is opencv-contrib-python-headless~=5.0.0.93, which is where all the contrib-backed categories (fisheye, aruco, ft, ximgproc, …) come from. This node is core imgproc, so it'll be there either way - but if half the pack's nodes are missing from your search, you're looking at the contrib-wheel problem:
python ComfyUI/custom_nodes/comfyui_cv/tools/repair_opencv_contrib.py --check
Common issues
OpenCV throwing about the point array. Fewer than five points, wrong dtype, wrong nesting. The wrapper appends the actual argument shapes to cv2's error, which is the fastest fix path.
Nothing like the shape you see. Check what you're actually feeding: contour points include every boundary wiggle, and a noisy outline produces a fit biased towards the noise. CV Filter Contours can keep only contours in a measured size/shape range, and CV Merge Contours tidies fragmented outlines before they ever reach a fitter.
You want all three methods in one graph. That's three nodes on three branches from the same point array, and the pack's shaped-moments node (CV Shape Moments) gives you canonical orientation alongside - useful if what you actually need is "which way is this thing pointing" rather than a drawn ellipse.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| points | NPARRAY | - - - A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| ellipse | CV_ROTATED_RECT | - - - Rotated rectangle ((center_x, center_y), (width, height), angle in degrees) - wire it into cv2.ellipse's box, cv2.boxPoints or cv2.rotatedRectangleIntersection. |