Skip to content

Conversation

@B1ueber2y
Copy link
Member

This PR relies on colmap/colmap#3629 so would need to wait for a new COLMAP release to be supported.

@nushakrishnan
Copy link

nushakrishnan commented Sep 15, 2025

Hello

Regarding this PR, an example script is provided below. This script fails when using hloc head and works when using this branch.

The example data can be downloaded here: https://polybox.ethz.ch/index.php/s/J3wF5ZTRtDbj5gg

from collections import defaultdict
from pathlib import Path

import pycolmap

from hloc import (
    extract_features,
    match_features,
    pairs_from_retrieval,
    triangulation
)


def pairs_from_frames(recon: pycolmap.Reconstruction):
    frame_pairs = set()
    by_index = defaultdict(list)

    for fid in sorted(recon.frames.keys()):
        fr = recon.frames[fid]
        img_ids = sorted([d.id for d in fr.data_ids])
        names = [recon.images[i].name for i in img_ids]

        for i in range(len(names)):
            for j in range(i + 1, len(names)):
                frame_pairs.add((names[i], names[j]))
                frame_pairs.add((names[j], names[i]))

        for k, n in enumerate(names):
            by_index[k].append(n)

    return frame_pairs

def postprocess_pairs_with_reconstruction(
    sfm_pairs_file: Path,
    reconstruction: pycolmap.Reconstruction | Path
):
    recon = (reconstruction if isinstance(reconstruction, pycolmap.Reconstruction)
             else pycolmap.Reconstruction(str(reconstruction)))

    frame_pairs = pairs_from_frames(recon)

    existing = set()
    with open(sfm_pairs_file, "r") as f:
        for line in f:
            a, b = line.strip().split()
            existing.add((a, b))

    # removing image pairs that belong to the same frame 
    existing = {p for p in existing if p not in frame_pairs}

    with open(sfm_pairs_file, "w") as f:
        for a, b in sorted(existing):
            f.write(f"{a} {b}\n")


def run():
    base_dir = Path("/media/test")
    keyframes_dir = base_dir / "images"
    hloc_outputs_dir = base_dir / "hloc"
    hloc_outputs_dir.mkdir(parents=True, exist_ok=True)

    reference_model_path = base_dir / "sparse"
    if not reference_model_path.exists():
        raise FileNotFoundError(f"reference_model not found at {reference_model_path}")

    triangulated_model_path = base_dir / "triangulated_model"
    pairs_path = hloc_outputs_dir / "pairs.txt"

    retrieval_conf = extract_features.confs["netvlad"]
    feature_conf   = extract_features.confs["aliked-n16"]
    matcher_conf   = match_features.confs["aliked+lightglue"]

    retrieval_path = extract_features.main(retrieval_conf, image_dir=keyframes_dir, export_dir=hloc_outputs_dir)
    features_path = extract_features.main(feature_conf, image_dir=keyframes_dir, export_dir=hloc_outputs_dir)

    pairs_from_retrieval.main(retrieval_path, pairs_path, 5)
    postprocess_pairs_with_reconstruction(pairs_path, reference_model_path)

    matches_path = match_features.main(
        conf=matcher_conf,
        pairs=pairs_path,
        features=feature_conf["output"],
        export_dir=hloc_outputs_dir,
    )

    triangulated_model = triangulation.main(
        sfm_dir=triangulated_model_path,
        reference_model=reference_model_path,
        image_dir=keyframes_dir,
        pairs=pairs_path,
        features=features_path,
        matches=matches_path,
    )

    return triangulated_model

if __name__ == "__main__":
    _ = run()

Error when using hloc head -

*** Aborted at 1757677348 (unix time) try "date -d @1757677348" if you are using GNU date ***
PC: @     0x7f757beec00f colmap::Reconstruction::TearDown()
*** SIGSEGV (@0x38) received by PID 2060485 (TID 0x7f757e925000) from PID 56; stack trace: ***
    @     0x7f757e9bfee8 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x99ee7)
    @     0x7f756376b89d (/local/home/akrishnan/research/envs/projectaria_tools_python_env/lib/python3.10/site-packages/pyceres.cpython-310-x86_64-linux-gnu.so+0x14289c)
    @     0x7f757e968520 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x4251f)
    @     0x7f757beec00f colmap::Reconstruction::TearDown()
    @     0x7f757bd3b9f4 colmap::IncrementalMapper::EndReconstruction(bool)
    @     0x7f757bc56713 colmap::IncrementalPipeline::TriangulateReconstruction(std::shared_ptr<colmap::Reconstruction> const&)
    @     0x7f757bbfde9e colmap::RunPointTriangulatorImpl(std::shared_ptr<colmap::Reconstruction> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,P�Pp�
    @     0x7f757b5e3388 (/local/home/akrishnan/research/envs/projectaria_tools_python_env/lib/python3.10/site-packages/pycolmap/_core.cpython-310-x86_64-linux-gnu.so+0x802387)
    @     0x7f757b5e813f (/local/home/akrishnan/research/envs/projectaria_tools_python_env/lib/python3.10/site-packages/pycolmap/_core.cpython-310-x86_64-linux-gnu.so+0x80713e)
    @     0x7f757b375eb2 (/local/home/akrishnan/research/envs/projectaria_tools_python_env/lib/python3.10/site-packages/pycolmap/_core.cpython-310-x86_64-linux-gnu.so+0x594eb1)
    @     0x56066d5d1962 (/usr/bin/python3.10+0x18a961)
    @     0x56066d5c842b _PyObject_MakeTpCall
    @     0x56066d5c212e _PyEval_EvalFrameDefault
    @     0x56066d6a1566 (/usr/bin/python3.10+0x25a565)
    @     0x56066d6a1436 PyEval_EvalCode
    @     0x56066d6c7ed8 (/usr/bin/python3.10+0x280ed7)
    @     0x56066d6c26df (/usr/bin/python3.10+0x27b6de)
    @     0x56066d6c7c75 (/usr/bin/python3.10+0x280c74)
    @     0x56066d6c7258 _PyRun_SimpleFileObject
    @     0x56066d6c6f37 _PyRun_AnyFileObject
    @     0x56066d6bb3ae Py_RunMain
    @     0x56066d69547d Py_BytesMain
    @     0x7f757e94fd90 (/usr/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
    @     0x7f757e94fe40 __libc_start_main
    @     0x56066d695375 _start
Segmentation fault

@B1ueber2y
Copy link
Member Author

B1ueber2y commented Sep 17, 2025

@nushakrishnan Thank you! This PR should be ready now. Can you help confirm if this works with the pycolmap 3.12.6 from pypi after it is released (should be available after some minutes: https://github.com/colmap/colmap/actions/runs/17792996954)

@nushakrishnan
Copy link

Hello @sarlinpe @Phil26AT @B1ueber2y , I can confirm that with pycolmap installed via pypi (v3.12.6) and hloc installed via this branch, the example script succeeds. Thanks!

Copy link
Collaborator

@Phil26AT Phil26AT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, have you checked whether the existing evals still run, e.g., if SP+SG on Aachen runs?

If yes, I think we can merge.

@nushakrishnan
Copy link

Looks good, have you checked whether the existing evals still run, e.g., if SP+SG on Aachen runs?

If yes, I think we can merge.

Hello, I was able to reproduce the results close to the reported values
Aachen day: 88.1 / 94.9 / 97.9 night: 84.7 / 92.9 / 99.0

Can we merge in this case?

Copy link
Member

@sarlinpe sarlinpe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Copy link
Member

@sarlinpe sarlinpe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@sarlinpe sarlinpe merged commit 374799c into master Sep 22, 2025
1 check passed
@sarlinpe sarlinpe deleted the features/pycolmap_database branch September 22, 2025 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants