Nodes/ComfyUI-Majoor-ImageOps/〽️ ImageOps Roto
ComfyUI Node

〽️ ImageOps Roto

Nuke-style vector masks inside a ComfyUI node, no queue required

By MajoorWaldi·Created 9 months ago·Updated 24 days ago· 14
〽️ ImageOps Roto
  • image
  • image
  • mask
◄bypassfalse►
◄feather0.0►
◄expand0.0►
◄opacity1.00►
◄invertfalse►
◄frame_offset0►
◄viewoverlay►
◄width1024►
◄height1024►
◄shapes►

Every masking tool in ComfyUI is automatic. SAM, BiRefNet, rembg, the ControlNet-aux detectors - they hand you a matte that is either right or wrong, and when it's wrong you get a blurry brush and a bout of patience. ImageOps Roto is the other thing: a real vector rotoscoping tool, with bezier handles, booleans, keyframes and feather, drawn on the node's own canvas. It's the only node in this pack that feels like it escaped from a compositor, and that's meant as a compliment.

Reach for it when the mask has to be exact - cutting a subject out for a new background, isolating one limb, relighting a region, patching a moving object through a video. Do this on a person's hair and you'll still want SAM; do it on a building, a car, a product, a logo, or any hard-edged shape, and roto beats segmentation by a mile.

How it works

Shapes are bezier point lists in normalised image coordinates, stamped into the shapes widget as JSON (the editor manages that for you - don't hand-edit it). The backend rasterises them with supersampled edges at full image size, which is why the matte survives being reused at a different resolution. That's the whole appeal of vector roto versus painted masks: it's resolution independent and, crucially, editable later.

Each shape carries its own operation - add, subtract or intersect - plus feather, opacity, visibility and draw order, so you build a matte by stacking: a big ellipse for the torso, subtract a hole for the arm that crosses it, add the stray bit of shoulder. Animated shapes interpolate linearly between keyframes at batch index + frame_offset, so a mask you keyframe on frames 0 and 24 will animate correctly across a 24-frame batch.

The parameters and the editor

The settings that matter: feather (0 → 512 px) softens the final matte, expand (−512 → 512 px) grows or shrinks every shape at once - that's the dial you want when your matte is one pixel inside the subject - and opacity / invert grade the result. frame_offset shifts which keyframe lands on which batch frame; width/height only matter when no image is connected, in which case the node just outputs a matte of that size. view (overlay / matte / result) is live preview only - it changes what you see while editing, never what gets queued. Don't sit there wondering why your saved image is still the source.

The editor is on the node's preview canvas. V select, B bezier (click to drop points, drag to pull handles, click the first point or hit Enter to close), E ellipse, R rectangle, F freehand - the stroke becomes a smooth closed spline. Shift constrains to a circle or square. Select tool: drag points and handles (Alt breaks the tangent), double-click a segment to add a point, Delete to remove, S/C to convert a point between smooth and corner. K sets a key on the current frame; edit an already-animated shape and it auto-keys. Ctrl+Z / Ctrl+Shift+Z for undo and redo, Ctrl+drag to pan, Ctrl+wheel to zoom.

Inputs: image (optional) and nothing else besides the widgets. Outputs: image - the source with the matte written into its alpha - and mask, which is the one you'll wire into an inpaint, a latent mask, or a compositing node.

Installing it

cd ComfyUI/custom_nodes
git clone https://github.com/MajoorWaldi/ComfyUI-Majoor-ImageOps

Restart, then hard-refresh the browser (Ctrl+F5 / Cmd+Shift+R). This one really is mandatory: the entire roto editor is the pack's frontend JS, and without a cache-bust you get a node with a blank preview and no tools. ComfyUI Manager users can search ComfyUI-Majoor-ImageOps instead. Requires ComfyUI 0.19.0+ (V3 node schema); no model files, no extra pip installs.

Where people get burned

  • The preview and the queue disagree. That's view. It's a monitor, not an output setting.
  • "Adding a point ruined my animation." It's by design - adding or deleting a point applies to every keyframe of that shape. Set your point count before you start keying.
  • The mask is offset on a video. Check frame_offset. The pack's Hold mode seeks upstream video by time using the video's frame rate and assumes 24 fps when it can't detect one, so if your source is 30 fps the hold position drifts. Connect a source with a known frame rate if you need exact frame matching.
  • Sharp jaggies? You shouldn't get them - the rasteriser supersamples - but if an edge looks crunchy, add 0.5–1 px of feather. It's a matte, not a knife.
Categoryimage/imageops

Inputs (11)

NameTypeDefaultDescription
bypassBOOLEANfalse—
featherFLOAT0.00–512Gaussian feather applied to the final matte, in pixels.
expandFLOAT0.0-512–512Grow (positive) or shrink (negative) every shape, in pixels.
opacityFLOAT1.000–1—
invertBOOLEANfalse—
frame_offsetINT0-1000000–1000000Keyframes are looked up at batch index + frame_offset.
viewCOMBOoverlayLive preview only: source with matte tint, the matte alone, or the source cut by the matte.
widthINT102464–8192Matte size when no image is connected.
heightINT102464–8192Matte size when no image is connected.
shapesSTRING—
imageoptIMAGE,VIDEOImages/Video input.

Outputs (2)

NameTypeDescription
imageIMAGE—
maskMASK—