Auto Roto

This setup "selects pixels" by learning from your examples and propagating the mask temporally. It's not 100% hands-off (you need initial keyframes), but it's as automated as Nuke's native tools get without plugins.### Usage Instructions

  1. Paste the script into Nuke's Script Editor and hit **Run**. It will create the "AutoRoto" Gizmo in your Node Graph.

  2. Connect your footage (Read node) to the Gizmo's input.

  3. **Train it**:

    • Scrub to 5-10 diverse keyframes (e.g., where the object moves/rotates).

    • In the RotoPaint tab (exposed knob), paint rough white masks over the object you want to isolate (use Brush tool, set to white on black background).

    • Go back to the main tab, set CopyCat's "operation" to "learn" and click **Train** (it analyzes your painted frames).

    • Switch "operation" to "predict" to generate auto-masks for all frames.

  4. Adjust the "num_samples" knob (default 8) for more training data if needed.

  5. Tweak Dilate/Erode for edge softening.

  6. The output is an RGBA with alpha as your pixel selection mask (use it downstream for compositing).

The Gizmo exposes key knobs for easy control: training samples, operation mode, dilation, and RotoPaint curves.

First submitted: 20 September 2025

Author: RedFijian1

Compatible Nuke versions: 16.0 or later

Compatibility: Source

import nuke

def create_auto_roto_gizmo():
    # Create the Group (Gizmo)
    group = nuke.Group(name="AutoRoto")
    group.setInput(0, None) # Expects input from upstream (e.g., Read)
    
    with group:
        # Input proxy
        nuke.createNode("Input", inpanel=False)
        
        # RotoPaint for manual keyframe masks (exposed for editing)
        rotopaint = nuke.createNode("RotoPaint", inpanel=False)
        rotopaint.setInput(0, nuke.toNode("Input"))
        rotopaint["operation"].setValue("copy") # Copy RGB + alpha
        rotopaint.setXYpos(0, 0)
        
        # CopyCat for auto-propagation (ML-based pixel selection)
        copycat = nuke.createNode("CopyCat", inpanel=False)
        copycat.setInput(0, rotopaint)
        copycat["operation"].setValue("none") # Default; change to 'learn' then 'predict'
        copycat["num_samples"].setValue(8) # Number of training frames
        copycat["learn_from"].setValue("alpha") # Learn from painted alpha
        copycat.setXYpos(0, 100)
        
        # Dilate/Erode for mask cleanup
        dilate = nuke.createNode("Dilate", inpanel=False)
        dilate.setInput(0, copycat)
        dilate["size"].setValue(1.0) # Expose for tweak
        dilate["operation"].setValue("dilate")
        dilate.setXYpos(0, 200)
        
        erode = nuke.createNode("Erode", inpanel=False)
        erode.setInput(0, dilate)
        erode["size"].setValue(1.0) # Match dilate for symmetry
        erode.setXYpos(0, 300)
        
        # Output with alpha as matte
        nuke.createNode("Output", inpanel=False)
        nuke.toNode("Output").setInput(0, erode)
    
    # Expose key knobs to the Gizmo's interface
    group["num_samples"].setValue(copycat["num_samples"].value())
    group["dilate_size"].setValue(dilate["size"].value())
    group["erode_size"].setValue(erode["size"].value())
    group["roto_curves"].setValue(rotopaint["curves"].value()) # For editing masks
    group["copycat_op"].setValue(copycat["operation"].value()) # For learn/predict toggle
    
    # Link exposed knobs back to internals
    group["num_samples"].setExpression('python: nuke.thisNode()["num_samples"].setValue(nuke.toNode("root").node("CopyCat1")["num_samples"])')
    # Note: For full linking, add tab with custom Python panel if needed (see Nuke docs)
    
    # Save as Gizmo (optional: saves to ~/.nuke/gizmos/)
    nuke.scriptSaveAsGizmo(group)
    
    print("AutoRoto Gizmo created! Connect input footage and train on keyframes.")
    return group

# Run the function
create_auto_roto_gizmo()

Sign in or register to download or rate.