11 #include <libqhullcpp/PointCoordinates.h>
12 #include <libqhullcpp/Qhull.h>
13 #include <libqhullcpp/QhullFacet.h>
14 #include <libqhullcpp/QhullFacetList.h>
15 #include <libqhullcpp/QhullVertexSet.h>
21 #include <unordered_map>
64 if (map_keys_to_tensors.count(
"positions") == 0) {
67 device_ = map_keys_to_tensors.at(
"positions").GetDevice();
69 {utility::nullopt, 3});
71 map_keys_to_tensors.end());
75 size_t num_points = 0;
76 std::string points_dtype_str =
"";
83 fmt::format(
"PointCloud on {} [{} points{}].\nAttributes:",
88 return str +
" None.";
90 if (keyval.first !=
"positions") {
91 str +=
fmt::format(
" {} (dtype = {}, shape = {}),", keyval.first,
92 keyval.second.GetDtype().ToString(),
93 keyval.second.GetShape().ToString());
96 str[str.size() - 1] =
'.';
137 auto other_attr_shape = other_attr.GetShape();
138 auto attr_shape = kv.second.GetShape();
139 int64_t combined_length = other_attr_shape[0] + attr_shape[0];
140 other_attr_shape[0] = combined_length;
141 attr_shape[0] = combined_length;
142 if (other_attr_shape != attr_shape) {
144 "Shape mismatch. Attribute {}, shape {}, is not "
145 "compatible with {}.",
146 kv.first, other_attr.GetShape(), kv.second.GetShape());
151 kv.second.GetDevice());
162 "The pointcloud is missing attribute {}. The pointcloud "
163 "being appended, must have all the attributes present in "
164 "the pointcloud it is being appended to.",
220 bool invert )
const {
230 indices_local = boolean_mask;
236 pcd.
SetPointAttr(kv.first, kv.second.IndexGet({indices_local}));
248 bool remove_duplicates )
const {
255 if (!remove_duplicates && !invert) {
263 "Pointcloud down sampled from {} points to {} points.",
length,
272 core::Tensor::Init<bool>(
true,
GetDevice()));
281 const std::string &reduction)
const {
282 if (voxel_size <= 0) {
285 if (reduction !=
"mean") {
298 voxeli_hashset.
Insert(voxeli, index_map_point2voxel, masks);
305 voxeli_hashset.
Find(voxeli, index_map_point2voxel, masks);
306 index_map_point2voxel = index_map_point2voxel.
To(
core::Int64);
309 int64_t num_voxels = voxeli_hashset.
Size();
312 auto voxel_num_points =
315 0, index_map_point2voxel,
321 auto point_attr = kv.second;
323 std::string attr_string = kv.first;
324 auto attr_dtype = point_attr.GetDtype();
328 attr_shape[0] = num_voxels;
331 if (reduction ==
"mean") {
332 voxel_attr.IndexAdd_(0, index_map_point2voxel,
334 voxel_attr /= voxel_num_points.View({-1, 1});
335 voxel_attr = voxel_attr.To(attr_dtype);
346 if (every_k_points == 0) {
348 "Illegal sample rate, every_k_points must be larger than 0.");
357 kv.second.Slice(0, 0,
length, (int64_t)every_k_points));
364 if (sampling_ratio < 0 || sampling_ratio > 1) {
366 "Illegal sampling_ratio {}, sampling_ratio must be between 0 "
371 std::vector<int64_t> indices(
length);
372 std::iota(std::begin(indices), std::end(indices), 0);
375 std::shuffle(indices.begin(), indices.end(),
379 const int sample_size = sampling_ratio *
length;
380 indices.resize(sample_size);
389 const size_t start_index)
const {
392 if (num_samples == 0) {
394 }
else if (num_samples ==
size_t(num_points)) {
396 }
else if (num_samples >
size_t(num_points)) {
398 "Illegal number of samples: {}, must <= point size: {}",
399 num_samples, num_points);
400 }
else if (start_index >=
size_t(num_points)) {
402 start_index, num_points);
410 int64_t farthest_index =
static_cast<int64_t
>(start_index);
412 for (
size_t i = 0; i < num_samples; i++) {
413 selection_mask[farthest_index] =
true;
417 core::Tensor distances_to_selected = (diff * diff).Sum({1});
421 farthest_index = smallest_distances.ArgMax({0}).Item<int64_t>();
427 size_t nb_points,
double search_radius)
const {
428 if (nb_points < 1 || search_radius <= 0) {
430 "Illegal input parameters, number of points and radius must be "
450 num_neighbors.
Ge(
static_cast<int64_t
>(nb_points));
455 size_t nb_neighbors,
double std_ratio)
const {
456 if (nb_neighbors < 1 || std_ratio <= 0) {
458 "Illegal input parameters, the number of neighbors and "
459 "standard deviation ratio must be positive.");
473 std::tie(indices, distance2) =
477 const double cloud_mean =
479 const core::Tensor std_distances_centered = avg_distances - cloud_mean;
480 const double sq_sum = (std_distances_centered * std_distances_centered)
485 std::sqrt(sq_sum / (avg_distances.
GetShape()[0] - 1));
486 const double distance_threshold = cloud_mean + std_ratio *
std_dev;
493 bool remove_nan,
bool remove_inf)
const {
496 if (remove_nan && remove_inf) {
497 finite_indices_mask =
499 }
else if (remove_nan) {
500 finite_indices_mask =
502 }
else if (remove_inf) {
503 finite_indices_mask =
512 return std::make_tuple(
SelectByMask(finite_indices_mask),
513 finite_indices_mask);
526 "Unsupported point position data-type. Only support "
527 "Int32, Int64, Float32 and Float64.");
533 points_voxeli_hashset.
Insert(points_voxeli, buf_indices, masks);
563 clipped_color = clipped_color.Clip(0.0f, 1.0f);
568 pcd_colors.
AsRvalue() = clipped_color;
575 double radius,
int max_nn,
double angle_threshold)
const {
580 "PointCloud must have normals attribute to compute boundary "
598 std::tie(indices, distance2, counts) =
601 "Use HybridSearch [max_nn: {} | radius {}] for computing "
608 points_d, normals_d, indices, counts, mask, angle_threshold);
610 CUDA_CALL(kernel::pointcloud::ComputeBoundaryPointsCUDA, points_d,
611 normals_d, indices, counts, mask, angle_threshold);
655 EstimateCovariancesUsingHybridSearchCUDA,
670 CUDA_CALL(kernel::pointcloud::EstimateCovariancesUsingKNNSearchCUDA,
685 EstimateCovariancesUsingRadiusSearchCUDA,
701 CUDA_CALL(kernel::pointcloud::EstimateNormalsFromCovariancesCUDA,
720 "No normals in the PointCloud. Call EstimateNormals() first.");
733 CUDA_CALL(kernel::pointcloud::OrientNormalsToAlignWithDirectionCUDA,
747 "No normals in the PointCloud. Call EstimateNormals() first.");
759 CUDA_CALL(kernel::pointcloud::OrientNormalsTowardsCameraLocationCUDA,
768 const double lambda ,
769 const double cos_alpha_tol ) {
776 "OrientNormalsConsistentTangentPlane: normals are missing; "
777 "call EstimateNormals() first.");
786 "PointCloud must have colors and normals attribute "
787 "to compute color gradients.");
801 if (this->
GetPointAttr(
"color_gradients").GetDtype() != dtype) {
803 "color_gradients attribute must be of same dtype as "
822 EstimateColorGradientsUsingHybridSearchCUDA,
841 EstimateColorGradientsUsingKNNSearchCUDA,
859 EstimateColorGradientsUsingRadiusSearchCUDA,
873 const Image &depth_in,
874 const Image &color_in,
883 const float invalid_fill = NAN;
885 const int bilateral_kernel_size =
886 depth_in.
IsCUDA() ? 3 : 5;
887 const float depth_diff_threshold = 0.14f;
888 const float bilateral_value_sigma = 10.f;
889 const float bilateral_distance_sigma = 10.f;
892 "Only powers of 2 are supported for stride when "
893 "with_normals=true.");
900 depth_in.
ClipTransform(depth_scale, 0.01f, depth_max, invalid_fill);
901 auto color = color_in;
902 auto intrinsics = intrinsics_in /
stride;
903 intrinsics[-1][-1] = 1.f;
905 depth = depth.FilterBilateral(bilateral_kernel_size,
906 bilateral_value_sigma,
907 bilateral_distance_sigma);
910 depth = depth.PyrDownDepth(depth_diff_threshold, invalid_fill);
914 const int64_t im_size = depth.GetRows() * depth.GetCols();
915 auto vertex_map = depth.CreateVertexMap(intrinsics, invalid_fill);
916 auto vertex_list = vertex_map.AsTensor().View({im_size, 3});
919 auto cam_to_world = extrinsics.
Inverse();
920 vertex_list = vertex_list
921 .
Matmul(cam_to_world.Slice(0, 0, 3, 1)
924 .
Add_(cam_to_world.Slice(0, 0, 3, 1)
927 vertex_map =
Image(vertex_list.View(vertex_map.AsTensor().GetShape())
930 auto normal_map_t = vertex_map.CreateNormalMap(invalid_fill)
935 normal_map_t.Slice(1, 0, 1, 1)
937 .LogicalAnd(vertex_list.Slice(1, 0, 1, 1).IsFinite())
941 vertex_list.GetItem({TensorKey::IndexTensor(valid_idx),
942 TensorKey::Slice(None, None, None)})},
944 normal_map_t.GetItem({TensorKey::IndexTensor(valid_idx),
945 TensorKey::Slice(None, None, None)})}});
946 if (
color.GetRows() > 0) {
950 .GetItem({TensorKey::IndexTensor(valid_idx),
951 TensorKey::Slice(None, None, None)}));
974 extrinsics_host, depth_scale,
980 extrinsics_host, depth_scale, depth_max,
994 {core::UInt16, core::Float32});
1002 intrinsics, extrinsics, depth_scale,
1008 intrinsics, extrinsics, depth_scale, depth_max,
stride);
1021 "Called ProjectToDepthImage on a point cloud with no Positions "
1022 "attribute. Returning empty image.");
1032 depth_scale, depth_max);
1045 "Called ProjectToRGBDImage on a point cloud with no Positions "
1046 "attribute. Returning empty image.");
1051 "Unable to project to RGBD without the Color attribute in the "
1069 intrinsics, extrinsics, depth_scale, depth_max);
1118 bool dtype_is_supported_for_conversion =
true;
1119 double normalization_factor = 1.0;
1123 normalization_factor =
1127 normalization_factor =
1133 "Dtype {} of color attribute is not supported for "
1134 "conversion to LegacyPointCloud and will be skipped. "
1135 "Supported dtypes include UInt8, UIn16, Float32, and "
1138 dtype_is_supported_for_conversion =
false;
1141 if (dtype_is_supported_for_conversion) {
1142 if (normalization_factor != 1.0) {
1145 normalization_factor;
1162 const core::Tensor &camera_location,
double radius)
const {
1168 std::vector<int64_t> indices(n);
1169 std::iota(indices.begin(), indices.end(), 0);
1176 bool print_progress)
const {
1179 (void)print_progress;
1182 std::vector<int32_t> labels(
static_cast<size_t>(n), -1);
1187 const double distance_threshold,
1189 const int num_iterations,
1190 const double probability)
const {
1191 (void)distance_threshold;
1193 (void)num_iterations;
1198 return std::make_tuple(plane, inliers);
1203 static_assert(std::is_same<realT, double>::value,
1204 "Qhull realT is not double. Update code!");
1205 using int_t = int32_t;
1210 orgQhull::Qhull qhull;
1211 std::string options =
"Qt";
1212 if (joggle_inputs) {
1215 qhull.runQhull(
"", 3, coordinates.
GetLength(),
1216 coordinates.
GetDataPtr<
double>(), options.c_str());
1217 orgQhull::QhullFacetList facets = qhull.facetList();
1220 triangles({qhull.facetCount(), 3}, int_dtype),
1221 point_indices({qhull.vertexCount()}, int_dtype);
1222 std::unordered_map<int_t, int_t> vertex_map;
1223 int_t tidx = 0, next_vtx = 0;
1224 auto p_vertices = vertices.
GetDataPtr<
double>();
1225 auto p_triangle = triangles.GetDataPtr<int_t>();
1226 auto p_point_indices = point_indices.GetDataPtr<int_t>();
1227 for (orgQhull::QhullFacetList::iterator it = facets.begin();
1228 it != facets.end(); ++it) {
1229 if (!(*it).isGood())
continue;
1231 orgQhull::QhullVertexSet vSet = it->vertices();
1232 int_t triangle_subscript = 0;
1233 for (orgQhull::QhullVertexSet::iterator vIt = vSet.begin();
1234 vIt != vSet.end(); ++vIt, ++triangle_subscript) {
1235 orgQhull::QhullPoint p = (*vIt).point();
1236 int_t vidx = p.id();
1238 auto inserted = vertex_map.insert({vidx, next_vtx});
1239 if (inserted.second) {
1240 p_triangle[triangle_subscript] = next_vtx;
1241 double *coords = p.coordinates();
1242 std::copy(coords, coords + 3, p_vertices);
1244 p_point_indices[next_vtx++] = vidx;
1246 p_triangle[triangle_subscript] =
1247 inserted.first->second;
1250 if ((*it).isTopOrient()) {
1251 std::swap(p_triangle[0], p_triangle[1]);
1256 if (tidx < triangles.GetShape(0)) {
1257 triangles = triangles.Slice(0, 0, tidx);
1259 if (next_vtx != vertices.GetShape(0)) {
1261 "Qhull output has incorrect number of vertices {} instead of "
1263 next_vtx, vertices.GetShape(0));
1283 bool capping)
const {
1284 using namespace vtkutils;
1291 bool capping)
const {
1292 using namespace vtkutils;
1297 bool invert)
const {
1301 "Bounding box is empty. Returning empty point cloud if "
1302 "invert is false, or the original point cloud if "
1314 "Bounding box is empty. Returning empty point cloud if "
1315 "invert is false, or the original point cloud if "
1326 std::tie(num_partitions, partition_ids) =
1329 return num_partitions;
1333 std::vector<Metric> metrics,
1340 "ComputeDistance is implemented only on CPU. Computing on "
1358 std::tie(indices12, sqr_distance12) = tree2.
KnnSearch(points1, 1);
1359 std::tie(indices21, sqr_distance21) = tree1.
KnnSearch(points2, 1);
1368 if (!have_all_attrs) {
1389 auto degp1 =
static_cast<int>(sqrt(Nc + 1));
1390 if (degp1 * degp1 != Nc + 1) {
1392 "f_rest has incomplete Spherical Harmonics coefficients "
1393 "({}), expected 0, 3, 8 or 15.",
#define CUDA_CALL(cuda_function,...)
filament::Texture::InternalFormat format
cmdLineReadable * params[]
#define AssertTensorDevice(tensor,...)
#define AssertTensorDtype(tensor,...)
#define AssertTensorDtypes(tensor,...)
#define AssertTensorShape(tensor,...)
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
std::vector< Eigen::Vector3d > getEigenColors() const
void addEigenNorms(const std::vector< Eigen::Vector3d > &normals)
bool hasNormals() const override
Returns whether normals are enabled or not.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
bool hasColors() const override
Returns whether colors are enabled or not.
void addEigenColors(const std::vector< Eigen::Vector3d > &colors)
bool reserveThePointsTable(unsigned _numberOfPoints)
Reserves memory to store the points coordinates.
std::vector< Eigen::Vector3d > getEigenNormals() const
virtual bool hasPoints() const
std::vector< Eigen::Vector3d > getEigenPoints() const
void addPoints(const std::vector< CCVector3 > &points)
std::string ToString() const
static const Dtype Float32
std::pair< Tensor, Tensor > Find(const Tensor &input_keys)
int64_t Size() const
Get the size (number of active entries) of the hash set.
std::pair< Tensor, Tensor > Insert(const Tensor &input_keys)
TensorKey is used to represent single index, slice or advanced indexing on a Tensor.
static TensorKey IndexTensor(const Tensor &index_tensor)
static TensorKey Slice(utility::optional< int64_t > start, utility::optional< int64_t > stop, utility::optional< int64_t > step)
bool AllClose(const Tensor &other, double rtol=1e-5, double atol=1e-8) const
Tensor Sqrt() const
Element-wise square root of a tensor, returns a new tensor.
Tensor Contiguous() const
Tensor Matmul(const Tensor &rhs) const
Tensor Ge(const Tensor &value) const
int64_t GetLength() const
void IndexAdd_(int64_t dim, const Tensor &index, const Tensor &src)
Advanced in-place reduction by index.
Tensor LogicalNot() const
Tensor Sub_(const Tensor &value)
Tensor SetItem(const Tensor &value)
Set all items. Equivalent to tensor[:] = value in Python.
Tensor Max(const SizeVector &dims, bool keepdim=false) const
Tensor Mul_(const Tensor &value)
Tensor All(const utility::optional< SizeVector > &dims=utility::nullopt, bool keepdim=false) const
Tensor Le(const Tensor &value) const
static Tensor Zeros(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor fill with zeros.
Tensor Sqrt_()
Element-wise square root of a tensor, in-place.
Tensor Add_(const Tensor &value)
Device GetDevice() const override
Tensor ReinterpretCast(const core::Dtype &dtype) const
Tensor Min(const SizeVector &dims, bool keepdim=false) const
Tensor Clone() const
Copy Tensor to the same device.
Tensor Mean(const SizeVector &dims, bool keepdim=false) const
static Tensor Empty(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor with uninitialized values.
static Tensor Ones(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor fill with ones.
SizeVector GetShape() const
Tensor Slice(int64_t dim, int64_t start, int64_t stop, int64_t step=1) const
Tensor To(Dtype dtype, bool copy=false) const
Tensor Floor() const
Element-wise floor value of a tensor, returning a new tensor.
static Tensor Full(const SizeVector &shape, T fill_value, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor fill with specified value.
A Class for nearest neighbor search.
std::tuple< Tensor, Tensor, Tensor > FixedRadiusSearch(const Tensor &query_points, double radius, bool sort=true)
bool HybridIndex(utility::optional< double > radius={})
bool FixedRadiusIndex(utility::optional< double > radius={})
std::tuple< Tensor, Tensor, Tensor > HybridSearch(const Tensor &query_points, const double radius, const int max_knn) const
std::pair< Tensor, Tensor > KnnSearch(const Tensor &query_points, int knn)
A bounding box that is aligned along the coordinate axes and defined by the min_bound and max_bound.
core::Tensor GetPointIndicesWithinBoundingBox(const core::Tensor &points) const
Indices to points that are within the bounding box.
static AxisAlignedBoundingBox CreateFromPoints(const core::Tensor &points)
core::Device GetDevice() const override
Returns the device attribute of this AxisAlignedBoundingBox.
bool IsEmpty() const override
Returns true iff the geometry is empty.
GeometryType
Specifies possible geometry types.
The Image class stores image with customizable rows, cols, channels, dtype and device.
Image ClipTransform(float scale, float min_value, float max_value, float clip_fill=0.0f) const
Return new image after scaling and clipping image values.
Image To(const core::Device &device, bool copy=false) const
Transfer the image to a specified device.
core::Tensor AsTensor() const
Returns the underlying Tensor of the Image.
int64_t GetCols() const
Get the number of columns of the image.
int64_t GetRows() const
Get the number of rows of the image.
A LineSet contains points and lines joining them and optionally attributes on the points and lines.
A bounding box oriented along an arbitrary frame of reference.
bool IsEmpty() const override
Returns true iff the geometry is empty.
static OrientedBoundingBox CreateFromPoints(const core::Tensor &points, bool robust=false, MethodOBBCreate method=MethodOBBCreate::MINIMAL_APPROX)
core::Device GetDevice() const override
Returns the device attribute of this OrientedBoundingBox.
core::Tensor GetPointIndicesWithinBoundingBox(const core::Tensor &points) const
Indices to points that are within the bounding box.
A point cloud contains a list of 3D points.
void SetPointNormals(const core::Tensor &value)
Set the value of the "normals" attribute. Convenience function.
void OrientNormalsToAlignWithDirection(const core::Tensor &orientation_reference=core::Tensor::Init< float >({0, 0, 1}, core::Device("CPU:0")))
Function to orient the normals of a point cloud.
std::tuple< PointCloud, core::Tensor > RemoveNonFinitePoints(bool remove_nan=true, bool remove_infinite=true) const
Remove all points from the point cloud that have a nan entry, or infinite value. It also removes the ...
std::tuple< core::Tensor, core::Tensor > SegmentPlane(const double distance_threshold=0.01, const int ransac_n=3, const int num_iterations=100, const double probability=0.99999999) const
Segment PointCloud plane using the RANSAC algorithm. This is a wrapper for a CPU implementation and a...
core::Tensor GetCenter() const
Returns the center for point coordinates.
int GaussianSplatGetSHOrder() const
Returns the order of spherical harmonics used for Gaussian Splatting. Returns 0 if f_rest is not pres...
PointCloud & NormalizeNormals()
Normalize point normals to length 1.
PointCloud & Rotate(const core::Tensor &R, const core::Tensor ¢er)
Rotates the PointPositions and PointNormals (if exists).
core::Tensor & GetPointNormals()
Get the value of the "normals" attribute. Convenience function.
PointCloud VoxelDownSample(double voxel_size, const std::string &reduction="mean") const
Downsamples a point cloud with a specified voxel size.
PointCloud Crop(const AxisAlignedBoundingBox &aabb, bool invert=false) const
Function to crop pointcloud into output pointcloud.
PointCloud FarthestPointDownSample(const size_t num_samples, const size_t start_index=0) const
Downsample a pointcloud into output pointcloud with a set of points has farthest distance.
bool HasPointPositions() const
void SetPointColors(const core::Tensor &value)
Set the value of the "colors" attribute. Convenience function.
bool HasPointAttr(const std::string &key) const
bool IsGaussianSplat() const
PointCloud SelectByIndex(const core::Tensor &indices, bool invert=false, bool remove_duplicates=false) const
Select points from input pointcloud, based on indices list into output point cloud.
core::Tensor GetMaxBound() const
Returns the max bound for point coordinates.
TriangleMesh ComputeConvexHull(bool joggle_inputs=false) const
static PointCloud FromLegacy(const cloudViewer::geometry::PointCloud &pcd_legacy, core::Dtype dtype=core::Float32, const core::Device &device=core::Device("CPU:0"))
Create a PointCloud from a legacy CloudViewer PointCloud.
PointCloud RandomDownSample(double sampling_ratio) const
Downsample a pointcloud by selecting random index point and its attributes.
std::tuple< TriangleMesh, core::Tensor > HiddenPointRemoval(const core::Tensor &camera_location, double radius) const
This is an implementation of the Hidden Point Removal operator described in Katz et....
OrientedBoundingBox GetOrientedBoundingBox() const
Create an oriented bounding box from attribute "positions".
void EstimateNormals(const utility::optional< int > max_nn=30, const utility::optional< double > radius=utility::nullopt)
Function to estimate point normals. If the point cloud normals exist, the estimated normals are orien...
void SetPointPositions(const core::Tensor &value)
Set the value of the "positions" attribute. Convenience function.
core::Tensor GetMinBound() const
Returns the min bound for point coordinates.
int PCAPartition(int max_points)
std::string ToString() const
Text description.
core::Tensor & GetPointPositions()
Get the value of the "positions" attribute. Convenience function.
LineSet ExtrudeRotation(double angle, const core::Tensor &axis, int resolution=16, double translation=0.0, bool capping=true) const
void OrientNormalsTowardsCameraLocation(const core::Tensor &camera_location=core::Tensor::Zeros({3}, core::Float32, core::Device("CPU:0")))
Function to orient the normals of a point cloud.
std::tuple< PointCloud, core::Tensor > RemoveStatisticalOutliers(size_t nb_neighbors, double std_ratio) const
Remove points that are further away from their nb_neighbor neighbors in average. This function is not...
bool IsEmpty() const override
Returns !HasPointPositions().
PointCloud To(const core::Device &device, bool copy=false) const
PointCloud SelectByMask(const core::Tensor &boolean_mask, bool invert=false) const
Select points from input pointcloud, based on boolean mask indices into output point cloud.
PointCloud UniformDownSample(size_t every_k_points) const
Downsamples a point cloud by selecting every kth index point and its attributes.
AxisAlignedBoundingBox GetAxisAlignedBoundingBox() const
Create an axis-aligned bounding box from attribute "positions".
void EstimateColorGradients(const utility::optional< int > max_nn=30, const utility::optional< double > radius=utility::nullopt)
Function to compute point color gradients. If radius is provided, then HybridSearch is used,...
PointCloud & PaintUniformColor(const core::Tensor &color)
Assigns uniform color to the point cloud.
cloudViewer::geometry::PointCloud ToLegacy() const
Convert to a legacy CloudViewer PointCloud.
core::Device GetDevice() const override
Returns the device attribute of this PointCloud.
static PointCloud CreateFromDepthImage(const Image &depth, const core::Tensor &intrinsics, const core::Tensor &extrinsics=core::Tensor::Eye(4, core::Float32, core::Device("CPU:0")), float depth_scale=1000.0f, float depth_max=3.0f, int stride=1, bool with_normals=false)
Factory function to create a point cloud from a depth image and a camera model.
LineSet ExtrudeLinear(const core::Tensor &vector, double scale=1.0, bool capping=true) const
std::tuple< PointCloud, core::Tensor > ComputeBoundaryPoints(double radius, int max_nn=30, double angle_threshold=90.0) const
Compute the boundary points of a point cloud. The implementation is inspired by the PCL implementatio...
geometry::RGBDImage ProjectToRGBDImage(int width, int height, const core::Tensor &intrinsics, const core::Tensor &extrinsics=core::Tensor::Eye(4, core::Float32, core::Device("CPU:0")), float depth_scale=1000.0f, float depth_max=3.0f)
Project a point cloud to an RGBD image.
void RemovePointAttr(const std::string &key)
PointCloud & Translate(const core::Tensor &translation, bool relative=true)
Translates the PointPositions of the PointCloud.
geometry::Image ProjectToDepthImage(int width, int height, const core::Tensor &intrinsics, const core::Tensor &extrinsics=core::Tensor::Eye(4, core::Float32, core::Device("CPU:0")), float depth_scale=1000.0f, float depth_max=3.0f)
Project a point cloud to a depth image.
bool HasPointNormals() const
PointCloud Clone() const
Returns copy of the point cloud on the same device.
std::tuple< PointCloud, core::Tensor > RemoveRadiusOutliers(size_t nb_points, double search_radius) const
Remove points that have less than nb_points neighbors in a sphere of a given radius.
std::tuple< PointCloud, core::Tensor > RemoveDuplicatedPoints() const
Remove duplicated points and there associated attributes.
const TensorMap & GetPointAttr() const
Getter for point_attr_ TensorMap. Used in Pybind.
core::Tensor ComputeMetrics(const PointCloud &pcd2, std::vector< Metric > metrics={Metric::ChamferDistance}, MetricParameters params=MetricParameters()) const
PointCloud & Scale(double scale, const core::Tensor ¢er)
Scales the PointPositions of the PointCloud.
PointCloud Append(const PointCloud &other) const
void SetPointAttr(const std::string &key, const core::Tensor &value)
core::Tensor ClusterDBSCAN(double eps, size_t min_points, bool print_progress=false) const
Cluster PointCloud using the DBSCAN algorithm Ester et al., "A Density-Based Algorithm for Discoverin...
core::Tensor & GetPointColors()
Get the value of the "colors" attribute. Convenience function.
PointCloud(const core::Device &device=core::Device("CPU:0"))
PointCloud & Transform(const core::Tensor &transformation)
Transforms the PointPositions and PointNormals (if exist) of the PointCloud.
bool HasPointColors() const
void OrientNormalsConsistentTangentPlane(size_t k, const double lambda=0.0, const double cos_alpha_tol=1.0)
Function to consistently orient estimated normals based on consistent tangent planes as described in ...
static PointCloud CreateFromRGBDImage(const RGBDImage &rgbd_image, const core::Tensor &intrinsics, const core::Tensor &extrinsics=core::Tensor::Eye(4, core::Float32, core::Device("CPU:0")), float depth_scale=1000.0f, float depth_max=3.0f, int stride=1, bool with_normals=false)
Factory function to create a point cloud from an RGB-D image and a camera model.
RGBDImage A pair of color and depth images.
Image depth_
The depth image.
Image color_
The color image.
std::string GetPrimaryKey() const
Returns the primary key of the TensorMap.
A triangle mesh contains vertices and triangles.
TriangleMesh To(const core::Device &device, bool copy=false) const
void SetVertexAttr(const std::string &key, const core::Tensor &value)
constexpr bool has_value() const noexcept
constexpr T const & value() const &
__device__ __forceinline__ float infinity()
__host__ __device__ float length(float2 v)
double std_dev(const T &vec)
std::vector< Eigen::Vector3d > TensorToEigenVector3dVector(const core::Tensor &tensor)
Converts a tensor of shape (N, 3) to std::vector<Eigen::Vector3d>. An exception will be thrown if the...
core::Tensor EigenVector3dVectorToTensor(const std::vector< Eigen::Vector3d > &values, core::Dtype dtype, const core::Device &device)
Converts a vector of Eigen::Vector3d to a (N, 3) tensor. This function also takes care of dtype conve...
Tensor Minimum(const Tensor &input, const Tensor &other)
Computes the element-wise minimum of input and other. The tensors must have same data type and device...
constexpr utility::nullopt_t None
std::tuple< int, core::Tensor > PCAPartition(core::Tensor &points, int max_points)
void ComputeBoundaryPointsCPU(const core::Tensor &points, const core::Tensor &normals, const core::Tensor &indices, const core::Tensor &counts, core::Tensor &mask, double angle_threshold)
void OrientNormalsTowardsCameraLocationCPU(const core::Tensor &points, core::Tensor &normals, const core::Tensor &camera)
void Project(core::Tensor &depth, utility::optional< std::reference_wrapper< core::Tensor >> image_colors, const core::Tensor &points, utility::optional< std::reference_wrapper< const core::Tensor >> colors, const core::Tensor &intrinsics, const core::Tensor &extrinsics, float depth_scale, float depth_max)
void EstimateNormalsFromCovariancesCPU(const core::Tensor &covariances, core::Tensor &normals, const bool has_normals)
void EstimateColorGradientsUsingRadiusSearchCPU(const core::Tensor &points, const core::Tensor &normals, const core::Tensor &colors, core::Tensor &color_gradient, const double &radius)
void EstimateColorGradientsUsingKNNSearchCPU(const core::Tensor &points, const core::Tensor &normals, const core::Tensor &colors, core::Tensor &color_gradient, const int64_t &max_nn)
void NormalizeNormalsCPU(core::Tensor &normals)
void OrientNormalsToAlignWithDirectionCPU(core::Tensor &normals, const core::Tensor &direction)
void EstimateCovariancesUsingHybridSearchCPU(const core::Tensor &points, core::Tensor &covariances, const double &radius, const int64_t &max_nn)
void Unproject(const core::Tensor &depth, utility::optional< std::reference_wrapper< const core::Tensor >> image_colors, core::Tensor &points, utility::optional< std::reference_wrapper< core::Tensor >> colors, const core::Tensor &intrinsics, const core::Tensor &extrinsics, float depth_scale, float depth_max, int64_t stride)
void EstimateCovariancesUsingRadiusSearchCPU(const core::Tensor &points, core::Tensor &covariances, const double &radius)
void EstimateCovariancesUsingKNNSearchCPU(const core::Tensor &points, core::Tensor &covariances, const int64_t &max_nn)
void EstimateColorGradientsUsingHybridSearchCPU(const core::Tensor &points, const core::Tensor &normals, const core::Tensor &colors, core::Tensor &color_gradient, const double &radius, const int64_t &max_nn)
CLOUDVIEWER_LOCAL LineSet ExtrudeLinearLineSet(const PointCloud &pointcloud, const core::Tensor &vector, double scale, bool capping)
CLOUDVIEWER_LOCAL LineSet ExtrudeRotationLineSet(const PointCloud &pointcloud, const double angle, const core::Tensor &axis, int resolution, double translation, bool capping)
core::Tensor ComputeMetricsCommon(core::Tensor distance12, core::Tensor distance21, std::vector< Metric > metrics, MetricParameters params)
static PointCloud CreatePointCloudWithNormals(const Image &depth_in, const Image &color_in, const core::Tensor &intrinsics_in, const core::Tensor &extrinsics, float depth_scale, float depth_max, int stride)
std::mt19937 * GetEngine()
constexpr nullopt_t nullopt
Generic file read and write utility for python interface.
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Holder for various parameters required by metrics.