ComfyUI Node

AP Flow Occlusion Mask

Where the flow lies — the occlusion mask that keeps warps from ghosting

By adampolczynski·Created 6 months ago·Updated 6 months ago· 1
AP Flow Occlusion Mask
  • flow_data
  • valid_mask
  • occlusion_mask
  • confidence_visualization
flow_directionab
batch_modeauto
flow_skip0
frames_skip0
abs_epsilon1.00
rel_epsilon0.050
dilate_occlusion0
current_frame_index0

Here's the thing nobody tells you about optical flow: the flow field is a lie in the places where objects appear or disappear. When the camera pans and a building slides behind a tree, there is no correct motion vector for the tree's edge - the pixels there were covered up between frame A and frame B. If you blindly warp along the flow in those regions, you get stretching, ghosting, and smears. That's what occlusion is, and it's the difference between a flow workflow that looks like video and one that looks like a Photoshop liquify accident.

AP Flow Occlusion Mask finds those regions for you. It's the honesty check between computing flow and applying it, and it's the reason the pack's composite node can blend warped and original pixels without smearing.

The mechanism

It uses forward-backward consistency - the standard technique, done properly. APGetRAFTOpticalFlow computed both the forward (ab) and backward (ba) fields. The occlusion node warps the backward field forward, then checks: if you go A→B with the forward flow, then come back B→A with the backward flow, do you land where you started? Where the round trip fails - the cycle error exceeds a threshold - the flow is inconsistent, which is exactly where occlusion lives.

Two knobs control the strictness:

  • abs_epsilon (default 1.0) - the absolute pixel distance below which a round trip counts as consistent.
  • rel_epsilon (default 0.05) - the relative allowance, scaled by how much motion there was. Fast motion gets more slack, which is the right behavior: big displacements have more uncertainty.

dilate_occlusion grows the occlusion regions by a kernel radius (up to 32) - use it when you want the mask to also swallow the uncertain fringe around occluded areas, which often prevents a thin ghosting halo.

Outputs and how to use them

Three outputs, and each has a job:

  • valid_mask - 1 where the flow round-trips consistently, 0 at occlusions. This is what you feed to a composite so warped pixels are only trusted where the flow was actually consistent.
  • occlusion_mask - the inverse: 1 where pixels are occluded. Plug this into APFlowComposite's occlusion_mask input (set invert_occlusion there if the polarity feels wrong) so the composite keeps the original frame instead of the warped one in covered regions.
  • confidence_visualization - a grayscale image of flow confidence, useful for eyeballing which regions will ghost before you waste a render on finding out.

It also carries the same flow_direction, batch_mode, flow_skip/frames_skip, and optional current_frame_index plumbing as the other flow nodes, so it slots into index-aware loops cleanly.

Installing it

Pack-wide install: ComfyUI Manager (search "AP_OpticalFlow") or

cd ComfyUI/custom_nodes
git clone https://github.com/adampolczynski/ComfyUI_AP_OpticalFlow
python -m pip install -r custom_nodes/ComfyUI_AP_OpticalFlow/requirements.txt

then restart. torchvision>=0.15 is the only dependency.

The honest cost

This node needs the backward flow field to do its job properly. If you set compute_backward=false on APGetRAFTOpticalFlow, the backward field is just the negated forward field, and forward-backward consistency becomes nearly meaningless - you'll get an occlusion mask that thinks everything is either fine or everything is occluded. So if you're using this node, leave compute_backward on. That's the single most common setup mistake with the occlusion step, and it produces confusing garbage that looks like a node bug when it's actually a config error.

Also: occlusion masks don't fix fast motion or heavy blur. The README is upfront that flow quality degrades there, and no consistency check can recover information the flow never had. If your shot is a whip-pan with motion blur, expect the occlusion regions to be large and the composite to lean on the original frame a lot - which is, honestly, the right outcome.

CategoryAP_OpticalFlow

Inputs (9)

NameTypeDefaultDescription
flow_dataAP_FLOW
flow_directionCOMBOab2 options: ab, ba
batch_modeCOMBOauto2 options: auto, by_index
flow_skipINT00–2147483647
frames_skipINT00–2147483647
abs_epsilonFLOAT1.000–50
rel_epsilonFLOAT0.0500–1
dilate_occlusionINT00–32
current_frame_indexoptINT00–2147483647

Outputs (3)

NameTypeDescription
valid_maskMASK
occlusion_maskMASK
confidence_visualizationIMAGE