mrv2 Annotations Image Node
Turn mrv2 scribbles into real inpainting masks
- IMAGE
- MASK
If you review frames in mrv2 - the open-source VFX player - you probably already scribble over them: a rectangle around the thing that's wrong, an arrow at the artifact, a redraw path. Those annotations are masks in waiting, and mrv2AnnotationsImageNode is what turns them into something ComfyUI can actually use. It reads mrv2's .json annotation export and renders it into a proper MASK tensor plus a colored IMAGE of the drawing. The "import your review notes" half of the ComfyUI-mrv2 pack, and the natural partner to its sibling mrv2SaveEXRImage on the export side.
How it works
The node has exactly one input: a dropdown listing files in the pack's json_files/ folder. Drop your mrv2 annotation JSON in there (next to the put_mrv2_json_files_here.txt placeholder it ships with), and it shows up in the list.
Under the hood it reads the annotation's render_size for canvas dimensions, then walks every shapes entry in the JSON. Each shape has a type, a float color (mapped to 0–255), and either a list of pts or center/radius. It draws onto a canvas four times larger than the final image for antialiasing, then downsamples with Lanczos. Handled shape types: DrawPath, Rectangle, FilledRectangle, ErasePath, Arrow, Circle, FilledCircle, Polygon, FilledPolygon. The mask comes out white-on-black wherever anything was drawn; ErasePath carves back to black, so you can draw corrections over a filled region. Text shapes (Text, GL2Text) are silently skipped - good to know, because mrv2 review notes are usually half text and half shapes. The node also returns time.time() from its changed-check, so it re-executes every run and always picks up your latest file edit without manual refreshing.
What you wire it into
The outputs are IMAGE and MASK. The IMAGE is the annotation overlay drawn on black - treat it as a preview/reference, not your plate; feed your actual frame into the graph separately. The MASK is the one that does the work: it plugs into VAE Encode for Inpainting (or a Set Latent Noise Mask), and the classic loop is mrv2 review → export JSON → drop in json_files/ → mask → inpaint → save EXR → back to the compositor. It's a genuinely tidy roto-to-inpaint bridge, and masked inpainting is still the tool when you need the unmasked pixels bit-identical rather than "close."
Gotchas worth knowing
The JSON has to be a real mrv2 annotation export - the code reads specific keys (render_size, annotations, shapes, and per-shape type/color/pts). A hand-built JSON with different keys will just KeyError. And one honest bug: unfilled Polygon shapes hit a typo in the drawing code and crash the node - use FilledPolygon or a path instead.
Install
Identical to the pack's other node - ComfyUI Manager → search ComfyUI-mrv2, or cd ComfyUI/custom_nodes && git clone https://github.com/ggarra13/ComfyUI-mrv2, then restart. Dependencies are openexr and pillow (this node only really needs Pillow, but the pack installs both). No models, no keys.
Fair warning: this one gets almost no search traffic - it's a niche bridge for people who already live in mrv2. But if that's you, it's the fastest route from "markup in review" to "mask in the graph."
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| annotations | COMBO | 1 options: put_mrv2_json_files_here.txt |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | The decoded image and mask. |
| MASK | MASK | — |