From a5e657efe46c23c7af631325d397643cc126b3fe Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 28 Aug 2024 20:40:46 +0200 Subject: [PATCH 1/7] add feature to choose voxel color mode in VoxelGrid --- cpp/open3d/geometry/VoxelGrid.h | 78 ++++++++++++++++++++++-- cpp/open3d/geometry/VoxelGridFactory.cpp | 23 ++++--- cpp/pybind/geometry/voxelgrid.cpp | 28 +++++++-- 3 files changed, 112 insertions(+), 17 deletions(-) diff --git a/cpp/open3d/geometry/VoxelGrid.h b/cpp/open3d/geometry/VoxelGrid.h index 30a228206e0..e4a7098320a 100644 --- a/cpp/open3d/geometry/VoxelGrid.h +++ b/cpp/open3d/geometry/VoxelGrid.h @@ -189,18 +189,28 @@ class VoxelGrid : public Geometry3D { double height, double depth); + /// \enum VoxelColorMode + /// + /// \brief Possible ways of determining voxel color from PointCloud. + enum class VoxelColorMode { AVG, MIN, MAX, SUM }; + /// Creates a VoxelGrid from a given PointCloud. The color value of a given - /// voxel is the average color value of the points that fall into it (if the + /// voxel is determined by the VoxelColorMode, e.g. by default the average + /// color value of the points that fall into it (if the /// PointCloud has colors). /// The bounds of the created VoxelGrid are computed from the PointCloud. /// /// \param input The input PointCloud. /// \param voxel_size Voxel size of of the VoxelGrid construction. + /// \param color_mode Mode of determining color for each voxel. static std::shared_ptr CreateFromPointCloud( - const PointCloud &input, double voxel_size); + const PointCloud &input, + double voxel_size, + VoxelColorMode color_mode = VoxelColorMode::AVG); /// Creates a VoxelGrid from a given PointCloud. The color value of a given - /// voxel is the average color value of the points that fall into it (if the + /// voxel is determined by the VoxelColorMode, e.g. by default the average + /// color value of the points that fall into it (if the /// PointCloud has colors). /// The bounds of the created VoxelGrid are defined by the given parameters. /// @@ -208,11 +218,13 @@ class VoxelGrid : public Geometry3D { /// \param voxel_size Voxel size of of the VoxelGrid construction. /// \param min_bound Minimum boundary point for the VoxelGrid to create. /// \param max_bound Maximum boundary point for the VoxelGrid to create. + /// \param color_mode Mode of determining color for each voxel. static std::shared_ptr CreateFromPointCloudWithinBounds( const PointCloud &input, double voxel_size, const Eigen::Vector3d &min_bound, - const Eigen::Vector3d &max_bound); + const Eigen::Vector3d &max_bound, + VoxelColorMode color_mode = VoxelColorMode::AVG); /// Creates a VoxelGrid from a given TriangleMesh. No color information is /// converted. The bounds of the created VoxelGrid are computed from the @@ -294,5 +306,63 @@ class AvgColorVoxel { Eigen::Vector3d color_; }; +/// \class AggColorVoxel +/// +/// \brief Class to aggregate color values from different votes in one voxel +/// Can be used to compute min, max, average and sum voxel color. +class AggColorVoxel { +public: + AggColorVoxel() + : num_of_points_(0), + color_(0.0, 0.0, 0.0), + min_color_(Eigen::Vector3d::Constant( + std::numeric_limits::max())), + max_color_(Eigen::Vector3d::Constant( + std::numeric_limits::lowest())) {} + +public: + void Add(const Eigen::Vector3i &voxel_index) { + if (num_of_points_ > 0 && voxel_index != voxel_index_) { + utility::LogWarning( + "Tried to aggregate ColorVoxel with different " + "voxel_index"); + } + voxel_index_ = voxel_index; + } + + void Add(const Eigen::Vector3i &voxel_index, const Eigen::Vector3d &color) { + Add(voxel_index); + color_ += color; + num_of_points_++; + min_color_ = min_color_.cwiseMin(color); + max_color_ = max_color_.cwiseMax(color); + } + + Eigen::Vector3i GetVoxelIndex() const { return voxel_index_; } + + Eigen::Vector3d GetAverageColor() const { + if (num_of_points_ > 0) { + return color_ / double(num_of_points_); + } else { + return color_; + } + } + + Eigen::Vector3d GetMinColor() const { return min_color_; } + + Eigen::Vector3d GetMaxColor() const { return max_color_; } + + Eigen::Vector3d GetSumColor() const { return color_; } + +public: + int num_of_points_; + Eigen::Vector3i voxel_index_; + Eigen::Vector3d color_; + +private: + Eigen::Vector3d min_color_; + Eigen::Vector3d max_color_; +}; + } // namespace geometry } // namespace open3d diff --git a/cpp/open3d/geometry/VoxelGridFactory.cpp b/cpp/open3d/geometry/VoxelGridFactory.cpp index a083c6524d5..c60169f957c 100644 --- a/cpp/open3d/geometry/VoxelGridFactory.cpp +++ b/cpp/open3d/geometry/VoxelGridFactory.cpp @@ -45,7 +45,8 @@ std::shared_ptr VoxelGrid::CreateFromPointCloudWithinBounds( const PointCloud &input, double voxel_size, const Eigen::Vector3d &min_bound, - const Eigen::Vector3d &max_bound) { + const Eigen::Vector3d &max_bound, + VoxelGrid::VoxelColorMode color_mode) { auto output = std::make_shared(); if (voxel_size <= 0.0) { utility::LogError("voxel_size <= 0."); @@ -57,7 +58,7 @@ std::shared_ptr VoxelGrid::CreateFromPointCloudWithinBounds( } output->voxel_size_ = voxel_size; output->origin_ = min_bound; - std::unordered_map> voxelindex_to_accpoint; Eigen::Vector3d ref_coord; @@ -76,9 +77,15 @@ std::shared_ptr VoxelGrid::CreateFromPointCloudWithinBounds( } for (auto accpoint : voxelindex_to_accpoint) { const Eigen::Vector3i &grid_index = accpoint.second.GetVoxelIndex(); - const Eigen::Vector3d &color = - has_colors ? accpoint.second.GetAverageColor() - : Eigen::Vector3d(0, 0, 0); + // clang-format off + const Eigen::Vector3d &color = has_colors ? + (color_mode == VoxelColorMode::AVG ? accpoint.second.GetAverageColor() + : color_mode == VoxelColorMode::MIN ? accpoint.second.GetMinColor() + : color_mode == VoxelColorMode::MAX ? accpoint.second.GetMaxColor() + : color_mode == VoxelColorMode::SUM ? accpoint.second.GetSumColor() + : Eigen::Vector3d::Zero()) + : Eigen::Vector3d::Zero(); + // clang-format on output->AddVoxel(geometry::Voxel(grid_index, color)); } utility::LogDebug( @@ -88,12 +95,14 @@ std::shared_ptr VoxelGrid::CreateFromPointCloudWithinBounds( } std::shared_ptr VoxelGrid::CreateFromPointCloud( - const PointCloud &input, double voxel_size) { + const PointCloud &input, + double voxel_size, + VoxelGrid::VoxelColorMode color_mode) { Eigen::Vector3d voxel_size3(voxel_size, voxel_size, voxel_size); Eigen::Vector3d min_bound = input.GetMinBound() - voxel_size3 * 0.5; Eigen::Vector3d max_bound = input.GetMaxBound() + voxel_size3 * 0.5; return CreateFromPointCloudWithinBounds(input, voxel_size, min_bound, - max_bound); + max_bound, color_mode); } std::shared_ptr VoxelGrid::CreateFromTriangleMeshWithinBounds( diff --git a/cpp/pybind/geometry/voxelgrid.cpp b/cpp/pybind/geometry/voxelgrid.cpp index 591d8705af6..f74df6afeca 100644 --- a/cpp/pybind/geometry/voxelgrid.cpp +++ b/cpp/pybind/geometry/voxelgrid.cpp @@ -63,6 +63,15 @@ void pybind_voxelgrid_definitions(py::module &m) { static_cast, std::shared_ptr, Geometry3D>>( m.attr("VoxelGrid")); + + py::enum_ color_mode( + voxelgrid, "VoxelColorMode", + "Mode of determining color for each voxel."); + color_mode.value("AVG", VoxelGrid::VoxelColorMode::AVG) + .value("MIN", VoxelGrid::VoxelColorMode::MIN) + .value("MAX", VoxelGrid::VoxelColorMode::MAX) + .value("SUM", VoxelGrid::VoxelColorMode::SUM); + py::detail::bind_default_constructor(voxelgrid); py::detail::bind_copy_functions(voxelgrid); voxelgrid @@ -129,19 +138,23 @@ void pybind_voxelgrid_definitions(py::module &m) { .def_static("create_from_point_cloud", &VoxelGrid::CreateFromPointCloud, "Creates a VoxelGrid from a given PointCloud. The " - "color value of a given voxel is the average color " + "color value of a given voxel is determined by the " + "VoxelColorMode, e.g. by default the average color " "value of the points that fall into it (if the " "PointCloud has colors). The bounds of the created " "VoxelGrid are computed from the PointCloud.", - "input"_a, "voxel_size"_a) + "input"_a, "voxel_size"_a, + "color_mode"_a = VoxelGrid::VoxelColorMode::AVG) .def_static("create_from_point_cloud_within_bounds", &VoxelGrid::CreateFromPointCloudWithinBounds, "Creates a VoxelGrid from a given PointCloud. The " - "color value of a given voxel is the average color " + "color value of a given voxel is determined by the " + "VoxelColorMode, e.g. by default the average color " "value of the points that fall into it (if the " "PointCloud has colors). The bounds of the created " "VoxelGrid are defined by the given parameters.", - "input"_a, "voxel_size"_a, "min_bound"_a, "max_bound"_a) + "input"_a, "voxel_size"_a, "min_bound"_a, "max_bound"_a, + "color_mode"_a = VoxelGrid::VoxelColorMode::AVG) .def_static("create_from_triangle_mesh", &VoxelGrid::CreateFromTriangleMesh, "Creates a VoxelGrid from a given TriangleMesh. No " @@ -162,6 +175,7 @@ void pybind_voxelgrid_definitions(py::module &m) { "origin point.") .def_readwrite("voxel_size", &VoxelGrid::voxel_size_, "``float64`` Size of the voxel."); + docstring::ClassMethodDocInject(m, "VoxelGrid", "has_colors"); docstring::ClassMethodDocInject(m, "VoxelGrid", "has_voxels"); docstring::ClassMethodDocInject(m, "VoxelGrid", "get_voxel", @@ -214,7 +228,8 @@ void pybind_voxelgrid_definitions(py::module &m) { docstring::ClassMethodDocInject( m, "VoxelGrid", "create_from_point_cloud", {{"input", "The input PointCloud"}, - {"voxel_size", "Voxel size of of the VoxelGrid construction."}}); + {"voxel_size", "Voxel size of of the VoxelGrid construction."}, + {"color_mode", "VoxelColorMode for determining voxel color."}}); docstring::ClassMethodDocInject( m, "VoxelGrid", "create_from_point_cloud_within_bounds", {{"input", "The input PointCloud"}, @@ -222,7 +237,8 @@ void pybind_voxelgrid_definitions(py::module &m) { {"min_bound", "Minimum boundary point for the VoxelGrid to create."}, {"max_bound", - "Maximum boundary point for the VoxelGrid to create."}}); + "Maximum boundary point for the VoxelGrid to create."}, + {"color_mode", "VoxelColorMode for determining voxel color."}}); docstring::ClassMethodDocInject( m, "VoxelGrid", "create_from_triangle_mesh", {{"input", "The input TriangleMesh"}, From 652c8286c56e7e41f78afe5af0ca8ee773f95488 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 28 Aug 2024 20:43:40 +0200 Subject: [PATCH 2/7] update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d032cdedbf4..fbcc29244fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ - Split pybind declarations/definitions to avoid C++ types in Python docs (PR #6869) - Fix minimal oriented bounding box of MeshBase derived classes and add new unit tests (PR #6898) - Fix projection of point cloud to Depth/RGBD image if no position attribute is provided (PR #6880) +- Add choice of voxel color mode when creating VoxelGrid from PointCloud ## 0.13 From ae31d31daf0295807674dcbc2139af26e233c049 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 28 Aug 2024 21:21:34 +0200 Subject: [PATCH 3/7] update tutorial for VoxelGrid color_mode change --- docs/jupyter/geometry/voxelization.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/jupyter/geometry/voxelization.ipynb b/docs/jupyter/geometry/voxelization.ipynb index 934e7b7d419..a724a263e90 100644 --- a/docs/jupyter/geometry/voxelization.ipynb +++ b/docs/jupyter/geometry/voxelization.ipynb @@ -64,7 +64,7 @@ "metadata": {}, "source": [ "## From point cloud\n", - "The voxel grid can also be created from a point cloud using the method `create_from_point_cloud`. A voxel is occupied if at least one point of the point cloud is within the voxel. The color of the voxel is the average of all the points within the voxel. The argument `voxel_size` defines the resolution of the voxel grid." + "The voxel grid can also be created from a point cloud using the method `create_from_point_cloud`. A voxel is occupied if at least one point of the point cloud is within the voxel. The argument `voxel_size` defines the resolution of the voxel grid. By default, the color of the voxel is the average of all the points within the voxel. The argument `color_mode` can be changed to determine the color by average, min, max or sum value of the points, e.g. with `o3d.geometry.VoxelGrid.VoxelColorMode.MIN`." ] }, { From 9f4b930839f92ddcd94165246a140622e6806088 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 28 Aug 2024 21:57:20 +0200 Subject: [PATCH 4/7] update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbcc29244fe..5c85076a423 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,7 +43,7 @@ - Split pybind declarations/definitions to avoid C++ types in Python docs (PR #6869) - Fix minimal oriented bounding box of MeshBase derived classes and add new unit tests (PR #6898) - Fix projection of point cloud to Depth/RGBD image if no position attribute is provided (PR #6880) -- Add choice of voxel color mode when creating VoxelGrid from PointCloud +- Add choice of voxel color mode when creating VoxelGrid from PointCloud (PR #6937) ## 0.13 From 41fe6b206fbfc87e8af534782db972be119902a4 Mon Sep 17 00:00:00 2001 From: Benjamin Ummenhofer Date: Thu, 19 Dec 2024 03:22:53 -0800 Subject: [PATCH 5/7] rename VoxelColorMode to VoxelPoolingMode --- cpp/open3d/geometry/VoxelGrid.h | 12 ++++++------ cpp/open3d/geometry/VoxelGridFactory.cpp | 14 +++++++------- cpp/pybind/geometry/voxelgrid.cpp | 24 ++++++++++++------------ docs/jupyter/geometry/voxelization.ipynb | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cpp/open3d/geometry/VoxelGrid.h b/cpp/open3d/geometry/VoxelGrid.h index fe32c20b381..258e975a12d 100644 --- a/cpp/open3d/geometry/VoxelGrid.h +++ b/cpp/open3d/geometry/VoxelGrid.h @@ -189,13 +189,13 @@ class VoxelGrid : public Geometry3D { double height, double depth); - /// \enum VoxelColorMode + /// \enum VoxelPoolingMode /// /// \brief Possible ways of determining voxel color from PointCloud. - enum class VoxelColorMode { AVG, MIN, MAX, SUM }; + enum class VoxelPoolingMode { AVG, MIN, MAX, SUM }; /// Creates a VoxelGrid from a given PointCloud. The color value of a given - /// voxel is determined by the VoxelColorMode, e.g. by default the average + /// voxel is determined by the VoxelPoolingMode, e.g. by default the average /// color value of the points that fall into it (if the /// PointCloud has colors). /// The bounds of the created VoxelGrid are computed from the PointCloud. @@ -206,10 +206,10 @@ class VoxelGrid : public Geometry3D { static std::shared_ptr CreateFromPointCloud( const PointCloud &input, double voxel_size, - VoxelColorMode color_mode = VoxelColorMode::AVG); + VoxelPoolingMode color_mode = VoxelPoolingMode::AVG); /// Creates a VoxelGrid from a given PointCloud. The color value of a given - /// voxel is determined by the VoxelColorMode, e.g. by default the average + /// voxel is determined by the VoxelPoolingMode, e.g. by default the average /// color value of the points that fall into it (if the /// PointCloud has colors). /// The bounds of the created VoxelGrid are defined by the given parameters. @@ -224,7 +224,7 @@ class VoxelGrid : public Geometry3D { double voxel_size, const Eigen::Vector3d &min_bound, const Eigen::Vector3d &max_bound, - VoxelColorMode color_mode = VoxelColorMode::AVG); + VoxelPoolingMode color_mode = VoxelPoolingMode::AVG); /// Creates a VoxelGrid from a given TriangleMesh. No color information is /// converted. The bounds of the created VoxelGrid are computed from the diff --git a/cpp/open3d/geometry/VoxelGridFactory.cpp b/cpp/open3d/geometry/VoxelGridFactory.cpp index 6a3e92eeed9..39fe03668ed 100644 --- a/cpp/open3d/geometry/VoxelGridFactory.cpp +++ b/cpp/open3d/geometry/VoxelGridFactory.cpp @@ -46,7 +46,7 @@ std::shared_ptr VoxelGrid::CreateFromPointCloudWithinBounds( double voxel_size, const Eigen::Vector3d &min_bound, const Eigen::Vector3d &max_bound, - VoxelGrid::VoxelColorMode color_mode) { + VoxelGrid::VoxelPoolingMode pooling_mode) { auto output = std::make_shared(); if (voxel_size <= 0.0) { utility::LogError("voxel_size <= 0."); @@ -79,10 +79,10 @@ std::shared_ptr VoxelGrid::CreateFromPointCloudWithinBounds( const Eigen::Vector3i &grid_index = accpoint.second.GetVoxelIndex(); // clang-format off const Eigen::Vector3d &color = has_colors ? - (color_mode == VoxelColorMode::AVG ? accpoint.second.GetAverageColor() - : color_mode == VoxelColorMode::MIN ? accpoint.second.GetMinColor() - : color_mode == VoxelColorMode::MAX ? accpoint.second.GetMaxColor() - : color_mode == VoxelColorMode::SUM ? accpoint.second.GetSumColor() + (pooling_mode == VoxelPoolingMode::AVG ? accpoint.second.GetAverageColor() + : pooling_mode == VoxelPoolingMode::MIN ? accpoint.second.GetMinColor() + : pooling_mode == VoxelPoolingMode::MAX ? accpoint.second.GetMaxColor() + : pooling_mode == VoxelPoolingMode::SUM ? accpoint.second.GetSumColor() : Eigen::Vector3d::Zero()) : Eigen::Vector3d::Zero(); // clang-format on @@ -97,12 +97,12 @@ std::shared_ptr VoxelGrid::CreateFromPointCloudWithinBounds( std::shared_ptr VoxelGrid::CreateFromPointCloud( const PointCloud &input, double voxel_size, - VoxelGrid::VoxelColorMode color_mode) { + VoxelGrid::VoxelPoolingMode pooling_mode) { Eigen::Vector3d voxel_size3(voxel_size, voxel_size, voxel_size); Eigen::Vector3d min_bound = input.GetMinBound() - voxel_size3 * 0.5; Eigen::Vector3d max_bound = input.GetMaxBound() + voxel_size3 * 0.5; return CreateFromPointCloudWithinBounds(input, voxel_size, min_bound, - max_bound, color_mode); + max_bound, pooling_mode); } std::shared_ptr VoxelGrid::CreateFromTriangleMeshWithinBounds( diff --git a/cpp/pybind/geometry/voxelgrid.cpp b/cpp/pybind/geometry/voxelgrid.cpp index 498210caca2..6bcc6b7264d 100644 --- a/cpp/pybind/geometry/voxelgrid.cpp +++ b/cpp/pybind/geometry/voxelgrid.cpp @@ -64,13 +64,13 @@ void pybind_voxelgrid_definitions(py::module &m) { std::shared_ptr, Geometry3D>>( m.attr("VoxelGrid")); - py::enum_ color_mode( - voxelgrid, "VoxelColorMode", + py::enum_ pooling_mode( + voxelgrid, "VoxelPoolingMode", "Mode of determining color for each voxel."); - color_mode.value("AVG", VoxelGrid::VoxelColorMode::AVG) - .value("MIN", VoxelGrid::VoxelColorMode::MIN) - .value("MAX", VoxelGrid::VoxelColorMode::MAX) - .value("SUM", VoxelGrid::VoxelColorMode::SUM); + pooling_mode.value("AVG", VoxelGrid::VoxelPoolingMode::AVG) + .value("MIN", VoxelGrid::VoxelPoolingMode::MIN) + .value("MAX", VoxelGrid::VoxelPoolingMode::MAX) + .value("SUM", VoxelGrid::VoxelPoolingMode::SUM); py::detail::bind_default_constructor(voxelgrid); py::detail::bind_copy_functions(voxelgrid); @@ -139,22 +139,22 @@ void pybind_voxelgrid_definitions(py::module &m) { &VoxelGrid::CreateFromPointCloud, "Creates a VoxelGrid from a given PointCloud. The " "color value of a given voxel is determined by the " - "VoxelColorMode, e.g. by default the average color " + "VoxelPoolingMode, e.g. by default the average color " "value of the points that fall into it (if the " "PointCloud has colors). The bounds of the created " "VoxelGrid are computed from the PointCloud.", "input"_a, "voxel_size"_a, - "color_mode"_a = VoxelGrid::VoxelColorMode::AVG) + "pooling_mode"_a = VoxelGrid::VoxelPoolingMode::AVG) .def_static("create_from_point_cloud_within_bounds", &VoxelGrid::CreateFromPointCloudWithinBounds, "Creates a VoxelGrid from a given PointCloud. The " "color value of a given voxel is determined by the " - "VoxelColorMode, e.g. by default the average color " + "VoxelPoolingMode, e.g. by default the average color " "value of the points that fall into it (if the " "PointCloud has colors). The bounds of the created " "VoxelGrid are defined by the given parameters.", "input"_a, "voxel_size"_a, "min_bound"_a, "max_bound"_a, - "color_mode"_a = VoxelGrid::VoxelColorMode::AVG) + "pooling_mode"_a = VoxelGrid::VoxelPoolingMode::AVG) .def_static("create_from_triangle_mesh", &VoxelGrid::CreateFromTriangleMesh, "Creates a VoxelGrid from a given TriangleMesh. No " @@ -229,7 +229,7 @@ void pybind_voxelgrid_definitions(py::module &m) { m, "VoxelGrid", "create_from_point_cloud", {{"input", "The input PointCloud"}, {"voxel_size", "Voxel size of of the VoxelGrid construction."}, - {"color_mode", "VoxelColorMode for determining voxel color."}}); + {"pooling_mode", "VoxelPoolingMode for determining voxel color."}}); docstring::ClassMethodDocInject( m, "VoxelGrid", "create_from_point_cloud_within_bounds", {{"input", "The input PointCloud"}, @@ -238,7 +238,7 @@ void pybind_voxelgrid_definitions(py::module &m) { "Minimum boundary point for the VoxelGrid to create."}, {"max_bound", "Maximum boundary point for the VoxelGrid to create."}, - {"color_mode", "VoxelColorMode for determining voxel color."}}); + {"pooling_mode", "VoxelPoolingMode that determines how to compute the voxel color."}}); docstring::ClassMethodDocInject( m, "VoxelGrid", "create_from_triangle_mesh", {{"input", "The input TriangleMesh"}, diff --git a/docs/jupyter/geometry/voxelization.ipynb b/docs/jupyter/geometry/voxelization.ipynb index a724a263e90..e7b98a64f7c 100644 --- a/docs/jupyter/geometry/voxelization.ipynb +++ b/docs/jupyter/geometry/voxelization.ipynb @@ -64,7 +64,7 @@ "metadata": {}, "source": [ "## From point cloud\n", - "The voxel grid can also be created from a point cloud using the method `create_from_point_cloud`. A voxel is occupied if at least one point of the point cloud is within the voxel. The argument `voxel_size` defines the resolution of the voxel grid. By default, the color of the voxel is the average of all the points within the voxel. The argument `color_mode` can be changed to determine the color by average, min, max or sum value of the points, e.g. with `o3d.geometry.VoxelGrid.VoxelColorMode.MIN`." + "The voxel grid can also be created from a point cloud using the method `create_from_point_cloud`. A voxel is occupied if at least one point of the point cloud is within the voxel. The argument `voxel_size` defines the resolution of the voxel grid. By default, the color of the voxel is the average of all the points within the voxel. The argument `pooling_mode` can be changed to determine the color by average, min, max or sum value of the points, e.g. with `o3d.geometry.VoxelGrid.VoxelPoolingMode.MIN`." ] }, { From 786b11be808ce82eae40575a0067cbac90a49b5a Mon Sep 17 00:00:00 2001 From: Benjamin Ummenhofer Date: Thu, 19 Dec 2024 03:36:17 -0800 Subject: [PATCH 6/7] update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2712029b3ab..ad1f4f43b17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,7 @@ - Split pybind declarations/definitions to avoid C++ types in Python docs (PR #6869) - Fix minimal oriented bounding box of MeshBase derived classes and add new unit tests (PR #6898) - Fix projection of point cloud to Depth/RGBD image if no position attribute is provided (PR #6880) -- Add choice of voxel color mode when creating VoxelGrid from PointCloud (PR #6937) +- Add choice of voxel pooling mode when creating VoxelGrid from PointCloud (PR #6937) - Support lowercase types when reading PCD files (PR #6930) - Fix visualization/draw ICP example and add warnings (PR #6933) - Unified cloud initializer pipeline for ICP (fixes segfault colored ICP) (PR #6942) From d3a4e3909378886c6a8d9af975d9a454641ad723 Mon Sep 17 00:00:00 2001 From: Benjamin Ummenhofer Date: Thu, 19 Dec 2024 04:54:43 -0800 Subject: [PATCH 7/7] apply style --- cpp/pybind/geometry/voxelgrid.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/pybind/geometry/voxelgrid.cpp b/cpp/pybind/geometry/voxelgrid.cpp index 6bcc6b7264d..92edd621fa6 100644 --- a/cpp/pybind/geometry/voxelgrid.cpp +++ b/cpp/pybind/geometry/voxelgrid.cpp @@ -229,7 +229,8 @@ void pybind_voxelgrid_definitions(py::module &m) { m, "VoxelGrid", "create_from_point_cloud", {{"input", "The input PointCloud"}, {"voxel_size", "Voxel size of of the VoxelGrid construction."}, - {"pooling_mode", "VoxelPoolingMode for determining voxel color."}}); + {"pooling_mode", + "VoxelPoolingMode for determining voxel color."}}); docstring::ClassMethodDocInject( m, "VoxelGrid", "create_from_point_cloud_within_bounds", {{"input", "The input PointCloud"}, @@ -238,7 +239,9 @@ void pybind_voxelgrid_definitions(py::module &m) { "Minimum boundary point for the VoxelGrid to create."}, {"max_bound", "Maximum boundary point for the VoxelGrid to create."}, - {"pooling_mode", "VoxelPoolingMode that determines how to compute the voxel color."}}); + {"pooling_mode", + "VoxelPoolingMode that determines how to compute the voxel " + "color."}}); docstring::ClassMethodDocInject( m, "VoxelGrid", "create_from_triangle_mesh", {{"input", "The input TriangleMesh"},