Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull updates from COLMAP #204

Merged
merged 4 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 0 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ project(PyCOLMAP)
set(CMAKE_CUDA_ARCHITECTURES "native")
find_package(colmap 3.9 REQUIRED)

if(${CERES_VERSION} VERSION_LESS "2.2.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
endif()

add_subdirectory(pybind11)

pybind11_add_module(pycolmap main.cc)
Expand Down
4 changes: 2 additions & 2 deletions helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ inline void AddStringToEnumConstructor(py::enum_<T>& enm) {
py::implicitly_convertible<std::string, T>();
}

template <typename T>
inline void make_dataclass(py::class_<T> cls) {
template <typename T, typename... options>
inline void make_dataclass(py::class_<T, options...> cls) {
cls.def(py::init([cls](py::dict dict) {
auto self = py::object(cls());
self.attr("mergedict").attr("__call__")(dict);
Expand Down
2 changes: 1 addition & 1 deletion package/build-wheels-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ make install
cd $CURRDIR
git clone https://github.com/colmap/colmap.git
cd colmap
git checkout 0d9ab40f6037b5ede71f3af3b8d1f5091f68855d
git checkout c0355417328f3706a30a9265fd52bc7a5aa4cb8c
mkdir build/
cd build/
CXXFLAGS="-fPIC" CFLAGS="-fPIC" cmake .. -DCMAKE_BUILD_TYPE=Release \
Expand Down
2 changes: 1 addition & 1 deletion package/build-wheels-macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ brew install \
cd $CURRDIR
git clone https://github.com/colmap/colmap.git
cd colmap
git checkout 0d9ab40f6037b5ede71f3af3b8d1f5091f68855d
git checkout c0355417328f3706a30a9265fd52bc7a5aa4cb8c
mkdir build
cd build
cmake .. -DGUI_ENABLED=OFF -DCUDA_ENABLED=OFF -DCGAL_ENABLED=OFF #-DBoost_USE_STATIC_LIBS=ON -DBOOSTROOT=${BOOST_DIR} -DBoost_NO_SYSTEM_PATHS=ON
Expand Down
17 changes: 8 additions & 9 deletions pipeline/images.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,18 @@ Camera infer_camera_from_image(const py::object image_path_,
std::invalid_argument,
(std::string("Cannot read image file: ") + image_path).c_str());

Camera camera;
camera.SetCameraId(kInvalidCameraId);
camera.SetModelIdFromName(options.camera_model);
double focal_length = 0.0;
if (bitmap.ExifFocalLength(&focal_length)) {
camera.SetPriorFocalLength(true);
} else {
bool has_prior_focal_length = bitmap.ExifFocalLength(&focal_length);
if (!has_prior_focal_length) {
focal_length = options.default_focal_length_factor *
std::max(bitmap.Width(), bitmap.Height());
camera.SetPriorFocalLength(false);
}
camera.InitializeWithId(
camera.ModelId(), focal_length, bitmap.Width(), bitmap.Height());
Camera camera = Camera::CreateFromModelName(kInvalidCameraId,
options.camera_model,
focal_length,
bitmap.Width(),
bitmap.Height());
camera.has_prior_focal_length = has_prior_focal_length;
THROW_CUSTOM_CHECK_MSG(
camera.VerifyParams(),
std::invalid_argument,
Expand Down
193 changes: 72 additions & 121 deletions reconstruction/camera.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Author: Philipp Lindenberger (Phil26AT)

#include "colmap/scene/image.h"
#include "colmap/scene/camera.h"

#include "colmap/sensor/models.h"
#include "colmap/util/misc.h"
#include "colmap/util/types.h"

Expand All @@ -16,109 +18,65 @@ using namespace pybind11::literals;

#include "log_exceptions.h"

PYBIND11_MAKE_OPAQUE(std::unordered_map<camera_t, Camera>);
using CameraMap = std::unordered_map<camera_t, Camera>;
PYBIND11_MAKE_OPAQUE(CameraMap);

// TODO: cleanup
std::string PrintCamera(const Camera& camera) {
std::stringstream ss;
ss << "<Camera 'camera_id="
<< (camera.CameraId() != kInvalidCameraId
? std::to_string(camera.CameraId())
: "Invalid")
<< ", model=" << camera.ModelName() << ", width=" << camera.Width()
<< ", height=" << camera.Height() << ", num_params=" << camera.NumParams()
<< (camera.camera_id != kInvalidCameraId ? std::to_string(camera.camera_id)
: "Invalid")
<< ", model=" << camera.ModelName() << ", width=" << camera.width
<< ", height=" << camera.height << ", num_params=" << camera.params.size()
<< "'>";
return ss.str();
}

void init_camera(py::module& m) {
using CameraMap = std::unordered_map<camera_t, Camera>;
auto PyCameraModelId = py::enum_<CameraModelId>(m, "CameraModelId")
.value("INVALID", CameraModelId::kInvalid);
#define CAMERA_MODEL_CASE(CameraModel) \
PyCameraModelId.value(CameraModel::model_name.c_str(), CameraModel::model_id);

py::bind_map<CameraMap>(m, "MapCameraIdCamera")
.def("__repr__", [](const CameraMap& self) {
std::string repr = "{";
bool is_first = true;
for (auto& pair : self) {
if (!is_first) {
repr += ", ";
}
is_first = false;
repr += std::to_string(pair.first) + ": " + PrintCamera(pair.second);
}
repr += "}";
return repr;
});
CAMERA_MODEL_CASES

py::class_<Camera, std::shared_ptr<Camera>>(m, "Camera")
.def(py::init<>())
.def(py::init([](const std::string& name,
size_t width,
size_t height,
const std::vector<double>& params,
camera_t camera_id) {
std::unique_ptr<Camera> camera =
std::unique_ptr<Camera>(new Camera());
THROW_CHECK(ExistsCameraModelWithName(name));
camera->SetModelIdFromName(name);
camera->SetWidth(width);
camera->SetHeight(height);
camera->SetParams(params);
camera->SetCameraId(camera_id);
return camera;
}),
"model"_a,
"width"_a,
"height"_a,
"params"_a,
"id"_a = kInvalidCameraId)
.def(py::init([](py::dict camera_dict) {
std::unique_ptr<Camera> camera =
std::unique_ptr<Camera>(new Camera());
std::string name = camera_dict["model"].cast<std::string>();
THROW_CHECK(ExistsCameraModelWithName(name));
camera->SetModelIdFromName(name);
camera->SetWidth(camera_dict["width"].cast<size_t>());
camera->SetHeight(camera_dict["height"].cast<size_t>());
camera->SetParams(
camera_dict["params"].cast<std::vector<double>>());
return camera;
}),
"camera_dict"_a)
.def_property("camera_id",
&Camera::CameraId,
&Camera::SetCameraId,
"Unique identifier of the camera.")
.def_property(
"model_id",
&Camera::ModelId,
[](Camera& self, int model_id) {
THROW_CHECK(ExistsCameraModelWithId(model_id));
self.SetModelId(model_id);
},
"Camera model ID.")
#undef CAMERA_MODEL_CASE
PyCameraModelId.export_values();
AddStringToEnumConstructor(PyCameraModelId);
py::implicitly_convertible<int, CameraModelId>();

py::bind_map<CameraMap>(m, "MapCameraIdCamera");

py::class_<Camera, std::shared_ptr<Camera>> PyCamera(m, "Camera");
PyCamera.def(py::init<>())
.def_static("create",
&Camera::CreateFromModelId,
"camera_id"_a,
"model"_a,
"focal_length"_a,
"width"_a,
"height"_a)
.def_readwrite(
"camera_id", &Camera::camera_id, "Unique identifier of the camera.")
.def_readwrite("model_id", &Camera::model_id, "Camera model ID.")
.def_property(
"model_name",
&Camera::ModelName,
[](Camera& self, std::string model_name) {
THROW_CHECK(ExistsCameraModelWithName(model_name));
self.SetModelIdFromName(model_name);
self.model_id = CameraModelNameToId(model_name);
},
"Camera model name (connected to model_id).")
.def_property(
"width", &Camera::Width, &Camera::SetWidth, "Width of camera sensor.")
.def_property("height",
&Camera::Height,
&Camera::SetHeight,
"Height of camera sensor.")
.def_readwrite("width", &Camera::width, "Width of camera sensor.")
.def_readwrite("height", &Camera::height, "Height of camera sensor.")
.def("mean_focal_length", &Camera::MeanFocalLength)
.def_property(
"focal_length", &Camera::FocalLength, &Camera::SetFocalLength)
.def_property(
"focal_length_x", &Camera::FocalLengthX, &Camera::SetFocalLengthX)
.def_property(
"focal_length_y", &Camera::FocalLengthY, &Camera::SetFocalLengthY)
.def_property("has_prior_focal_length",
&Camera::HasPriorFocalLength,
&Camera::SetPriorFocalLength)
.def_readwrite("has_prior_focal_length", &Camera::has_prior_focal_length)
.def_property("principal_point_x",
&Camera::PrincipalPointX,
&Camera::SetPrincipalPointX)
Expand All @@ -137,18 +95,20 @@ void init_camera(py::module& m) {
.def("calibration_matrix",
&Camera::CalibrationMatrix,
"Compute calibration matrix from params.")
.def(
"params_info",
&Camera::ParamsInfo,
"Get human-readable information about the parameter vector ordering.")
.def("num_params", &Camera::NumParams, "Number of raw camera parameters.")
.def("params_info",
&Camera::ParamsInfo,
"Get human-readable information about the parameter vector "
"ordering.")
.def_property(
"params",
[](Camera& self) {
return Eigen::Map<Eigen::VectorXd>(self.ParamsData(),
self.NumParams());
// Return a view (via a numpy array) instead of a copy.
return Eigen::Map<Eigen::VectorXd>(self.params.data(),
self.params.size());
},
[](Camera& self, const std::vector<double>& params) {
self.params = params;
},
&Camera::SetParams,
"Camera parameters.")
.def("params_to_string",
&Camera::ParamsToString,
Expand All @@ -158,37 +118,11 @@ void init_camera(py::module& m) {
"Set camera parameters from comma-separated list.")
.def("verify_params",
&Camera::VerifyParams,
"Check whether parameters are valid, i.e. the parameter vector has\n"
"the correct dimensions that match the specified camera model.")
"Check whether parameters are valid, i.e. the parameter vector has"
"\nthe correct dimensions that match the specified camera model.")
.def("has_bogus_params",
&Camera::HasBogusParams,
"Check whether camera has bogus parameters.")
.def(
"initialize_with_id",
[](Camera& self,
const int model_id,
const double focal_length,
const size_t width,
const size_t height) {
THROW_CHECK(ExistsCameraModelWithId(model_id));
self.InitializeWithId(model_id, focal_length, width, height);
},
"Initialize parameters for given camera model ID and focal length, "
"and set\n"
"the principal point to be the image center.")
.def(
"initialize_with_name",
[](Camera& self,
std::string model_name,
const double focal_length,
const size_t width,
const size_t height) {
THROW_CHECK(ExistsCameraModelWithName(model_name));
self.InitializeWithName(model_name, focal_length, width, height);
},
"Initialize parameters for given camera model name and focal length, "
"and set\n"
"the principal point to be the image center.")
.def("cam_from_img",
&Camera::CamFromImg,
"Project point in image plane to world / infinity.")
Expand Down Expand Up @@ -256,14 +190,31 @@ void init_camera(py::module& m) {
.def("summary", [](const Camera& self) {
std::stringstream ss;
ss << "Camera:\n\tcamera_id="
<< (self.CameraId() != kInvalidCameraId
? std::to_string(self.CameraId())
<< (self.camera_id != kInvalidCameraId
? std::to_string(self.camera_id)
: "Invalid")
<< "\n\tmodel = " << self.ModelName()
<< "\n\twidth = " << self.Width() << "\n\theight = " << self.Height()
<< "\n\tnum_params = " << self.NumParams()
<< "\n\tmodel = " << self.ModelName() << "\n\twidth = " << self.width
<< "\n\theight = " << self.height
<< "\n\tnum_params = " << self.params.size()
<< "\n\tparams_info = " << self.ParamsInfo()
<< "\n\tparams = " << self.ParamsToString();
return ss.str();
});
PyCamera.def(py::init([PyCamera](py::dict dict) {
auto self = py::object(PyCamera());
for (auto& it : dict) {
auto key_str = it.first.cast<std::string>();
if ((key_str == "model") || (key_str == "model_name")) {
self.attr("model_id") = it.second; // Implicit conversion.
} else {
self.attr(it.first) = it.second;
}
}
return self.cast<Camera>();
}),
"dict"_a);
PyCamera.def(py::init([PyCamera](py::kwargs kwargs) {
py::dict dict = kwargs.cast<py::dict>();
return PyCamera(dict).cast<Camera>();
}));
}
4 changes: 2 additions & 2 deletions reconstruction/image.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ void init_image(py::module& m) {
.def(
"set_up",
[](Image& self, const class Camera& camera) {
THROW_CHECK_EQ(self.CameraId(), camera.CameraId());
THROW_CHECK_EQ(self.CameraId(), camera.camera_id);
self.SetUp(camera);
},
"Setup the image and necessary internal data structures before being "
Expand Down Expand Up @@ -256,7 +256,7 @@ void init_image(py::module& m) {
std::vector<Eigen::Vector2d> world_points(point3Ds.size());
for (int idx = 0; idx < point3Ds.size(); ++idx) {
world_points[idx] =
(self.CamFromWorld() * point3Ds[idx].XYZ()).hnormalized();
(self.CamFromWorld() * point3Ds[idx].xyz).hnormalized();
}
return world_points;
},
Expand Down
Loading