diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cc3b841 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +ARG UBUNTU_VERSION=22.04 +ARG NVIDIA_CUDA_VERSION=12.3.1 +FROM nvidia/cuda:${NVIDIA_CUDA_VERSION}-devel-ubuntu${UBUNTU_VERSION} as builder + +ARG COLMAP_VERSION=3.9.1 +ARG CUDA_ARCHITECTURES=70 +ENV CUDA_ARCHITECTURES=${CUDA_ARCHITECTURES} +ENV QT_XCB_GL_INTEGRATION=xcb_egl + +# Prevent stop building ubuntu at time zone selection. +ENV DEBIAN_FRONTEND=noninteractive + +# Prepare and empty machine for building. +RUN apt-get update && \ + apt-get install -y --no-install-recommends --no-install-suggests \ + git \ + cmake \ + ninja-build \ + build-essential \ + libboost-program-options-dev \ + libboost-filesystem-dev \ + libboost-graph-dev \ + libboost-system-dev \ + libeigen3-dev \ + libflann-dev \ + libfreeimage-dev \ + libmetis-dev \ + libgoogle-glog-dev \ + libgtest-dev \ + libsqlite3-dev \ + libglew-dev \ + qtbase5-dev \ + libqt5opengl5-dev \ + libcgal-dev \ + python-is-python3 \ + python3-minimal \ + python3-pip \ + python3-dev \ + python3-setuptools + +# Install Ceres. +RUN apt-get install -y --no-install-recommends --no-install-suggests wget && \ + wget "http://ceres-solver.org/ceres-solver-2.1.0.tar.gz" && \ + tar zxf ceres-solver-2.1.0.tar.gz && \ + mkdir ceres-build && \ + cd ceres-build && \ + cmake ../ceres-solver-2.1.0 -GNinja && \ + ninja install + +# Install Colmap. +RUN wget "https://github.com/colmap/colmap/archive/refs/tags/${COLMAP_VERSION}.tar.gz" -O colmap-${COLMAP_VERSION}.tar.gz && \ + tar zxvf colmap-${COLMAP_VERSION}.tar.gz && \ + mkdir colmap-build && \ + cd colmap-build && \ + cmake ../colmap-${COLMAP_VERSION} -GNinja -DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCHITECTURES} && \ + ninja install + + +# Build pyceres. +COPY . /pyceres +WORKDIR /pyceres +RUN pip install . -vv diff --git a/README.md b/README.md index 6f903d7..e19fea9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ git clone --recursive git@github.com:cvg/pyceres.git cd pyceres ``` -2. Install [COLMAP 3.8](https://colmap.github.io/) - _make sure to use tag 3.8_. +2. Install [COLMAP 3.9.1](https://colmap.github.io/) 3. Build the package: @@ -19,6 +19,19 @@ cd pyceres pip install -e . ``` +### Docker image + +Alternatively, you can build the Docker image: + +```sh +export COLMAP_VERSION=3.9.1 +export CUDA_ARCHITECTURES=70 +docker build -t pyceres \ + --build-arg COLMAP_VERSION=${COLMAP_VERSION} \ + --build-arg CUDA_ARCHITECTURES=${CUDA_ARCHITECTURES} \ + -f Dockerfile . +``` + ## Factor graph optimization For now we support the following cost functions, defined in `_pyceres/factors/`: diff --git a/_pyceres/factors/bundle.cc b/_pyceres/factors/bundle.cc index 4994781..a997589 100644 --- a/_pyceres/factors/bundle.cc +++ b/_pyceres/factors/bundle.cc @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include #include @@ -15,12 +15,9 @@ inline void WorldToPixel(const T* camera_params, const T* qvec, const T* tvec, projection[1] += tvec[1]; projection[2] += tvec[2]; - // Project to image plane. - projection[0] /= projection[2]; // u - projection[1] /= projection[2]; // v - // Distort and transform to pixel space. - CameraModel::WorldToImage(camera_params, projection[0], projection[1], &xy[0], &xy[1]); + CameraModel::ImgFromCam(camera_params, projection[0], projection[1], projection[2], + &xy[0], &xy[1]); } template @@ -43,7 +40,7 @@ class BundleAdjustmentCost { static ceres::CostFunction* Create(const Eigen::Vector2d& point2D, const double stddev) { return (new ceres::AutoDiffCostFunction, 2, 4, 3, 3, - CameraModel::kNumParams>( + CameraModel::num_params>( new BundleAdjustmentCost(point2D, stddev))); } @@ -78,7 +75,7 @@ class BundleAdjustmentConstantPoseCost : public BundleAdjustmentCost, - 2, 3, CameraModel::kNumParams>( + 2, 3, CameraModel::num_params>( new BundleAdjustmentConstantPoseCost(point2D, stddev, qvec, tvec))); } @@ -111,7 +108,7 @@ class BundleAdjustmentConstantRigCost : public BundleAdjustmentCost const Eigen::Vector4d rel_qvec, const Eigen::Vector3d rel_tvec) { return (new ceres::AutoDiffCostFunction, - 2, 4, 3, 3, CameraModel::kNumParams>( + 2, 4, 3, 3, CameraModel::num_params>( new BundleAdjustmentConstantRigCost(point2D, stddev, rel_qvec, rel_tvec))); } @@ -144,7 +141,7 @@ class BundleAdjustmentRigCost : public BundleAdjustmentCost { static ceres::CostFunction* Create(const Eigen::Vector2d& point2D, const double stddev) { return (new ceres::AutoDiffCostFunction, 2, 4, 3, - 4, 3, 3, CameraModel::kNumParams>( + 4, 3, 3, CameraModel::num_params>( new BundleAdjustmentRigCost(point2D, stddev))); } @@ -159,12 +156,12 @@ class BundleAdjustmentRigCost : public BundleAdjustmentCost { } }; -ceres::CostFunction* CreateBundleAdjustmentCost(int camera_model_id, - const Eigen::Vector2d& point2D, - const double stddev) { +ceres::CostFunction* CreateBundleAdjustmentCost( + const colmap::CameraModelId camera_model_id, const Eigen::Vector2d& point2D, + const double stddev) { switch (camera_model_id) { #define CAMERA_MODEL_CASE(CameraModel) \ - case colmap::CameraModel::kModelId: \ + case colmap::CameraModel::model_id: \ return BundleAdjustmentCost::Create(point2D, stddev); \ break; CAMERA_MODEL_SWITCH_CASES @@ -173,11 +170,11 @@ ceres::CostFunction* CreateBundleAdjustmentCost(int camera_model_id, } ceres::CostFunction* CreateBundleAdjustmentConstantPoseCost( - int camera_model_id, const Eigen::Vector2d& point2D, const Eigen::Vector4d& qvec, - const Eigen::Vector3d& tvec, const double stddev) { + const colmap::CameraModelId camera_model_id, const Eigen::Vector2d& point2D, + const Eigen::Vector4d& qvec, const Eigen::Vector3d& tvec, const double stddev) { switch (camera_model_id) { #define CAMERA_MODEL_CASE(CameraModel) \ - case colmap::CameraModel::kModelId: \ + case colmap::CameraModel::model_id: \ return BundleAdjustmentConstantPoseCost::Create( \ point2D, stddev, qvec, tvec); \ break; @@ -187,11 +184,12 @@ ceres::CostFunction* CreateBundleAdjustmentConstantPoseCost( } ceres::CostFunction* CreateBundleAdjustmentConstantRigCost( - int camera_model_id, const Eigen::Vector2d& point2D, const Eigen::Vector4d& rel_qvec, - const Eigen::Vector3d& rel_tvec, const double stddev) { + const colmap::CameraModelId camera_model_id, const Eigen::Vector2d& point2D, + const Eigen::Vector4d& rel_qvec, const Eigen::Vector3d& rel_tvec, + const double stddev) { switch (camera_model_id) { #define CAMERA_MODEL_CASE(CameraModel) \ - case colmap::CameraModel::kModelId: \ + case colmap::CameraModel::model_id: \ return BundleAdjustmentConstantRigCost::Create( \ point2D, stddev, rel_qvec, rel_tvec); \ break; @@ -200,12 +198,12 @@ ceres::CostFunction* CreateBundleAdjustmentConstantRigCost( } } -ceres::CostFunction* CreateBundleAdjustmentRigCost(int camera_model_id, - const Eigen::Vector2d& point2D, - const double stddev) { +ceres::CostFunction* CreateBundleAdjustmentRigCost( + const colmap::CameraModelId camera_model_id, const Eigen::Vector2d& point2D, + const double stddev) { switch (camera_model_id) { #define CAMERA_MODEL_CASE(CameraModel) \ - case colmap::CameraModel::kModelId: \ + case colmap::CameraModel::model_id: \ return BundleAdjustmentRigCost::Create(point2D, stddev); \ break; CAMERA_MODEL_SWITCH_CASES diff --git a/setup.py b/setup.py index ae7ce04..1471fca 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,7 @@ def build_extension(self, ext): '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, '-DPYTHON_EXECUTABLE=' + sys.executable, '-DVERSION_INFO={}'.format(self.distribution.get_version()), + '-DCMAKE_CUDA_ARCHITECTURES={}'.format(os.environ.get('CUDA_ARCHITECTURES', 'native')), ] eigen_dir = os.environ.get('EIGEN3_INCLUDE_DIRS') if eigen_dir is not None: