From 4c09e073ff3c659519c820944189222dffb5eae6 Mon Sep 17 00:00:00 2001 From: Paul-Edouard Sarlin Date: Wed, 24 Jan 2024 13:41:23 +0100 Subject: [PATCH 1/3] Add type_caster --- pycolmap/main.cc | 1 - pycolmap/pybind11_extension.h | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/pycolmap/main.cc b/pycolmap/main.cc index 2c20203..e152aef 100644 --- a/pycolmap/main.cc +++ b/pycolmap/main.cc @@ -12,7 +12,6 @@ #include "pycolmap/utils.h" #include -#include #include #include diff --git a/pycolmap/pybind11_extension.h b/pycolmap/pybind11_extension.h index 312d8ef..a96d0c9 100644 --- a/pycolmap/pybind11_extension.h +++ b/pycolmap/pybind11_extension.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -56,6 +57,43 @@ struct type_caster { } }; +// Autocast from numpy.ndarray to std::vector +template +struct type_caster>> { + public: + using MatrixType = + typename Eigen::Matrix; + using VectorType = typename Eigen::Matrix; + using props = EigenProps; + PYBIND11_TYPE_CASTER(std::vector, props::descriptor); + + bool load(handle src, bool) { + const auto buf = array::ensure(src); + if (!buf) { + return false; + } + const buffer_info info = buf.request(); + if (info.ndim != 2 || info.shape[1] != Size) { + return false; + } + const size_t num_elements = info.shape[0]; + value.resize(num_elements); + const auto& mat = src.cast>(); + Eigen::Map( + reinterpret_cast(value.data()), num_elements, Size) = mat; + return true; + } + + static handle cast(const std::vector& vec, + return_value_policy /* policy */, + handle h) { + Eigen::Map mat( + reinterpret_cast(vec.data()), vec.size(), Size); + return type_caster>::cast( + mat, return_value_policy::copy, h); + } +}; + } // namespace detail // Fix long-standing bug https://github.com/pybind/pybind11/issues/4529 From 3a5952a789377f7b73e9b4ccedf8b9c5926054ad Mon Sep 17 00:00:00 2001 From: Paul-Edouard Sarlin Date: Wed, 24 Jan 2024 15:58:58 +0100 Subject: [PATCH 2/3] Avoid copies in Camera functions --- pycolmap/scene/camera.h | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/pycolmap/scene/camera.h b/pycolmap/scene/camera.h index 882dedd..ee5d545 100644 --- a/pycolmap/scene/camera.h +++ b/pycolmap/scene/camera.h @@ -140,22 +140,23 @@ void BindCamera(py::module& m) { "Project point in image plane to world / infinity.") .def( "cam_from_img", - [](const Camera& self, const std::vector& points2D) { - std::vector world_points2D; - for (size_t idx = 0; idx < points2D.size(); ++idx) { - world_points2D.push_back(self.CamFromImg(points2D[idx])); + [](const Camera& self, + const py::EigenDRef& image_points) { + std::vector world_points(image_points.rows()); + for (size_t idx = 0; idx < image_points.rows(); ++idx) { + world_points[idx] = self.CamFromImg(image_points.row(idx)); } - return world_points2D; + return world_points; }, "Project list of points in image plane to world / infinity.") .def( "cam_from_img", - [](const Camera& self, const std::vector& points2D) { - std::vector world_points2D; - for (size_t idx = 0; idx < points2D.size(); ++idx) { - world_points2D.push_back(self.CamFromImg(points2D[idx].xy)); + [](const Camera& self, const std::vector& image_points) { + std::vector world_points(image_points.size()); + for (size_t idx = 0; idx < image_points.size(); ++idx) { + world_points[idx] = self.CamFromImg(image_points[idx].xy); } - return world_points2D; + return world_points; }, "Project list of points in image plane to world / infinity.") .def("cam_from_img_threshold", @@ -167,22 +168,22 @@ void BindCamera(py::module& m) { .def( "img_from_cam", [](const Camera& self, - const std::vector& world_points2D) { - std::vector image_points2D; - for (size_t idx = 0; idx < world_points2D.size(); ++idx) { - image_points2D.push_back(self.ImgFromCam(world_points2D[idx])); + const py::EigenDRef& world_points) { + std::vector image_points(world_points.rows()); + for (size_t idx = 0; idx < world_points.rows(); ++idx) { + image_points[idx] = self.ImgFromCam(world_points.row(idx)); } - return image_points2D; + return image_points; }, "Project list of points from world / infinity to image plane.") .def( "img_from_cam", - [](const Camera& self, const std::vector& world_points2D) { - std::vector image_points2D; - for (size_t idx = 0; idx < world_points2D.size(); ++idx) { - image_points2D.push_back(self.ImgFromCam(world_points2D[idx].xy)); + [](const Camera& self, const std::vector& world_points) { + std::vector image_points(world_points.size()); + for (size_t idx = 0; idx < world_points.size(); ++idx) { + image_points[idx] = self.ImgFromCam(world_points[idx].xy); } - return image_points2D; + return image_points; }, "Project list of points from world / infinity to image plane.") .def("rescale", From 7518756712581325a12b77902e4a3639b319946a Mon Sep 17 00:00:00 2001 From: Paul-Edouard Sarlin Date: Wed, 24 Jan 2024 16:59:42 +0100 Subject: [PATCH 3/3] Fix --- pycolmap/scene/camera.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pycolmap/scene/camera.h b/pycolmap/scene/camera.h index ee5d545..3eab552 100644 --- a/pycolmap/scene/camera.h +++ b/pycolmap/scene/camera.h @@ -141,7 +141,7 @@ void BindCamera(py::module& m) { .def( "cam_from_img", [](const Camera& self, - const py::EigenDRef& image_points) { + const py::EigenDRef& image_points) { std::vector world_points(image_points.rows()); for (size_t idx = 0; idx < image_points.rows(); ++idx) { world_points[idx] = self.CamFromImg(image_points.row(idx)); @@ -168,7 +168,7 @@ void BindCamera(py::module& m) { .def( "img_from_cam", [](const Camera& self, - const py::EigenDRef& world_points) { + const py::EigenDRef& world_points) { std::vector image_points(world_points.rows()); for (size_t idx = 0; idx < world_points.rows(); ++idx) { image_points[idx] = self.ImgFromCam(world_points.row(idx));