Skip to content

Commit

Permalink
Enable auto conversion from Python list / tuple by using deque.
Browse files Browse the repository at this point in the history
Add __repr__
  • Loading branch information
ssheorey committed Nov 19, 2024
1 parent 9f60d3d commit 3d0cf90
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 16 deletions.
7 changes: 7 additions & 0 deletions cpp/open3d/t/geometry/Geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#pragma once

#include <fmt/format.h>

#include <string>

#include "open3d/core/Device.h"
Expand Down Expand Up @@ -106,6 +108,11 @@ struct MetricParameters {
/// distance computation. This specifies the number of points sampled. No
/// sampling is done for point clouds.
size_t n_sampled_points = 1000;
std::string ToString() const {
return fmt::format(
"MetricParameters: fscore_radius={}, n_sampled_points={}",
fscore_radius, n_sampled_points);
}
};

} // namespace geometry
Expand Down
34 changes: 26 additions & 8 deletions cpp/pybind/t/geometry/geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

#include "open3d/t/geometry/Geometry.h"

#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>

#include <deque>
#include <vector>

#include "pybind/docstring.h"
Expand Down Expand Up @@ -56,7 +58,6 @@ void pybind_geometry_declarations(py::module& m) {
"Hausdorff Distance")
.value("FScore", Metric::FScore, "F-Score")
.export_values();
py::bind_vector<std::vector<Metric>>(m_geometry, "VectorMetric");
py::class_<MetricParameters> metric_parameters(
m_geometry, "MetricParameters",
"Holder for various parameters required by metrics.");
Expand All @@ -75,23 +76,40 @@ void pybind_geometry_declarations(py::module& m) {

void pybind_geometry_definitions(py::module& m) {
auto m_geometry = static_cast<py::module>(m.attr("geometry"));
py::bind_vector<std::vector<Metric>>(m_geometry, "VectorMetric");

auto metric_parameters = static_cast<py::class_<MetricParameters>>(
m_geometry.attr("MetricParameters"));
// Use std::deque instead of std::vector to enable automatic Python list /
// tuple conversion. FIXME: Ideally this should work for std::vector.
metric_parameters
.def(py::init<const std::vector<float>&, size_t>(),
"fscore_radius"_a = std::vector<float>{0.01},
.def(py::init([](const std::deque<float>& fsr, size_t nsp) {
std::vector<float> fsrvec{fsr.begin(), fsr.end()};
return MetricParameters{fsrvec, nsp};
}),
"fscore_radius"_a = std::deque<float>{0.01f},
"n_sampled_points"_a = 1000)
.def_readwrite("fscore_radius", &MetricParameters::fscore_radius,
"Radius for computing the F-Score. A match between "
"a point and its nearest neighbor is sucessful if "
"it is within this radius.")
.def_property(
"fscore_radius",
[](const MetricParameters& self) { // getter
return std::deque<float>(self.fscore_radius.begin(),
self.fscore_radius.end());
},
[](MetricParameters& self,
const std::deque<float>& fsr) { // setter
self.fscore_radius =
std::vector<float>(fsr.begin(), fsr.end());
},
"Radius for computing the F-Score. A match between "
"a point and its nearest neighbor is sucessful if "
"it is within this radius.")
.def_readwrite("n_sampled_points",
&MetricParameters::n_sampled_points,
"Points are sampled uniformly from the surface of "
"triangle meshes before distance computation. This "
"specifies the number of points sampled. No "
"sampling is done for point clouds.");
"sampling is done for point clouds.")
.def("__repr__", &MetricParameters::ToString);

pybind_geometry_class_definitions(m_geometry);
pybind_drawable_geometry_class_definitions(m_geometry);
Expand Down
1 change: 0 additions & 1 deletion cpp/pybind/utility/eigen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ namespace utility {

void pybind_eigen_declarations(py::module &m) {
auto intvector = pybind_eigen_vector_of_scalar<int>(m, "IntVector");
auto floatvector = pybind_eigen_vector_of_scalar<float>(m, "FloatVector");
auto doublevector =
pybind_eigen_vector_of_scalar<double>(m, "DoubleVector");
auto vector3dvector = pybind_eigen_vector_of_vector<Eigen::Vector3d>(
Expand Down
4 changes: 1 addition & 3 deletions python/test/t/geometry/test_pointcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,11 @@ def test_metrics():

# (1, 3, 3, 1) vertices are shifted by (0, 0.1, 0.1*sqrt(2), 0.1*sqrt(3))
# respectively
metric_params = MetricParameters(
fscore_radius=o3d.utility.FloatVector((0.01, 0.11, 0.15, 0.18)))
metric_params = MetricParameters(fscore_radius=(0.01, 0.11, 0.15, 0.18))
metrics = pcd1.compute_metrics(
pcd2, (Metric.ChamferDistance, Metric.HausdorffDistance, Metric.FScore),
metric_params)

print(metrics)
np.testing.assert_allclose(
metrics.cpu().numpy(),
(0.22436734, np.sqrt(3) / 10, 100. / 8, 400. / 8, 700. / 8, 100.),
Expand Down
5 changes: 1 addition & 4 deletions python/test/t/geometry/test_trianglemesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -1404,14 +1404,11 @@ def test_metrics():

# 3 faces of the cube are the same, and 3 are shifted up by 0.1 - raycast
# distances should follow this.
metric_params = MetricParameters(fscore_radius=o3d.utility.FloatVector(
(0.05, 0.15)),
metric_params = MetricParameters(fscore_radius=(0.05, 0.15),
n_sampled_points=100000)
# n_sampled_points=100000)
metrics = box1.compute_metrics(
box2, (Metric.ChamferDistance, Metric.HausdorffDistance, Metric.FScore),
metric_params)

print(metrics)
np.testing.assert_allclose(metrics.cpu().numpy(), (0.1, 0.17, 50, 100),
rtol=0.05)

0 comments on commit 3d0cf90

Please sign in to comment.