colmap / pycolmap

Python bindings for COLMAP
BSD 3-Clause "New" or "Revised" License
858 stars 125 forks source link

Error when importing pycolmap #265

Closed LRV2K1 closed 3 months ago

LRV2K1 commented 3 months ago

I have successfully used created a SFM pipeline using pycolmap and have successfully run this python file, but when I try to import this file into another file to use the SFM pipeline from there I get the following error:

Aborted at 1709306653 (unix time) try "date -d @1709306653" if you are using GNU date @ 0x7ff8865f0ef5 _seh_filter_exe @ 0x7ff6b4ee1f58 OPENSSL_Applink @ 0x7ff87e40e390 C_specific_handler @ 0x7ff888a323af chkstk @ 0x7ff8889e14b4 RtlRaiseException @ 0x7ff888a30ebe KiUserExceptionDispatcher @ 0x7ff817dd26de void cdecl ExceptionPtrRethrow(void const ptr64) @ 0x7ffff82d9ade public: void cdecl c10::ivalue::Future::markCompleted(void) __ptr64 @ 0x7ffff8670de4 struct _object ptr64 cdecl THPGenerator_initDefaultGenerator(struct at::Generator) @ 0x7ff8120ee4c5 (unknown) @ 0x7ff812647799 PyInit_pycolmap @ 0x7ff87a251080 (unknown) @ 0x7ff87a2526b5 __NLG_Return2 @ 0x7ff888a31716 RtlCaptureContext2 @ 0x7ff8120f0e90 (unknown) @ 0x7ff81293392c PyCFunction_GetFlags @ 0x7ff8128eea11 _PyObject_MakeTpCall @ 0x7ff8128f10a9 PyMethod_Self @ 0x7ff81294bcb7 _PyTuple_DebugMallocStats @ 0x7ff81294ebe9 _PyObject_LookupSpecialId @ 0x7ff81295a720 PyType_Ready @ 0x7ff8129e6192 _PyEval_EvalFrameDefault @ 0x7ff8129eaa4e _PyEval_EvalFrameDefault @ 0x7ff8128eedad _PyFunction_Vectorcall @ 0x7ff8128eeb19 PyVectorcall_Function @ 0x7ff8128eec5f _PyObject_Call @ 0x7ff8129ec4fd PyEval_GetFuncDesc @ 0x7ff8129e7d7f _PyEval_EvalFrameDefault @ 0x7ff8129eaa4e _PyEval_EvalFrameDefault @ 0x7ff8128eedad _PyFunction_Vectorcall @ 0x7ff8128eeb19 PyVectorcall_Function @ 0x7ff8128eec5f _PyObject_Call

I am using pycolmap version 0.6.1 installed via pip, and am running it on a windows system.

Is there a way to correctly import other files that use pycolmap, or do I need to have all the pycolmap functions inside the project main file?

sarlinpe commented 3 months ago

Can you provide a minimal example to reproduce this? does is occur on import pycolmap? or at a different point?

LRV2K1 commented 3 months ago

It appears to go wrong the moment I import torch https://pytorch.org/

main.py

from sfm import *
import torch

def main(
        img_path: Path,
        clean: bool = False
) -> None:
    sfm = SFM(img_path)
    sfm.sfm(clean)

if __name__ == '__main__':
    tyro.cli(main)

sfm.py

import shutil
from pathlib import Path
import os

import tyro

import enlighten

import pycolmap
from pycolmap import logging

class SFM:
    def __init__(self, img_path: Path):
        self.img_path: Path = img_path
        self.sfm_path: Path = img_path / "sfm"
        self.db_path: Path = self.sfm_path / "database.db"

        self.reconstruction: pycolmap.Reconstruction = None

    def sfm(self, clean: bool = False):
        self._sfm(clean)

        try:
            self.reconstruction = pycolmap.Reconstruction(self.sfm_path / "0")
        except:
            raise Exception("SFM could not reconstruct the data")

        # for point3D_id, point3D in self.reconstruction.points3D.items():
        #     print(point3D)
        for camera_id, camera in self.reconstruction.cameras.items():
            print(camera_id, camera)
        for image_id, image in self.reconstruction.images.items():
            print(image_id, image, f"p={image.projection_center()}", f"d={image.viewing_direction()}")

    def _sfm(self, clean: bool = False):
        if not os.path.exists(self.sfm_path):
            os.makedirs(self.sfm_path)
        if self.db_path.exists() and not clean:
            return

        logging.set_log_destination(logging.INFO, self.sfm_path / "INFO.log.")  # + time

        if self.db_path.exists():
            self.db_path.unlink()
        if self.sfm_path.exists():
            shutil.rmtree(self.sfm_path)
        self.sfm_path.mkdir(exist_ok=True)

        pycolmap.extract_features(self.db_path, self.img_path)
        pycolmap.match_exhaustive(self.db_path)
        num_images = pycolmap.Database(self.db_path).num_images

        with enlighten.Manager() as manager:
            with manager.counter(total=num_images, desc="Images registered:") as pbar:
                pbar.update(0, force=True)
                recs = pycolmap.incremental_mapping(
                    self.db_path,
                    self.img_path,
                    self.sfm_path,
                    initial_image_pair_callback=lambda: pbar.update(2),
                    next_image_callback=lambda: pbar.update(1),
                )
        for idx, rec in recs.items():
            logging.info(f"#{idx} {rec.summary()}")

def main(
        img_path: Path,
        clean: bool = False
) -> None:
    sfm = SFM(img_path)
    sfm.sfm(clean)

if __name__ == "__main__":
    tyro.cli(main)

running sfm.py does not cause any issues, running main.py returns the error.

when not importing torch in main.py the program does work, unfortunately I do need torch.

sarlinpe commented 3 months ago

So this has nothing to do with pycolmap? from sfm import * is probably a bad idea.

LRV2K1 commented 3 months ago

It appears to be that the combination pycolmap and pytorch do not cooperate, the from sfm import SFM does not fix the problem. I will try to restructure my project in such a way that they stay completely separated.

LRV2K1 commented 3 months ago

@sarlinpe Thanks for the quick help, this saved me a lot of time, I should now be able to continue after restructuring some of the code.