CV Disparity Interpolate (Edge-Aware)
Making a holey disparity map dense — with planes, not smears
- left
- right
- disparity
- confidence
- disparity
- valid
- seeds
- found
CV Disparity Interpolate (Edge-Aware) turns a sparse, holey disparity map into a dense one by fitting a local plane to the trustworthy pixels around each hole, guided by the rectified left image.
You'd reach for it whenever you're about to do something that needs every pixel to have a depth: back-projecting to a point cloud, rendering a parallax or VR view, measuring a distance to the ground, masking by depth. Raw SGBM output has big empty regions exactly where the scene is hardest - the sky, the road, the blank wall - and those are also the largest surfaces in frame.
Both obvious alternatives have documented failure modes here. cv2.inpaint is image-blind: it smears disparity across object silhouettes, so your foreground bleeds into the background. Letting the WLS filter do the filling is better but still assumes disparity is locally constant, so a textureless slanted surface - a road, most obviously - gets bent into a ridge. The measurement the pack ships with this node makes that concrete: run a plane fit through the road band and the RMS degrades from 0.06 m to 0.36 m, while this node keeps 0.06 m at roughly 100% coverage. If your scenes have ground planes in them, that's the entire argument.
How it works
Two interpolators, chosen by method:
- RIC - the default. Fits a plane per SLIC superpixel and keeps silhouettes best. ~0.2 s at 640x480. It randomises its model fitting, so output varies slightly run to run.
- EPIC (EpicFlow) - about twice as fast, slightly smoother on flat ground, blurrier at depth edges. Deterministic.
Both take the match set from both views, so left and right are both required inputs, and both need the pair to be rectified - this is an epipolar-geometry method, not a general stereo magic box.
Then post_smoothing runs an edge-aware global smoother over the per-superpixel planes. Leave it on global smoother (recommended): the tooltip's own measurement is edge alignment dropping from 89% to 53% without it, because raw per-superpixel planes show up as visible blocky steps.
Inputs and outputs
Required: left (rectified left frame - the guide), right (rectified right frame, same size), disparity (HxW float32 in pixels with holes; negative or zero where the matcher failed), method, and min_disparity (0.05 - the value above which an input pixel counts as a seed). Feed it the raw matcher output, not a pre-filtered map.
Optional: confidence - wire the confidence output of CV Disparity Filter (WLS) here and seeds below confidence_threshold (128) are dropped, which is how occlusions and failed left-right checks stay out of the fit. Also k (32, neighbouring seeds per local fit - larger is smoother and slower), superpixel_size (15, RIC only), post_smoothing, and max_seeds (30000).
That max_seeds cap is not optional, and the tooltip explains why: cv2 asserts when the match count hits 32767 (match_num < SHRT_MAX), and a full 640x480 map has roughly 180k valid pixels. Leave the default alone unless you enjoy hard crashes.
Outputs: disparity (dense float32), valid (uint8 mask above min_disparity, near-complete after a successful run), seeds (the input pixels actually used - preview it to see what the fit was given; genuinely useful when results look off), and found (false when there were too few seeds, in which case the input disparity is passed through unchanged).
Install
Part of comfyui_cv (bmad4ever/comfyui_cv). Search "ComfyUI CV" in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Then restart ComfyUI. Python ≥ 3.12 and a recent V3-API ComfyUI. These interpolators live in ximgproc, which is a contrib module - the contrib wheel is required, not merely recommended. Because all four OpenCV distributions share one site-packages/cv2, another pack installing plain opencv-python silently removes the contrib submodules and this node disappears from the menu; tools/repair_opencv_contrib.py --check diagnoses that, --apply repairs it.
Common issues
found = false. Too few seeds, most commonly because you interpolated a map that was already filtered down to nothing, or yourmin_disparitythreshold sits above most of the map's real values.- It runs but nothing looks different. Check
seeds- if you accidentally fed a map where almost every pixel is abovemin_disparity, the fit has no holes left to fill and the output is essentially the input. - Blocky steps across smooth surfaces.
post_smoothinggot turned off, orsuperpixel_sizeis too large for the structure you're resolving. Drop it to 8–10 on detailed scenes. - Results wobble between runs. That's RIC's randomised model fitting. Switch to EPIC if you need determinism, and accept slightly softer depth edges.
- Depth edges are fuzzy. More seeds from a confidence map, smaller
superpixel_size, higherk.
One general point from the pack's own README, worth internalising for this whole area: the shipped workflows are demonstrations, and several pipelines in them are tuned to specific datasets. The nodes are the reusable part. Treat the numbers above as measurements from a particular stereo pair, not as promises about yours.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| left | NPARRAY,IMAGE | Rectified LEFT frame - the guide whose edges and superpixels the interpolation follows. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size. | |
| right | NPARRAY,IMAGE | Rectified RIGHT frame. Same size as 'left'; the interpolators take both views of the match set. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size. | |
| disparity | NPARRAY | HxW float disparity in PIXELS with holes (negative / zero where the matcher failed), e.g. 'CV Stereo Disparity (SGBM)' or the 'disparity_raw' output of the WLS node. | |
| method | COMBO | RIC (superpixel plane fit) | RIC fits a plane per SLIC superpixel and keeps silhouettes best (~0.2 s at 640x480); EPIC (EpicFlow) is ~2x faster and slightly smoother on flat ground but blurrier at depth edges. RIC randomizes its model fitting, so its output varies slightly run to run; EPIC is deterministic. |
| min_disparity | FLOAT | 0.05-256–256 | Disparity above which an input pixel counts as a seed. The SGBM nodes mark invalid pixels below min_disparity, so the default keeps everything positive. |
| confidenceopt | NPARRAY | Optional HxW confidence map (0-255), e.g. the 'confidence' output of 'CV Stereo Disparity (WLS filtered)'. Seeds below the threshold are dropped, which is how occlusions and failed left-right checks stay out of the fit. | |
| confidence_thresholdopt | FLOAT | 1280–255 | Minimum confidence for a seed (ignored when no confidence map is connected). |
| kopt | INT | 324–256 | Neighbouring seeds used to fit each local model. Larger = smoother and slower. |
| superpixel_sizeopt | INT | 154–64 | RIC only: average SLIC superpixel side in pixels. Smaller follows finer structure at more cost. |
| post_smoothingopt | COMBO | global smoother (recommended) | Run the edge-aware global smoother over the interpolated result. 'none' leaves the raw per-superpixel planes visible as blocky steps (measured: edge alignment 89% -> 53%). |
| max_seedsopt | INT | 3000064–32000 | Seeds are subsampled to at most this many. cv2 ASSERTS on 32767 or more (match_num < SHRT_MAX), and a full 640x480 map has ~180k valid pixels, so this cap is not optional. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| disparity | NPARRAY | HxW float32 dense disparity in pixels. |
| valid | NPARRAY | uint8 0/255 mask of pixels with a disparity above min_disparity (near-complete after a successful interpolation). |
| seeds | NPARRAY | uint8 0/255 mask of the input pixels actually used as seeds - preview it to see what the fit was given. |
| found | BOOLEAN | False when there were too few seeds to interpolate; the input disparity is passed through unchanged. |