[CVPR 2026] Fast-FoundationStereo: Real-Time Zero-Shot Stereo Matching
[CVPR 2026] Fast-FoundationStereo: Real-Time Zero-Shot Stereo Matching
This is the official implementation of our paper accepted to CVPR 2026
Authors: Bowen Wen, Shaurya Dewan, Stan Birchfield
Stereo foundation models achieve strong zero-shot generalization but remain computationally prohibitive for real-time applications. Efficient stereo architectures, on the other hand, sacrifice robustness for speed and require costly per-domain fine-tuning. To bridge this gap, we present Fast-FoundationStereo, a family of architectures that achieve, for the first time, strong zero-shot generalization at real-time frame rate. We employ a divide-and-conquer acceleration strategy with three components: (1) knowledge distillation to compress the hybrid backbone into a single efficient student; (2) blockwise neural architecture search for automatically discovering optimal cost filtering designs under latency budgets, reducing search complexity exponentially; and (3) structured pruning for eliminating redundancy in the iterative refinement module. Furthermore, we introduce an automatic pseudo-labeling pipeline used to curate 1.4M in-the-wild stereo pairs to supplement synthetic training data and facilitate knowledge distillation. The resulting model can run over 10× faster than FoundationStereo while closely matching its zero-shot accuracy, thus establishing a new state-of-the-art among real-time methods.
[NOTE] This model is designed for real-time applications. For offline computation for the best accuracy, please checkout our earlier work FoundationStereo.
docker build --network host -t ffs -f docker/dockerfile .
bash docker/run_container.shconda create -n ffs python=3.12 && conda activate ffs
pip install torch==2.6.0 torchvision==0.21.0 xformers --index-url https://download.pytorch.org/whl/cu124
pip install -r requirements.txtCommercial use: Download C-Fast-FoundationStereo under the NVIDIA Open Model Agreement. For commercially licensed training and inference code, see NVIDIA TAO Toolkit.
Research checkpoints: Download from Google Drive and put under the folder weights/ (e.g. ./weights/23-36-37). Below table compares the differences among some representative models of varying sizes from our trained family. They are sorted from slowest to fastest, with accuracy descending, where runtime is profiled on GPU 3090, image size 640x480.
To trade-off speed and accuracy, there are two options:
| Checkpoint | valid_iters | Runtime-Pytorch (ms) | Runtime-TRT (ms) | Peak Memory (MB) |
|---|---|---|---|---|
23-36-37 |
8 | 49.4 | 23.4 | 653 |
23-36-37 |
4 | 41.1 | 18.4 | 653 |
20-26-39 |
8 | 43.6 | 19.4 | 651 |
20-26-39 |
4 | 37.5 | 16.4 | 651 |
20-30-48 |
8 | 38.4 | 16.6 | 646 |
20-30-48 |
4 | 29.3 | 14.0 | 646 |
python scripts/run_demo.py --model_dir weights/23-36-37/model_best_bp2_serialize.pth --left_file demo_data/left.png --right_file demo_data/right.png --intrinsic_file demo_data/K.txt --out_dir output/ --remove_invisible 0 --denoise_cloud 1 --scale 1 --get_pc 1 --valid_iters 8 --max_disp 192 --zfar 100| Flag | Meaning |
|---|---|
--model_dir |
Path to the trained weights/model file |
--left_file |
Path to the left image file |
--right_file |
Path to the right image file |
--intrinsic_file |
Path to the camera intrinsic matrix and baseline file |
--out_dir |
Output directory for saving results |
--remove_invisible |
Whether to ignore non-overlapping region's depth (0: no, 1: yes) |
--denoise_cloud |
Whether to apply denoising to the point cloud (0: no, 1: yes) |
--scale |
Image scaling factor |
--get_pc |
Obtain point cloud output (0: no, 1: yes) |
--valid_iters |
Number of refinement updates during forward pass |
--max_disp |
Maximum disparity for volume encoding, 192 should be enough, unless you need to sense very near objects (e.g. <0.1m). Increasing it runs slower and uses more memory. |
--zfar |
Maximum depth to include in point cloud |
Refer to scripts/run_demo.py for comprehensive list of flags.
Tips:
--scale 0.5 to downsize input image, then upsize the output depth to your need with nearest neighbor interpolation.--scale 0.5, and reduce refine iterations by e.g. --valid_iters 4.Expect to see results like below:
Disparity/Depth:
Point cloud:
For TRT, we recommend first setup env in docker.
Export the full model as a single ONNX file. This replaces the Triton GWC kernel with ONNX-compatible ops so no intermediate engine split is needed.
python scripts/make_single_onnx.py --model_dir weights/23-36-37/model_best_bp2_serialize.pth --save_path output/ --height 480 --width 640 --valid_iters 8 --max_disp 192| Flag | Meaning |
|---|---|
--model_dir |
Path to the trained weights/model file |
--save_path |
Directory to save the ONNX model and config |
--height |
Input image height, must be divisible by 32. Reduce for faster speed. |
--width |
Input image width, must be divisible by 32. Reduce for faster speed. |
--valid_iters |
Number of refinement updates during forward pass, reduce for faster speed, but may drop quality |
--max_disp |
Maximum disparity for volume encoding, 192 should be enough, unless you need to sense very near objects (e.g. <0.1m). Increasing it runs slower and uses more memory. |
--onnx_name |
Base name for the saved ONNX file (default: fast_foundationstereo) |
Then convert to a single TRT engine:
trtexec --onnx=output/fast_foundationstereo.onnx --saveEngine=output/fast_foundationstereo.engine --fp16To run inference with the single ONNX or TRT engine:
python scripts/run_demo_single_trt.py --model_dir output/ --left_file demo_data/left.png --right_file demo_data/right.png --intrinsic_file demo_data/K.txt --out_dir output_demo/ --get_pc 1 --remove_invisible 0 --denoise_cloud 1 --zfar 100The script auto-detects .engine or .onnx files in --model_dir. To use a specific file, pass --model_file directly.
| Flag | Meaning |
|---|---|
--model_dir |
Directory containing the .onnx/.engine file and its .yaml config |
--model_file |
Explicit path to .onnx or .engine file (overrides auto-search) |
--left_file |
Path to the left image file |
--right_file |
Path to the right image file |
--intrinsic_file |
Path to the camera intrinsic matrix and baseline file |
--out_dir |
Output directory for saving results |
--remove_invisible |
Whether to ignore non-overlapping region's depth (0: no, 1: yes) |
--denoise_cloud |
Whether to apply denoising to the point cloud (0: no, 1: yes) |
--get_pc |
Obtain point cloud output (0: no, 1: yes) |
--zfar |
Maximum depth (m) to include in point cloud |
Note: The single ONNX model expects pre-normalized float32 inputs (ImageNet normalization stripped). The inference script handles this automatically. If integrating into your own pipeline, apply normalization beforehand:
normalized = (pixel - mean) / std
mean = [123.675, 116.28, 103.53]
std = [ 58.395, 57.12, 57.375]The original export splits the model into two ONNX files around the Triton GWC kernel, which runs as an intermediate step between the two TRT engines.
python scripts/make_onnx.py --model_dir weights/23-36-37/model_best_bp2_serialize.pth --save_path output/ --height 448 --width 640 --valid_iters 8 --max_disp 192| Flag | Meaning |
|---|---|
--model_dir |
Path to the trained weights/model file |
--save_path |
Directory to save ONNX outputs and zip file |
--height |
Input image height, better to be divisible by 32. Reduce image size can increase speed. |
No open issues yet, or sync has not completed.