Nodes/ComfyUI CV/CV Draw Ellipses
ComfyUI Node

CV Draw Ellipses

Because straight-line fitting lies about round things

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Draw Ellipses
  • source
  • ellipses
  • labels
  • image
  • count
◄thickness2►
◄color(0, 255, 0)►
◄draw_centerstrue►

Why you'd reach for this

An ellipse's five numbers - centre, two semi-axes, an angle - are a compact, honest description of anything roundish seen at an angle. Rims, eyes, coins on a table, the end of a cylinder. Ellipse fitting is how classic CV describes them, and it's also how the pack's Edge Drawing node reports what it found.

But five numbers per object are unreadable in a table, and an ellipse drawn slightly wrong is very visible - you instantly see whether the fit hugs the rim or floats somewhere near it. This node is that check.

How it works

It takes Nx5 rows of (cx, cy, semi_axis_a, semi_axis_b, angle_deg) and calls cv2.ellipse once per row. Nx4 is accepted too, treated as an axis-aligned ellipse with angle 0 - a convenience so you can hand it a centre-and-radii set without padding a column of zeros yourself. A circle is just a == b, so you don't need a separate node for it.

CV Edge Drawing emits exactly this row layout, which is the intended pairing: that node finds ellipses among its segments and lines, and this one draws them so you can see whether the detector's ellipses are the objects you wanted or the shadows next to them.

Like every drawing node here, -1 as thickness fills the shape, and draw_centers defaults on - a small dot at each centre. With several concentric or nested fits that dot is what keeps the render legible instead of a pile of rings.

Also like the rest of the pack: None or an empty array passes the image through unchanged with count = 0. Hough-style detectors return nothing all the time; treating that as an error would make the node unusable in a folder-wide run. And the output format follows the input, IMAGE → IMAGE, MASK → MASK, so the node slots into a mask graph without conversion.

Inputs and outputs that matter

  • ellipses - Nx5 or Nx4. Get the column order right; a swapped semi-axis pair gives you a plausible-looking ellipse rotated by 90°, which is exactly the kind of bug a visualizer is supposed to catch.
  • thickness - default 2, -1 fills.
  • color - a bare number (broadcast to all channels) or a BGR tuple. On a MASK, only the blue component survives, so use '255'.
  • draw_centers - default true.
  • labels (optional) - one colour per cluster, from the same safe categorical palette as CV Draw Points, so an ellipse and the points it came from agree on colour.
  • image and count. Branch on count with an if/else (Basic Data Handling's, which the README names as a companion pack) if the nothing-found case needs its own path - that's the pattern the author's own tooltip suggests, and it beats letting an empty overlay pretend to be a result.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Python ≥ 3.12 and a ComfyUI recent enough for the V3 node API, or search ComfyUI CV in ComfyUI Manager. No model, no VRAM - this is cv2.ellipse on the CPU.

Common issues

  • Ellipses elsewhere on the frame than the objects. You're drawing detections computed on a resized or letterboxed copy. Fit and draw at the same resolution.
  • Degenerate slivers. A near-zero semi-axis means a bad fit - probably too few inlier points. Look upstream at how many points fed the fit.
  • Invisible on a mask. BGR tuple, one channel, blue-only. Use a single value.
  • Angle looks 90° off. semi_axis_a and semi_axis_b swapped, or the angle is in radians from whatever produced the array. cv2's angle here is degrees - and the node is strict about the array: anything that isn't Nx5 or Nx4 raises with the shape it got.
  • Contrib wheels. A plain opencv-python install over opencv-contrib-python-headless empties the shared contrib submodules and contrib-backed nodes disappear from the pack. tools/repair_opencv_contrib.py --check then --apply.
Categoryimage/CV/points

Inputs (6)

NameTypeDefaultDescription
sourceCOMFY_MATCHTYPE_V3Image or mask to draw on (a copy is made). 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.
ellipsesNPARRAYNx5 (cx, cy, semi_axis_a, semi_axis_b, angle_deg) or Nx4 (angle assumed 0); 'OpenCV Edge Drawing' plugs in directly.
thicknessINT2-1–64Outline thickness; -1 fills the ellipses.
colorSTRING(0, 255, 0)Color as a single value (broadcast to all channels) or BGR tuple, e.g. '255' or '(0, 255, 0)'. Shorter tuples are zero-padded; longer tuples are truncated. Ignored when labels are connected.
draw_centersBOOLEANtrueAlso mark each center with a small dot.
labelsoptNPARRAY(N,) integer labels: one color per cluster.

Outputs (2)

NameTypeDescription
imageCOMFY_MATCHTYPE_V3Same format as the image input.
countINTHow many ellipses were drawn - branch on it with if/else for the nothing-found case.