Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -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
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,27 @@ git clone --recursive [email protected]: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:

```sh
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/`:
Expand Down
48 changes: 23 additions & 25 deletions _pyceres/factors/bundle.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <colmap/camera/models.h>
#include <colmap/geometry/projection.h>
#include <colmap/scene/projection.h>
#include <colmap/sensor/models.h>
#include <colmap/util/types.h>

#include <ceres/ceres.h>
Expand All @@ -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 <typename T>
Expand All @@ -43,7 +40,7 @@ class BundleAdjustmentCost {
static ceres::CostFunction* Create(const Eigen::Vector2d& point2D,
const double stddev) {
return (new ceres::AutoDiffCostFunction<BundleAdjustmentCost<CameraModel>, 2, 4, 3, 3,
CameraModel::kNumParams>(
CameraModel::num_params>(
new BundleAdjustmentCost(point2D, stddev)));
}

Expand Down Expand Up @@ -78,7 +75,7 @@ class BundleAdjustmentConstantPoseCost : public BundleAdjustmentCost<CameraModel
const Eigen::Vector4d qvec,
const Eigen::Vector3d tvec) {
return (new ceres::AutoDiffCostFunction<BundleAdjustmentConstantPoseCost<CameraModel>,
2, 3, CameraModel::kNumParams>(
2, 3, CameraModel::num_params>(
new BundleAdjustmentConstantPoseCost(point2D, stddev, qvec, tvec)));
}

Expand Down Expand Up @@ -111,7 +108,7 @@ class BundleAdjustmentConstantRigCost : public BundleAdjustmentCost<CameraModel>
const Eigen::Vector4d rel_qvec,
const Eigen::Vector3d rel_tvec) {
return (new ceres::AutoDiffCostFunction<BundleAdjustmentConstantRigCost<CameraModel>,
2, 4, 3, 3, CameraModel::kNumParams>(
2, 4, 3, 3, CameraModel::num_params>(
new BundleAdjustmentConstantRigCost(point2D, stddev, rel_qvec, rel_tvec)));
}

Expand Down Expand Up @@ -144,7 +141,7 @@ class BundleAdjustmentRigCost : public BundleAdjustmentCost<CameraModel> {
static ceres::CostFunction* Create(const Eigen::Vector2d& point2D,
const double stddev) {
return (new ceres::AutoDiffCostFunction<BundleAdjustmentRigCost<CameraModel>, 2, 4, 3,
4, 3, 3, CameraModel::kNumParams>(
4, 3, 3, CameraModel::num_params>(
new BundleAdjustmentRigCost(point2D, stddev)));
}

Expand All @@ -159,12 +156,12 @@ class BundleAdjustmentRigCost : public BundleAdjustmentCost<CameraModel> {
}
};

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<colmap::CameraModel>::Create(point2D, stddev); \
break;
CAMERA_MODEL_SWITCH_CASES
Expand All @@ -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<colmap::CameraModel>::Create( \
point2D, stddev, qvec, tvec); \
break;
Expand All @@ -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<colmap::CameraModel>::Create( \
point2D, stddev, rel_qvec, rel_tvec); \
break;
Expand All @@ -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<colmap::CameraModel>::Create(point2D, stddev); \
break;
CAMERA_MODEL_SWITCH_CASES
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down