OpenCV fitEllipseAMS_1
The OpenCV ellipse fitter that answers in a string
- points
- literal
You've found the contour of something round - a coin, an eye, a wheel, a droplet - and now you want its center, its size, and exactly how far it's tilted. That's what this node does: it takes a pile of 2D points and fits the best ellipse through them, using OpenCV's fitEllipseAMS function wrapped for ComfyUI.
It's an analysis node, not a filter. It doesn't touch pixels in the usual way, so don't wire it into the image path expecting to see a prettier picture. You reach for it downstream of detection: get a contour or a point cloud out of an OpenCV segmentation step, feed it in, and read the geometry out the other side. If you're building something that needs to measure rather than render - aligning a subject, finding the rotation of a part, tracking a circular object frame to frame - this is the node.
How it works
fitEllipseAMS fits an ellipse by minimizing an approximate mean square error, which is the "AMS" in the name. It's one of three ellipse fits OpenCV ships - plain fitEllipse, fitEllipseAMS, and fitEllipseDirect - and this pack dutifully generated nodes for all of them. AMS is the one that holds up better with noisy point sets; the direct method is faster but simpler. For clean, well-sampled contours you'd barely notice a difference.
The pack is auto-generated from OpenCV's type stubs, and here's where that shows: fitEllipse returns a RotatedRect - a composite type the generator doesn't support - so instead of getting numbers out, you get a string literal. That's expected behavior, not a bug.
Inputs and outputs
There's exactly one input that matters:
- points (
NPARRAY) - a set of 2D points, typically an N×2 float array of(x, y)pairs from a contour or detection step.
And one output:
- literal (
STRING) - the fitted ellipse as a Python literal string, shaped like((center_x, center_y), (width, height), angle). The angle is in degrees, measured counterclockwise from the horizontal.
The catch: it's text. If you want to use that angle as a number - say, to drive a rotation - you're parsing a string, because there's no convenience node in the pack yet to unpack a RotatedRect. Keep that in mind before you build a whole workflow around the value.
Installing
This node ships in geroldmeisinger/opencv-comfyui, an auto-generated pack wrapping hundreds of standalone OpenCV functions. Install it once and you get all of them (635 nodes - the menu gets crowded, and this pack is honest about it: "Expect dragons!").
Via ComfyUI Manager: search for "opencv-comfyui" and install. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui
Then restart ComfyUI. The pack needs opencv-contrib-python (its requirements.txt installs it, plus numpy and torch):
pip install opencv-contrib-python
Common issues
The whole pack has a few standing gotchas that will bite you here too. Images must be converted between Comfy's IMAGE tensor and OpenCV's NPARRAY (Image2Nparray in, Nparrays2Image out) - and Image2Nparray only accepts batch_size==1, so run single images through it. If you feed this node a grayscale or color image when it wants a point array, you'll get shape errors; points wants coordinates, not pixels.
And if you see invalid syntax from any of these nodes, it's the literal-string parameters being parsed with ast.literal_eval - check your Python syntax in the text box.
Honestly: this is a niche node for people doing geometric analysis in ComfyUI. If you just want to rotate an image to match a tilted object, there are friendlier packs. If you're fitting ellipses to point clouds, this is the one.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| points | NPARRAY | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| literal | STRING | — |