Video Difference Mask
Too lazy to paint a video mask? Film the shot twice and diff it
- video_with_object
- video_without_object
- mask
The hardest part of EffectErase Object Removal isn't the removal, it's the mask. Painting a mask that follows a moving object across dozens of frames is miserable, and the whole pack is useless without one. Video Difference Mask is the pack's cheat code: it hands you the mask with zero painting, by doing the one thing that always works in video - subtracting one shot from another.
Here's the idea. You control the shot, so you film it twice: once clean (no object), once with the object in frame. A locked-down camera makes every pixel identical between the two takes except where the object is. Subtract one video from the other, threshold the difference, and what's left is your object. The node does exactly that, per frame, and outputs a MASK tensor ready to plug straight into EffectErase Object Removal's video_mask input.
The mechanism
Nothing model-based here - it's plain computer vision, a short loop of numpy and OpenCV operations:
- Frame-by-frame absolute difference of the two clips (truncated to the shorter one's length and resolution).
- Per-channel differences average into grayscale and get compared against
threshold- pixels that differ more than that become "object", everything else stays background. noise_radiusruns a morphological open/close pass to kill specks and fill gaps. The 5px default is sized for the compression noise that survives in any encoded video.min_areadrops any connected blob smaller than the cutoff via connected-component analysis, so stray sensor noise doesn't become a phantom object.
The mask output is a [T, H, W] float tensor, one mask per frame - exactly the shape EffectErase Object Removal expects from video_mask.
The three knobs, in order of importance
threshold(default 0.15) - how much pixel change counts as "the object". Frames are 0–1 floats, so 0.15 is a real difference. Raise it if shadows or motion blur bleed into the mask; lower it if the object is low-contrast against the background.min_area(default 500) - the noise floor. Raising it kills specks; but if the object is small in frame, raising it too far erases the object too.noise_radius(default 5) - morphological cleanup. Leave it alone unless you're chasing a specific artifact.
Where this works - and where it absolutely does not
Be honest with yourself, because the node can't be. It only works if the only difference between the two takes is the object. That means:
- A locked-down camera. Handheld footage diffs across the whole frame and your mask comes out a mess.
- Same lighting, same exposure. Shadows count as differences - which is usually fine, you probably want the shadow gone anyway - but a cloud passing through will mask half the frame.
- You actually have the clean take. This is a production technique: plate shots, product videos, mannequin and rig removal. It is not a way to pull random objects out of archival footage you didn't shoot. For that you're back to painting masks by hand.
One thing people miss: min_area filtering is per-frame and frame-accurate, so a small object can pop in and out of the mask between frames. For video that's mostly harmless - EffectErase only needs the mask to be roughly right, since it rebuilds the whole region anyway - but if your mask flickers, raise min_area or pre-clean it before it hits the removal node.
Installing
It ships in the same pack as EffectErase Object Removal, so one install gets you both. ComfyUI Manager → search "ComfyUI-EffectErase", or:
cd ComfyUI/custom_nodes
git clone https://github.com/alisson-anjos/ComfyUI-EffectErase
# then restart ComfyUI
The good news: unlike its big sibling, this node downloads nothing. No model, no weights, no multi-gigabyte first run - it's numpy and OpenCV, and it executes in milliseconds. That also makes it a handy general utility: any workflow that needs "where did these two videos differ" can use it, even if you never touch EffectErase.
Wire mask into EffectErase Object Removal's video_mask, and you've got a completely hands-off removal loop: clean plate in, object video in, erased video out.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| video_with_object | IMAGE | — | |
| video_without_object | IMAGE | — | |
| threshold | FLOAT | 0.150.01–1 | — |
| noise_radius | INT | 50–50 | — |
| min_area | INT | 5000–100000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |