Irregular To EllipseMask
Turn a messy hand-drawn mask into a clean, regular shape
- mask
- ellipse_mask
Some masks you want exactly as they are. Others you want regularized - a smooth, predictable region that an edit model can work inside without tripping over ragged edges. Irregular To EllipseMask is the second kind. You feed it a rough mask and it fits a clean ellipse (or convex hull) around the shape and hands it back. It's the "make my masking look professional" button.
Where it actually earns its keep: product shots where you want a soft elliptical vignette, inpainting regions that should be rounder than your lasso was, or any workflow where a slightly bigger, smoother mask gives the edit model room to blend. It's also handy when you're deriving masks from segmentation output and the raw blob has holes and pockmarks you don't want.
How it works
It's OpenCV geometry all the way down. The mask gets binarized, optionally hole-filled (via scipy.ndimage.binary_fill_holes), then the biggest contour is fit with cv2.fitEllipse. Three output_modes change the final shape: ellipse (the best-fit ellipse), convex_hull (the polygon that wraps the shape without concavities), and filled_original (which skips the shape-fitting entirely and just gives you the hole-filled blob - useful when all you wanted was the cleanup, not the geometry).
The settings worth knowing:
keep_region-largestkeeps only the biggest blob,top/bottom/left/rightpick the one on that side,allkeeps everything. Defaultlargest, which is right for most "I want the subject" cases.expand_mask- positive dilates (grows) the result, negative erodes it. This is the practical dial when your fit is slightly smaller than the subject.blur_amount- a separate Gaussian blur on top of the shape, for feathering an inpaint boundary.smoothing_kernel_size- odd numbers only (3–31); it's enforced in code if you slip up.
Output
One MASK, named ellipse_mask, same size as the input. Feed it into a mask-to-conditioning node, a preview, or the mask input of an edit model and you're done.
Install
Part of the ComfyUI-YCNodes pack. ComfyUI Manager → search "ComfyUI-YCNodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/yichengup/ComfyUI-YCNodes
Then restart ComfyUI. Deps are torch, numpy, pillow, opencv-python and scipy - note scipy specifically, since this is one of the few nodes in the pack that actually uses it (binary_fill_holes). No model downloads. Expect it under the "YCNode/Mask" menu heading.
Gotchas
cv2.fitEllipse needs at least five contour points, and the code handles the rare degenerate case by falling back to a bounding rectangle, so you won't get a crash - just a rectangular surprise. Keep your mask values in the 0–1 range (that's what ComfyUI masks are, so this is usually a non-issue). And remember expand_mask is a single integer applying to all sides; if you need per-side control, this isn't the node.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| keep_region | COMBO | largest | 6 options: all, largest, top, bottom, left, right |
| fill_holes | COMBO | enable | 2 options: enable, disable |
| smooth_edges | COMBO | enable | 2 options: enable, disable |
| smoothing_kernel_size | INT | 53–31 | — |
| output_mode | COMBO | ellipse | 3 options: ellipse, convex_hull, filled_original |
| expand_mask | INT | 0-100–100 | — |
| blur_amount | FLOAT | 0.00–100 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| ellipse_mask | MASK | — |