[ACCV 2026 Oral] DGSfM: Depth-Guided Scale-Aware Global Structure-from-Motion
See the codeDGSfM reconstructs a scene from an unordered image collection. It combines monocular depth, local or dense image correspondences, depth-aware relative pose estimation, and scaled-depth guided global optimization to produce a COLMAP-format reconstruction.
From the repository root, install DGSfM and its dependencies with:
# create a conda environment
conda create -n dgsfm python=3.12
conda activate dgsfm
conda install nvidia::cuda-toolkit==12.8.0
pip install torch==2.8.0 torchvision==0.23.0 xformers==0.0.32.post1 --index-url https://download.pytorch.org/whl/cu128
# install additional dependencies for reposed
conda install cmake -c conda-forge --override-channels
conda install eigen -c conda-forge --override-channels
# install this project as a package
pip install -e .
# install pypose and bae
# first install cudss 0.5 for cuda 12.x and cudss 0.7.1 for cuda 13.x
conda install libcudss-dev==0.5.0.16 -c conda-forge --override-channels
pip install git+https://github.com/pypose/pypose.git
pip install git+https://github.com/pypose/bae.git --no-build-isolation
Model weights are downloaded on their first use unless noted below.
configs/custom.yaml and set root to your dataset directory.third_party/checkpoints) if you use the default disambiguation stage.For example, after creating configs/my_scene.yaml:
python priors/monodepth.py -c configs/my_scene.yaml
python priors/disambiguation.py -c configs/my_scene.yaml
python priors/feats_corrs.py -c configs/my_scene.yaml
python priors/colmapdb.py -c configs/my_scene.yaml
python run_sfm_colmapdb.py -c configs/my_scene.yaml
This example uses the sparse LoMa configuration in custom.yaml, so it does not need the dense-matching command.
root is a directory containing one directory per scene. Each scene needs an images/ directory and three writable working directories. The pipeline creates the reconstruction directory (in COLMAP format), priors/ (depth, feats, matches in h5 files) and databases/ (COLMAP database .db file).
<root>/
└── <scene-name>/
├── images/ # Input images: JPG, PNG, HEIF, or HEIC
├── priors/ # Intermediate files: h5, txt
├── databases/ # COLMAP database file
└── colmap_gt/ # Optional reference COLMAP model; required for evaluation
For a single scene named garden, prepare the directory with:
mkdir -p /path/to/dataset/garden/{images}
Then copy images to /path/to/dataset/garden/images/ and set the following in your configuration:
root: /path/to/dataset
dataset_name: Custom
image_folder: images
matching_type: exhaustive
Configuration files are YAML overrides of the defaults defined in dgsfm/database/config.py. The provided Custom, ETH3D and IMC 2021 files are good starting points.
The settings most commonly changed for a new dataset are:
| Setting | Purpose | Typical values |
|---|---|---|
root | Dataset root containing scene directories. | Absolute path to the dataset. |
dataset_name | Selects the scene-directory convention and evaluation labels. | ETH3D, IMC2021, TPSfM. |
matching_type | Selects candidate image pairs. | exhaustive or sequential. |
viewgraph.depth_model | Monocular depth estimator. | MoGe2, MoGe1, MoGe3, UniDepth2, ZoeDepth. |
viewgraph.feats_model | Feature extractor. | LoMaB, LoMaL, LoMaG, or a dense matcher such as RoMav2. |
viewgraph.match_model | Correspondence matcher. | LoMaB, LoMaL, LoMaG, RoMav1, RoMav2. |
viewgraph.num_feats | Maximum features retained per image. | 4096 is used by the supplied configurations. |
With matching_type: exhaustive, all image pairs in a scene are considered. This grows quadratically with the image count. Use sequential and tune viewgraph.window_size for ordered sequences.
The provided configurations use LoMa for both feature extraction and matching:
viewgraph:
feats_model: LoMaB
match_model: LoMaB
For this sparse setup, skip priors/dense_match.py. To use dense RoMa matching, set both model fields to a RoMa variant, for example RoMav2, then include the dense-matching stage before generating features and correspondences.
Run every command from the repository root and use the same -c configuration argument throughout. Stages write their intermediates under each scene's priors/ and final database file excluding monodepth estimates in databases/.
| Step | Command | Produces |
|---|---|---|
| 1. Monocular depth | python priors/monodepth.py -c <config> | Per-image depth, confidence, and intrinsics. |
| 2. Disambiguation | python priors/disambiguation.py -c <config> | Pairwise Doppelgangers++ scores. |
| 3. Dense matching | python priors/dense_match.py -c <config> | Dense RoMa warps and confidence maps. Required only for RoMa dense matching. |
| 4. Features and correspondences | python priors/feats_corrs.py -c <config> | Image features and pairwise feature matches. |
| 5. COLMAP database | python priors/colmapdb.py -c <config> | A COLMAP database containing images, keypoints, and matches. |
| 6. Global mapping | python run_sfm_colmapdb.py -c <config> | Filtered view graph, global reconstruction, and pose evaluation. |
For the default sparse configuration, run:
python priors/monodepth.py -c configs/custom.yaml
python priors/disambiguation.py -c configs/custom.yaml
python priors/feats_corrs.py -c configs/custom.yaml
python priors/colmapdb.py -c configs/custom.yaml
python run_sfm_colmapdb.py -c configs/custom.yaml
For a dense RoMa configuration, insert this command between disambiguation and feature generation:
python priors/dense_match.py -c configs/custom_dense.yaml
For a scene named <scene-name>, DGSfM writes the following files:
<root>/<scene-name>/
├── priors/
│ ├── <depth-model>.h5
│ ├── doppelgangers_pairs.txt # When disambiguation is enabled
│ ├── <matcher>.h5 # For dense RoMa matching only
│ ├── <feature-model>_feats.h5
│ ├── <feature-model>_<matcher>.h5
│ └── focals.txt
├── databases/
│ └── <feature-model>_<matcher>.db
└── ours_<depth-model>_<feature-model>_<matcher>/
├── cameras.txt
├── images.txt
└── points3D.txt
The reconstruction is exported as a text-format COLMAP model, so it can be inspected or converted with standard COLMAP tooling.
run_sfm_colmapdb.py evaluates each reconstruction at the end of mapping. To enable it, place a reference COLMAP model in <scene>/colmap_gt/. The script reports pose AUC at the thresholds in pose_error_thresholds.
If your collection has no ground-truth COLMAP model, the reconstruction is still written before evaluation begins. The current entry point expects colmap_gt/ for its final evaluation step; remove or bypass that step in run_sfm_colmapdb.py when reconstructing an unevaluated custom collection.
[ACCV 2026 Oral] DGSfM: Depth-Guided Scale-Aware Global Structure-from-Motion
See the codeDGSfM reconstructs a scene from an unordered image collection. It combines monocular depth, local or dense image correspondences, depth-aware relative pose estimation, and scaled-depth guided global optimization to produce a COLMAP-format reconstruction.
From the repository root, install DGSfM and its dependencies with:
# create a conda environment
conda create -n dgsfm python=3.12
conda activate dgsfm
conda install nvidia::cuda-toolkit==12.8.0
pip install torch==2.8.0 torchvision==0.23.0 xformers==0.0.32.post1 --index-url https://download.pytorch.org/whl/cu128
# install additional dependencies for reposed
conda install cmake -c conda-forge --override-channels
conda install eigen -c conda-forge --override-channels
# install this project as a package
pip install -e .
# install pypose and bae
# first install cudss 0.5 for cuda 12.x and cudss 0.7.1 for cuda 13.x
conda install libcudss-dev==0.5.0.16 -c conda-forge --override-channels
pip install git+https://github.com/pypose/pypose.git
pip install git+https://github.com/pypose/bae.git --no-build-isolation
Model weights are downloaded on their first use unless noted below.
configs/custom.yaml and set root to your dataset directory.third_party/checkpoints) if you use the default disambiguation stage.For example, after creating configs/my_scene.yaml:
python priors/monodepth.py -c configs/my_scene.yaml
python priors/disambiguation.py -c configs/my_scene.yaml
python priors/feats_corrs.py -c configs/my_scene.yaml
python priors/colmapdb.py -c configs/my_scene.yaml
python run_sfm_colmapdb.py -c configs/my_scene.yaml
This example uses the sparse LoMa configuration in custom.yaml, so it does not need the dense-matching command.
root is a directory containing one directory per scene. Each scene needs an images/ directory and three writable working directories. The pipeline creates the reconstruction directory (in COLMAP format), priors/ (depth, feats, matches in h5 files) and databases/ (COLMAP database .db file).
<root>/
└── <scene-name>/
├── images/ # Input images: JPG, PNG, HEIF, or HEIC
├── priors/ # Intermediate files: h5, txt
├── databases/ # COLMAP database file
└── colmap_gt/ # Optional reference COLMAP model; required for evaluation
For a single scene named garden, prepare the directory with:
mkdir -p /path/to/dataset/garden/{images}
Then copy images to /path/to/dataset/garden/images/ and set the following in your configuration:
root: /path/to/dataset
dataset_name: Custom
image_folder: images
matching_type: exhaustive
Configuration files are YAML overrides of the defaults defined in dgsfm/database/config.py. The provided Custom, ETH3D and IMC 2021 files are good starting points.
The settings most commonly changed for a new dataset are:
| Setting | Purpose | Typical values |
|---|---|---|
root | Dataset root containing scene directories. | Absolute path to the dataset. |
dataset_name | Selects the scene-directory convention and evaluation labels. | ETH3D, IMC2021, TPSfM. |
matching_type | Selects candidate image pairs. | exhaustive or sequential. |
viewgraph.depth_model | Monocular depth estimator. | MoGe2, MoGe1, MoGe3, UniDepth2, ZoeDepth. |
viewgraph.feats_model | Feature extractor. | LoMaB, LoMaL, LoMaG, or a dense matcher such as RoMav2. |
viewgraph.match_model | Correspondence matcher. | LoMaB, LoMaL, LoMaG, RoMav1, RoMav2. |
viewgraph.num_feats | Maximum features retained per image. | 4096 is used by the supplied configurations. |
With matching_type: exhaustive, all image pairs in a scene are considered. This grows quadratically with the image count. Use sequential and tune viewgraph.window_size for ordered sequences.
The provided configurations use LoMa for both feature extraction and matching:
viewgraph:
feats_model: LoMaB
match_model: LoMaB
For this sparse setup, skip priors/dense_match.py. To use dense RoMa matching, set both model fields to a RoMa variant, for example RoMav2, then include the dense-matching stage before generating features and correspondences.
Run every command from the repository root and use the same -c configuration argument throughout. Stages write their intermediates under each scene's priors/ and final database file excluding monodepth estimates in databases/.
| Step | Command | Produces |
|---|---|---|
| 1. Monocular depth | python priors/monodepth.py -c <config> | Per-image depth, confidence, and intrinsics. |
| 2. Disambiguation | python priors/disambiguation.py -c <config> | Pairwise Doppelgangers++ scores. |
| 3. Dense matching | python priors/dense_match.py -c <config> | Dense RoMa warps and confidence maps. Required only for RoMa dense matching. |
| 4. Features and correspondences | python priors/feats_corrs.py -c <config> | Image features and pairwise feature matches. |
| 5. COLMAP database | python priors/colmapdb.py -c <config> | A COLMAP database containing images, keypoints, and matches. |
| 6. Global mapping | python run_sfm_colmapdb.py -c <config> | Filtered view graph, global reconstruction, and pose evaluation. |
For the default sparse configuration, run:
python priors/monodepth.py -c configs/custom.yaml
python priors/disambiguation.py -c configs/custom.yaml
python priors/feats_corrs.py -c configs/custom.yaml
python priors/colmapdb.py -c configs/custom.yaml
python run_sfm_colmapdb.py -c configs/custom.yaml
For a dense RoMa configuration, insert this command between disambiguation and feature generation:
python priors/dense_match.py -c configs/custom_dense.yaml
For a scene named <scene-name>, DGSfM writes the following files:
<root>/<scene-name>/
├── priors/
│ ├── <depth-model>.h5
│ ├── doppelgangers_pairs.txt # When disambiguation is enabled
│ ├── <matcher>.h5 # For dense RoMa matching only
│ ├── <feature-model>_feats.h5
│ ├── <feature-model>_<matcher>.h5
│ └── focals.txt
├── databases/
│ └── <feature-model>_<matcher>.db
└── ours_<depth-model>_<feature-model>_<matcher>/
├── cameras.txt
├── images.txt
└── points3D.txt
The reconstruction is exported as a text-format COLMAP model, so it can be inspected or converted with standard COLMAP tooling.
run_sfm_colmapdb.py evaluates each reconstruction at the end of mapping. To enable it, place a reference COLMAP model in <scene>/colmap_gt/. The script reports pose AUC at the thresholds in pose_error_thresholds.
If your collection has no ground-truth COLMAP model, the reconstruction is still written before evaluation begins. The current entry point expects colmap_gt/ for its final evaluation step; remove or bypass that step in run_sfm_colmapdb.py when reconstructing an unevaluated custom collection.