π¬ Ellipse Detection (Simple)
For the Circles Hough Can't Catch β Ellipse Detection the Simple Way
- image
- image_output
- standard_mask
- inverted_mask
The Hough node in this pack is great at perfect circles and useless at everything else. The moment a wheel is viewed from an angle, or a porthole reads as a flattened oval, Hough comes back empty-handed - the author lists exactly this as a known open issue. This node is the companion that picks up the slack, and it works a completely different way: plain OpenCV contour analysis instead of the Hough transform. Same philosophy - pure math, no model weights, no GPU, deterministic results - but built to tolerate squashed circles.
How it works
The pipeline is short and readable: grayscale, then a median blur, then an Otsu binary threshold, then findContours walks the result. Each contour is simplified with approxPolyDP and screened by how close its area comes to the ellipse that would fit in its bounding box. Winners get drawn and filled into a mask. That "how close to a real ellipse" score is the heart of the node, and it's what makes the settings click.
The inputs that matter
- div (default 0.5) - the acceptance threshold for that area ratio. A perfect ellipse scores close to 1.0, so a higher
divmeans "only accept things that are basically perfect ellipses," and a lower one lets sloppier, more deformed shapes through. If an ellipse you want is being rejected, dragdivdown. - eps (default 0.01) - the approximation tolerance for
approxPolyDP, as a fraction of the contour perimeter. Too small and contours stay jagged; too large and you lose the shape. - number_sections (default 1) - the minimum number of polygon sides a contour must approximate to before it's even considered. The default accepts everything, which is usually right.
- contour_switch - draw the raw contour (on) or the angular polygon approximation (off). Leave it on for smooth ellipses; the polygon view is mainly a debugging aid.
- exclude_circles (optional input) - same trick as the Hough node: run once, note the numbers drawn on the output, then pass a comma list like
1,4to drop those on the next run. Deterministic math makes this reliable.
One thing worth knowing from the code: the masks here are solid-filled (via fillPoly), not just outlines. That's actually nicer for inpainting than the circle node's stroke-style masks - you get a clean filled region to set.
Outputs
- image_output - the input with detected ellipses drawn in
color_tuple_ellipse, numbered if you want. - standard_mask / inverted_mask - the two MASK tensors, filled white-on-black and its inverse. Wire either into a Set Mask node to target inpainting inside the shapes, or the inverse to target everything outside them.
That's it - three outputs, no colored preview mask, no terminal data string. Leaner than its sibling, which is fine for the job.
The one real gotcha
Because it leans on Otsu's threshold, the node works best when your ellipses are a clearly different brightness from the background. Otsu assumes a bimodal histogram - dark shapes on a light background, or the reverse. Give it a busy, low-contrast photo and the contour list fills with noise that the area-ratio filter has to chew through. This is a "detect shapes on a clean background" tool, not a magic semantic segmenter.
Installation
It ships in the same pack as the Hough node, so one install gets you both. No models, no extra dependencies - only cv2/PIL/torch that ComfyUI already has:
cd ComfyUI/custom_nodes
git clone https://github.com/zentrocdot/ComfyUI_Circle_Detection
or search "Circle Detection" in ComfyUI Manager, then restart. Nodes live under 𧬠Circle Detection Nodes. If nothing seems to match, check div and the contrast of your image before touching anything else - those two account for most "it found nothing" reports.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| number_sections | INT | 11β256 | β |
| div | FLOAT | 0.500β10 | β |
| eps | FLOAT | 0.010.01β10 | β |
| contour_switch | BOOLEAN | true | β |
| color_tuple_ellipse | STRING | (255, 0, 255) | β |
| thickness | INT | 21β256 | β |
| numbering | BOOLEAN | true | β |
| number_size | INT | 11β256 | β |
| exclude_circlesopt | STRING | β |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image_output | IMAGE | β |
| standard_mask | MASK | β |
| inverted_mask | MASK | β |