sithu31296/DGSfM

[ACCV 2026 Oral] DGSfM: Depth-Guided Scale-Aware Global Structure-from-Motion

Python

32

6 commits

updated Sep 30, 2026

See the code

README

DGSfM: Depth-Guided Scale-Aware Global Structure-from-Motion

DGSfM 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.

Installation

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.

Quick start

  1. Create a configuration from configs/custom.yaml and set root to your dataset directory.
  2. Arrange your images as described in Dataset layout.
  3. Download the Doppelgangers++ checkpoint (save it to third_party/checkpoints) if you use the default disambiguation stage.
  4. Run the commands in Pipeline, always passing the same configuration file.

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.

Dataset layout

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

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:

SettingPurposeTypical values
rootDataset root containing scene directories.Absolute path to the dataset.
dataset_nameSelects the scene-directory convention and evaluation labels.ETH3D, IMC2021, TPSfM.
matching_typeSelects candidate image pairs.exhaustive or sequential.
viewgraph.depth_modelMonocular depth estimator.MoGe2, MoGe1, MoGe3, UniDepth2, ZoeDepth.
viewgraph.feats_modelFeature extractor.LoMaB, LoMaL, LoMaG, or a dense matcher such as RoMav2.
viewgraph.match_modelCorrespondence matcher.LoMaB, LoMaL, LoMaG, RoMav1, RoMav2.
viewgraph.num_featsMaximum 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.

Sparse and dense matching

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.

Pipeline

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/.

StepCommandProduces
1. Monocular depthpython priors/monodepth.py -c <config>Per-image depth, confidence, and intrinsics.
2. Disambiguationpython priors/disambiguation.py -c <config>Pairwise Doppelgangers++ scores.
3. Dense matchingpython priors/dense_match.py -c <config>Dense RoMa warps and confidence maps. Required only for RoMa dense matching.
4. Features and correspondencespython priors/feats_corrs.py -c <config>Image features and pairwise feature matches.
5. COLMAP databasepython priors/colmapdb.py -c <config>A COLMAP database containing images, keypoints, and matches.
6. Global mappingpython 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

Outputs

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.

Evaluation

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.

reconstruction
sfm
slam

sithu31296/DGSfM

[ACCV 2026 Oral] DGSfM: Depth-Guided Scale-Aware Global Structure-from-Motion

Python

32

6 commits

updated Sep 30, 2026

See the code

README

DGSfM: Depth-Guided Scale-Aware Global Structure-from-Motion

DGSfM 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.

Installation

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.

Quick start

  1. Create a configuration from configs/custom.yaml and set root to your dataset directory.
  2. Arrange your images as described in Dataset layout.
  3. Download the Doppelgangers++ checkpoint (save it to third_party/checkpoints) if you use the default disambiguation stage.
  4. Run the commands in Pipeline, always passing the same configuration file.

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.

Dataset layout

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

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:

SettingPurposeTypical values
rootDataset root containing scene directories.Absolute path to the dataset.
dataset_nameSelects the scene-directory convention and evaluation labels.ETH3D, IMC2021, TPSfM.
matching_typeSelects candidate image pairs.exhaustive or sequential.
viewgraph.depth_modelMonocular depth estimator.MoGe2, MoGe1, MoGe3, UniDepth2, ZoeDepth.
viewgraph.feats_modelFeature extractor.LoMaB, LoMaL, LoMaG, or a dense matcher such as RoMav2.
viewgraph.match_modelCorrespondence matcher.LoMaB, LoMaL, LoMaG, RoMav1, RoMav2.
viewgraph.num_featsMaximum 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.

Sparse and dense matching

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.

Pipeline

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/.

StepCommandProduces
1. Monocular depthpython priors/monodepth.py -c <config>Per-image depth, confidence, and intrinsics.
2. Disambiguationpython priors/disambiguation.py -c <config>Pairwise Doppelgangers++ scores.
3. Dense matchingpython priors/dense_match.py -c <config>Dense RoMa warps and confidence maps. Required only for RoMa dense matching.
4. Features and correspondencespython priors/feats_corrs.py -c <config>Image features and pairwise feature matches.
5. COLMAP databasepython priors/colmapdb.py -c <config>A COLMAP database containing images, keypoints, and matches.
6. Global mappingpython 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

Outputs

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.

Evaluation

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.

reconstruction
sfm
slam