32 namespace pointcloud {
41 #if defined(__CUDACC__)
57 const bool have_colors = image_colors.has_value();
73 const auto& imcol = image_colors.value().get();
81 #if defined(__CUDACC__)
83 int* count_ptr =
count.GetDataPtr<
int>();
85 std::atomic<int> count_atomic(0);
86 std::atomic<int>* count_ptr = &count_atomic;
89 int64_t n = rows_strided * cols_strided;
94 [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
95 int64_t y = (workload_idx / cols_strided) * stride;
96 int64_t x = (workload_idx % cols_strided) * stride;
98 float d = *depth_indexer.GetDataPtr<scalar_t>(x, y) /
100 if (d > 0 && d < depth_max) {
101 int idx = OPEN3D_ATOMIC_ADD(count_ptr, 1);
103 float x_c = 0, y_c = 0, z_c = 0;
104 ti.Unproject(static_cast<float>(x),
105 static_cast<float>(y), d, &x_c, &y_c,
108 float* vertex = point_indexer.GetDataPtr<float>(idx);
109 ti.RigidTransform(x_c, y_c, z_c, vertex + 0, vertex + 1,
113 colors_indexer.GetDataPtr<float>(idx);
115 image_colors_indexer.GetDataPtr<float>(x,
117 *pcd_pixel = *image_pixel;
118 *(pcd_pixel + 1) = *(image_pixel + 1);
119 *(pcd_pixel + 2) = *(image_pixel + 2);
124 #if defined(__CUDACC__)
125 int total_pts_count =
count.Item<
int>();
127 int total_pts_count = (*count_ptr).load();
136 colors.value().get().Slice(0, 0, total_pts_count);
140 #if defined(__CUDACC__)
141 void GetPointMaskWithinAABBCUDA
151 const scalar_t* points_ptr = points.GetDataPtr<scalar_t>();
152 const int64_t n = points.GetLength();
153 const scalar_t* min_bound_ptr = min_bound.GetDataPtr<scalar_t>();
154 const scalar_t* max_bound_ptr = max_bound.GetDataPtr<scalar_t>();
155 bool* mask_ptr = mask.GetDataPtr<bool>();
158 points.GetDevice(), n,
159 [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
160 const scalar_t x = points_ptr[3 * workload_idx + 0];
161 const scalar_t y = points_ptr[3 * workload_idx + 1];
162 const scalar_t z = points_ptr[3 * workload_idx + 2];
164 if (x >= min_bound_ptr[0] && x <= max_bound_ptr[0] &&
165 y >= min_bound_ptr[1] && y <= max_bound_ptr[1] &&
166 z >= min_bound_ptr[2] && z <= max_bound_ptr[2]) {
167 mask_ptr[workload_idx] = true;
169 mask_ptr[workload_idx] = false;
175 #if defined(__CUDACC__)
176 void GetPointMaskWithinOBBCUDA
190 const int64_t n =
points.GetLength();
193 const scalar_t* pd_ptr = pd.GetDataPtr<scalar_t>();
195 const scalar_t* rotation_ptr = rotation_t.GetDataPtr<scalar_t>();
196 const scalar_t* half_extent_ptr = half_extent.GetDataPtr<scalar_t>();
197 bool* mask_ptr = mask.GetDataPtr<bool>();
199 core::ParallelFor(points.GetDevice(), n,
200 [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
201 int64_t idx = 3 * workload_idx;
202 if (abs(core::linalg::kernel::dot_3x1(
203 pd_ptr + idx, rotation_ptr)) <=
204 half_extent_ptr[0] &&
205 abs(core::linalg::kernel::dot_3x1(
206 pd_ptr + idx, rotation_ptr + 3)) <=
207 half_extent_ptr[1] &&
208 abs(core::linalg::kernel::dot_3x1(
209 pd_ptr + idx, rotation_ptr + 6)) <=
210 half_extent_ptr[2]) {
211 mask_ptr[workload_idx] = true;
213 mask_ptr[workload_idx] = false;
219 #if defined(__CUDACC__)
220 void NormalizeNormalsCUDA
226 const int64_t n =
normals.GetLength();
229 scalar_t* ptr =
normals.GetDataPtr<scalar_t>();
233 int64_t idx = 3 * workload_idx;
234 scalar_t x = ptr[idx];
235 scalar_t y = ptr[idx + 1];
236 scalar_t z = ptr[idx + 2];
237 scalar_t norm = sqrt(x * x + y * y + z * z);
250 #if defined(__CUDACC__)
251 void OrientNormalsToAlignWithDirectionCUDA
257 const int64_t n =
normals.GetLength();
260 scalar_t* ptr =
normals.GetDataPtr<scalar_t>();
261 const scalar_t* direction_ptr = direction.GetDataPtr<scalar_t>();
265 int64_t idx = 3 * workload_idx;
266 scalar_t*
normal = ptr + idx;
271 normal[0] = direction_ptr[0];
272 normal[1] = direction_ptr[1];
273 normal[2] = direction_ptr[2];
275 normal, direction_ptr) < 0) {
284 #if defined(__CUDACC__)
285 void OrientNormalsTowardsCameraLocationCUDA
293 const int64_t n =
normals.GetLength();
296 scalar_t* normals_ptr =
normals.GetDataPtr<scalar_t>();
297 const scalar_t* camera_ptr = camera.GetDataPtr<scalar_t>();
298 const scalar_t* points_ptr =
points.GetDataPtr<scalar_t>();
303 int64_t idx = 3 * workload_idx;
304 scalar_t*
normal = normals_ptr + idx;
305 const scalar_t*
point = points_ptr + idx;
306 const scalar_t reference[3] = {camera_ptr[0] -
point[0],
307 camera_ptr[1] -
point[1],
308 camera_ptr[2] -
point[2]};
309 const scalar_t norm =
319 if (norm_new == 0.0) {
338 template <
typename scalar_t>
347 if (!(
abs(query[0] - query[2]) < 1e-6) ||
348 !(
abs(query[1] - query[2]) < 1e-6)) {
349 const scalar_t norm2_inv =
350 1.0 / sqrt(query[0] * query[0] + query[1] * query[1]);
351 v[0] = -1 * query[1] * norm2_inv;
352 v[1] = query[0] * norm2_inv;
355 const scalar_t norm2_inv =
356 1.0 / sqrt(query[1] * query[1] + query[2] * query[2]);
358 v[1] = -1 * query[2] * norm2_inv;
359 v[2] = query[1] * norm2_inv;
365 template <
typename scalar_t>
372 template <
typename scalar_t>
375 int l = 2 * root + 1;
376 int r = 2 * root + 2;
378 if (l < n && arr[l] > arr[largest]) {
381 if (r < n && arr[r] > arr[largest]) {
384 if (largest != root) {
385 Swap<scalar_t>(&arr[root], &arr[largest]);
386 Heapify<scalar_t>(arr, n, largest);
390 template <
typename scalar_t>
392 for (
int i = n / 2 - 1; i >= 0; i--)
Heapify(arr, n, i);
394 for (
int i = n - 1; i > 0; i--) {
395 Swap<scalar_t>(&arr[0], &arr[i]);
396 Heapify<scalar_t>(arr, i, 0);
400 template <
typename scalar_t>
403 double angle_threshold) {
405 scalar_t max_diff = 0;
407 for (
int i = 0; i < counts - 1; i++) {
408 diff = angles[i + 1] - angles[i];
409 max_diff =
max(max_diff, diff);
413 diff = 2 *
M_PI - angles[counts - 1] + angles[0];
414 max_diff =
max(max_diff, diff);
416 return max_diff > angle_threshold *
M_PI / 180.0 ? true :
false;
419 #if defined(__CUDACC__)
420 void ComputeBoundaryPointsCUDA
429 double angle_threshold) {
430 const int nn_size = indices.GetShape()[1];
433 const scalar_t* points_ptr = points.GetDataPtr<scalar_t>();
434 const scalar_t* normals_ptr = normals.GetDataPtr<scalar_t>();
435 const int64_t n = points.GetLength();
436 const int32_t* indices_ptr = indices.GetDataPtr<int32_t>();
437 const int32_t* counts_ptr = counts.GetDataPtr<int32_t>();
438 bool* mask_ptr = mask.GetDataPtr<bool>();
440 core::Tensor angles = core::Tensor::Full(
441 indices.GetShape(), -10, points.GetDtype(), points.GetDevice());
442 scalar_t* angles_ptr = angles.GetDataPtr<scalar_t>();
445 points.GetDevice(), n,
446 [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
448 GetCoordinateSystemOnPlane(normals_ptr + 3 * workload_idx,
452 int indices_size = counts_ptr[workload_idx] - 1;
453 if (indices_size > 0) {
454 const scalar_t* query = points_ptr + 3 * workload_idx;
455 for (int i = 1; i < indices_size + 1; i++) {
456 const int idx = workload_idx * nn_size + i;
458 const scalar_t* point_ref =
459 points_ptr + 3 * indices_ptr[idx];
460 const scalar_t delta[3] = {point_ref[0] - query[0],
461 point_ref[1] - query[1],
462 point_ref[2] - query[2]};
463 const scalar_t angle = atan2(
464 core::linalg::kernel::dot_3x1(v, delta),
465 core::linalg::kernel::dot_3x1(u, delta));
467 angles_ptr[idx] = angle;
472 angles_ptr + workload_idx * nn_size + 1,
475 mask_ptr[workload_idx] = IsBoundaryPoints<scalar_t>(
476 angles_ptr + workload_idx * nn_size + 1,
477 indices_size, angle_threshold);
485 template <
typename scalar_t>
487 const scalar_t* points_ptr,
488 const int32_t* indices_ptr,
489 const int32_t& indices_count,
490 scalar_t* covariance_ptr) {
491 if (indices_count < 3) {
492 covariance_ptr[0] = 1.0;
493 covariance_ptr[1] = 0.0;
494 covariance_ptr[2] = 0.0;
495 covariance_ptr[3] = 0.0;
496 covariance_ptr[4] = 1.0;
497 covariance_ptr[5] = 0.0;
498 covariance_ptr[6] = 0.0;
499 covariance_ptr[7] = 0.0;
500 covariance_ptr[8] = 1.0;
504 double centroid[3] = {0};
505 for (int32_t i = 0; i < indices_count; ++i) {
506 int32_t idx = 3 * indices_ptr[i];
507 centroid[0] += points_ptr[idx];
508 centroid[1] += points_ptr[idx + 1];
509 centroid[2] += points_ptr[idx + 2];
512 centroid[0] /= indices_count;
513 centroid[1] /= indices_count;
514 centroid[2] /= indices_count;
517 double cumulants[6] = {0};
518 for (int32_t i = 0; i < indices_count; ++i) {
519 int32_t idx = 3 * indices_ptr[i];
520 const double x =
static_cast<double>(points_ptr[idx]) - centroid[0];
521 const double y =
static_cast<double>(points_ptr[idx + 1]) - centroid[1];
522 const double z =
static_cast<double>(points_ptr[idx + 2]) - centroid[2];
524 cumulants[0] += x * x;
525 cumulants[1] += y * y;
526 cumulants[2] += z * z;
528 cumulants[3] += x * y;
529 cumulants[4] += x * z;
530 cumulants[5] += y * z;
536 const double normalization_factor =
static_cast<double>(indices_count - 1);
537 for (
int i = 0; i < 6; ++i) {
538 cumulants[i] /= normalization_factor;
542 covariance_ptr[0] =
static_cast<scalar_t
>(cumulants[0]);
544 covariance_ptr[4] =
static_cast<scalar_t
>(cumulants[1]);
546 covariance_ptr[8] =
static_cast<scalar_t
>(cumulants[2]);
549 covariance_ptr[1] =
static_cast<scalar_t
>(cumulants[3]);
550 covariance_ptr[3] = covariance_ptr[1];
553 covariance_ptr[2] =
static_cast<scalar_t
>(cumulants[4]);
554 covariance_ptr[6] = covariance_ptr[2];
557 covariance_ptr[5] =
static_cast<scalar_t
>(cumulants[5]);
558 covariance_ptr[7] = covariance_ptr[5];
561 #if defined(__CUDACC__)
562 void EstimateCovariancesUsingHybridSearchCUDA
568 const double& radius,
569 const int64_t& max_nn) {
571 int64_t n =
points.GetLength();
580 std::tie(indices, distance, counts) =
584 const scalar_t* points_ptr =
points.GetDataPtr<scalar_t>();
585 int32_t* neighbour_indices_ptr = indices.
GetDataPtr<int32_t>();
586 int32_t* neighbour_counts_ptr = counts.
GetDataPtr<int32_t>();
587 scalar_t* covariances_ptr = covariances.GetDataPtr<scalar_t>();
593 const int32_t neighbour_offset = max_nn * workload_idx;
595 const int32_t neighbour_count =
596 neighbour_counts_ptr[workload_idx];
599 const int32_t covariances_offset = 9 * workload_idx;
603 neighbour_indices_ptr + neighbour_offset,
605 covariances_ptr + covariances_offset);
612 #if defined(__CUDACC__)
613 void EstimateCovariancesUsingRadiusSearchCUDA
619 const double& radius) {
621 int64_t n =
points.GetLength();
630 std::tie(indices, distance, counts) =
634 const scalar_t* points_ptr =
points.GetDataPtr<scalar_t>();
635 const int32_t* neighbour_indices_ptr = indices.
GetDataPtr<int32_t>();
636 const int32_t* neighbour_counts_ptr = counts.
GetDataPtr<int32_t>();
637 scalar_t* covariances_ptr = covariances.GetDataPtr<scalar_t>();
641 const int32_t neighbour_offset =
642 neighbour_counts_ptr[workload_idx];
643 const int32_t neighbour_count =
644 (neighbour_counts_ptr[workload_idx + 1] -
645 neighbour_counts_ptr[workload_idx]);
648 const int32_t covariances_offset =
653 neighbour_indices_ptr + neighbour_offset,
655 covariances_ptr + covariances_offset);
662 #if defined(__CUDACC__)
663 void EstimateCovariancesUsingKNNSearchCUDA
669 const int64_t& max_nn) {
671 int64_t n =
points.GetLength();
683 int32_t nn_count =
static_cast<int32_t
>(indices.
GetShape()[1]);
687 "Not enough neighbors to compute Covariances / Normals. "
689 "increasing the max_nn parameter.");
693 auto points_ptr =
points.GetDataPtr<scalar_t>();
694 auto neighbour_indices_ptr = indices.
GetDataPtr<int32_t>();
695 auto covariances_ptr = covariances.GetDataPtr<scalar_t>();
701 const int32_t neighbour_offset = nn_count * workload_idx;
704 const int32_t covariances_offset = 9 * workload_idx;
708 neighbour_indices_ptr + neighbour_offset, nn_count,
709 covariances_ptr + covariances_offset);
716 template <
typename scalar_t>
718 const scalar_t eval0,
719 scalar_t* eigen_vector0) {
720 scalar_t row0[3] = {A[0] - eval0, A[1], A[2]};
721 scalar_t row1[3] = {A[1], A[4] - eval0, A[5]};
722 scalar_t row2[3] = {A[2], A[5], A[8] - eval0};
724 scalar_t r0xr1[3], r0xr2[3], r1xr2[3];
745 scalar_t sqrt_d = sqrt(d0);
746 eigen_vector0[0] = r0xr1[0] / sqrt_d;
747 eigen_vector0[1] = r0xr1[1] / sqrt_d;
748 eigen_vector0[2] = r0xr1[2] / sqrt_d;
750 }
else if (imax == 1) {
751 scalar_t sqrt_d = sqrt(d1);
752 eigen_vector0[0] = r0xr2[0] / sqrt_d;
753 eigen_vector0[1] = r0xr2[1] / sqrt_d;
754 eigen_vector0[2] = r0xr2[2] / sqrt_d;
757 scalar_t sqrt_d = sqrt(d2);
758 eigen_vector0[0] = r1xr2[0] / sqrt_d;
759 eigen_vector0[1] = r1xr2[1] / sqrt_d;
760 eigen_vector0[2] = r1xr2[2] / sqrt_d;
765 template <
typename scalar_t>
767 const scalar_t* evec0,
768 const scalar_t eval1,
769 scalar_t* eigen_vector1) {
771 if (
abs(evec0[0]) >
abs(evec0[1])) {
772 scalar_t inv_length =
773 1.0 / sqrt(evec0[0] * evec0[0] + evec0[2] * evec0[2]);
774 U[0] = -evec0[2] * inv_length;
776 U[2] = evec0[0] * inv_length;
778 scalar_t inv_length =
779 1.0 / sqrt(evec0[1] * evec0[1] + evec0[2] * evec0[2]);
781 U[1] = evec0[2] * inv_length;
782 U[2] = -evec0[1] * inv_length;
784 scalar_t V[3], AU[3], AV[3];
793 scalar_t absM00 =
abs(m00);
794 scalar_t absM01 =
abs(m01);
795 scalar_t absM11 =
abs(m11);
796 scalar_t max_abs_comp;
798 if (absM00 >= absM11) {
799 max_abs_comp =
max(absM00, absM01);
800 if (max_abs_comp > 0) {
801 if (absM00 >= absM01) {
803 m00 = 1 / sqrt(1 + m01 * m01);
807 m01 = 1 / sqrt(1 + m00 * m00);
810 eigen_vector1[0] = m01 * U[0] - m00 * V[0];
811 eigen_vector1[1] = m01 * U[1] - m00 * V[1];
812 eigen_vector1[2] = m01 * U[2] - m00 * V[2];
815 eigen_vector1[0] = U[0];
816 eigen_vector1[1] = U[1];
817 eigen_vector1[2] = U[2];
821 max_abs_comp =
max(absM11, absM01);
822 if (max_abs_comp > 0) {
823 if (absM11 >= absM01) {
825 m11 = 1 / sqrt(1 + m01 * m01);
829 m01 = 1 / sqrt(1 + m11 * m11);
832 eigen_vector1[0] = m11 * U[0] - m01 * V[0];
833 eigen_vector1[1] = m11 * U[1] - m01 * V[1];
834 eigen_vector1[2] = m11 * U[2] - m01 * V[2];
837 eigen_vector1[0] = U[0];
838 eigen_vector1[1] = U[1];
839 eigen_vector1[2] = U[2];
845 template <
typename scalar_t>
847 const scalar_t* covariance_ptr, scalar_t* normals_ptr) {
851 scalar_t max_coeff = covariance_ptr[0];
853 for (
int i = 1; i < 9; ++i) {
854 if (max_coeff < covariance_ptr[i]) {
855 max_coeff = covariance_ptr[i];
859 if (max_coeff == 0) {
860 normals_ptr[0] = 0.0;
861 normals_ptr[1] = 0.0;
862 normals_ptr[2] = 0.0;
868 for (
int i = 0; i < 9; ++i) {
869 A[i] = covariance_ptr[i] / max_coeff;
872 scalar_t norm = A[1] * A[1] + A[2] * A[2] + A[5] * A[5];
880 scalar_t q = (A[0] + A[4] + A[8]) / 3.0;
882 scalar_t b00 = A[0] - q;
883 scalar_t b11 = A[4] - q;
884 scalar_t b22 = A[8] - q;
887 sqrt((b00 * b00 + b11 * b11 + b22 * b22 + norm * 2.0) / 6.0);
889 scalar_t c00 = b11 * b22 - A[5] * A[5];
890 scalar_t c01 = A[1] * b22 - A[5] * A[2];
891 scalar_t c02 = A[1] * A[5] - b11 * A[2];
892 scalar_t det = (b00 * c00 - A[1] * c01 + A[2] * c02) / (p * p * p);
894 scalar_t half_det = det * 0.5;
895 half_det =
min(
max(half_det,
static_cast<scalar_t
>(-1.0)),
896 static_cast<scalar_t
>(1.0));
898 scalar_t angle = acos(half_det) / 3.0;
899 const scalar_t two_thrids_pi = 2.09439510239319549;
901 scalar_t beta2 = cos(angle) * 2.0;
902 scalar_t beta0 = cos(angle + two_thrids_pi) * 2.0;
903 scalar_t beta1 = -(beta0 + beta2);
905 eval[0] = q + p * beta0;
906 eval[1] = q + p * beta1;
907 eval[2] = q + p * beta2;
910 ComputeEigenvector0<scalar_t>(A, eval[2], evec2);
912 if (eval[2] < eval[0] && eval[2] < eval[1]) {
913 normals_ptr[0] = evec2[0];
914 normals_ptr[1] = evec2[1];
915 normals_ptr[2] = evec2[2];
920 ComputeEigenvector1<scalar_t>(A, evec2, eval[1], evec1);
922 if (eval[1] < eval[0] && eval[1] < eval[2]) {
923 normals_ptr[0] = evec1[0];
924 normals_ptr[1] = evec1[1];
925 normals_ptr[2] = evec1[2];
930 normals_ptr[0] = evec1[1] * evec2[2] - evec1[2] * evec2[1];
931 normals_ptr[1] = evec1[2] * evec2[0] - evec1[0] * evec2[2];
932 normals_ptr[2] = evec1[0] * evec2[1] - evec1[1] * evec2[0];
936 ComputeEigenvector0<scalar_t>(A, eval[0], evec0);
938 if (eval[0] < eval[1] && eval[0] < eval[2]) {
939 normals_ptr[0] = evec0[0];
940 normals_ptr[1] = evec0[1];
941 normals_ptr[2] = evec0[2];
945 ComputeEigenvector1<scalar_t>(A, evec0, eval[1], evec1);
947 if (eval[1] < eval[0] && eval[1] < eval[2]) {
948 normals_ptr[0] = evec1[0];
949 normals_ptr[1] = evec1[1];
950 normals_ptr[2] = evec1[2];
954 normals_ptr[0] = evec0[1] * evec1[2] - evec0[2] * evec1[1];
955 normals_ptr[1] = evec0[2] * evec1[0] - evec0[0] * evec1[2];
956 normals_ptr[2] = evec0[0] * evec1[1] - evec0[1] * evec1[0];
960 if (covariance_ptr[0] < covariance_ptr[4] &&
961 covariance_ptr[0] < covariance_ptr[8]) {
962 normals_ptr[0] = 1.0;
963 normals_ptr[1] = 0.0;
964 normals_ptr[2] = 0.0;
966 }
else if (covariance_ptr[4] < covariance_ptr[0] &&
967 covariance_ptr[4] < covariance_ptr[8]) {
968 normals_ptr[0] = 0.0;
969 normals_ptr[1] = 1.0;
970 normals_ptr[2] = 0.0;
973 normals_ptr[0] = 0.0;
974 normals_ptr[1] = 0.0;
975 normals_ptr[2] = 1.0;
981 #if defined(__CUDACC__)
982 void EstimateNormalsFromCovariancesCUDA
990 int64_t n = covariances.GetLength();
993 const scalar_t* covariances_ptr = covariances.GetDataPtr<scalar_t>();
994 scalar_t* normals_ptr =
normals.GetDataPtr<scalar_t>();
997 covariances.GetDevice(), n,
999 int32_t covariances_offset = 9 * workload_idx;
1000 int32_t normals_offset = 3 * workload_idx;
1001 scalar_t normals_output[3] = {0};
1002 EstimatePointWiseNormalsWithFastEigen3x3<scalar_t>(
1003 covariances_ptr + covariances_offset,
1006 if ((normals_output[0] * normals_output[0] +
1007 normals_output[1] * normals_output[1] +
1008 normals_output[2] * normals_output[2]) == 0.0 &&
1010 normals_output[0] = 0.0;
1011 normals_output[1] = 0.0;
1012 normals_output[2] = 1.0;
1015 if ((normals_ptr[normals_offset] * normals_output[0] +
1016 normals_ptr[normals_offset + 1] *
1018 normals_ptr[normals_offset + 2] *
1019 normals_output[2]) < 0.0) {
1020 normals_output[0] *= -1;
1021 normals_output[1] *= -1;
1022 normals_output[2] *= -1;
1026 normals_ptr[normals_offset] = normals_output[0];
1027 normals_ptr[normals_offset + 1] = normals_output[1];
1028 normals_ptr[normals_offset + 2] = normals_output[2];
1035 template <
typename scalar_t>
1037 const scalar_t* points_ptr,
1038 const scalar_t* normals_ptr,
1039 const scalar_t* colors_ptr,
1040 const int32_t& idx_offset,
1041 const int32_t* indices_ptr,
1042 const int32_t& indices_count,
1043 scalar_t* color_gradients_ptr) {
1044 if (indices_count < 4) {
1045 color_gradients_ptr[idx_offset] = 0;
1046 color_gradients_ptr[idx_offset + 1] = 0;
1047 color_gradients_ptr[idx_offset + 2] = 0;
1049 scalar_t vt[3] = {points_ptr[idx_offset], points_ptr[idx_offset + 1],
1050 points_ptr[idx_offset + 2]};
1052 scalar_t nt[3] = {normals_ptr[idx_offset], normals_ptr[idx_offset + 1],
1053 normals_ptr[idx_offset + 2]};
1055 scalar_t it = (colors_ptr[idx_offset] + colors_ptr[idx_offset + 1] +
1056 colors_ptr[idx_offset + 2]) /
1059 scalar_t AtA[9] = {0};
1060 scalar_t Atb[3] = {0};
1070 scalar_t s = vt[0] * nt[0] + vt[1] * nt[1] + vt[2] * nt[2];
1073 for (; i < indices_count; i++) {
1074 int64_t neighbour_idx_offset = 3 * indices_ptr[i];
1076 if (neighbour_idx_offset == -1) {
1080 scalar_t vt_adj[3] = {points_ptr[neighbour_idx_offset],
1081 points_ptr[neighbour_idx_offset + 1],
1082 points_ptr[neighbour_idx_offset + 2]};
1086 scalar_t d = vt_adj[0] * nt[0] + vt_adj[1] * nt[1] +
1087 vt_adj[2] * nt[2] - s;
1090 scalar_t vt_proj[3] = {vt_adj[0] - d * nt[0], vt_adj[1] - d * nt[1],
1091 vt_adj[2] - d * nt[2]};
1093 scalar_t it_adj = (colors_ptr[neighbour_idx_offset + 0] +
1094 colors_ptr[neighbour_idx_offset + 1] +
1095 colors_ptr[neighbour_idx_offset + 2]) /
1098 scalar_t A[3] = {vt_proj[0] - vt[0], vt_proj[1] - vt[1],
1099 vt_proj[2] - vt[2]};
1101 AtA[0] += A[0] * A[0];
1102 AtA[1] += A[1] * A[0];
1103 AtA[2] += A[2] * A[0];
1104 AtA[4] += A[1] * A[1];
1105 AtA[5] += A[2] * A[1];
1106 AtA[8] += A[2] * A[2];
1108 scalar_t b = it_adj - it;
1116 scalar_t A[3] = {(i - 1) * nt[0], (i - 1) * nt[1], (i - 1) * nt[2]};
1118 AtA[0] += A[0] * A[0];
1119 AtA[1] += A[0] * A[1];
1120 AtA[2] += A[0] * A[2];
1121 AtA[4] += A[1] * A[1];
1122 AtA[5] += A[1] * A[2];
1123 AtA[8] += A[2] * A[2];
1131 color_gradients_ptr + idx_offset);
1135 #if defined(__CUDACC__)
1136 void EstimateColorGradientsUsingHybridSearchCUDA
1144 const double& radius,
1145 const int64_t& max_nn) {
1147 int64_t n =
points.GetLength();
1157 std::tie(indices, distance, counts) =
1161 auto points_ptr =
points.GetDataPtr<scalar_t>();
1162 auto normals_ptr =
normals.GetDataPtr<scalar_t>();
1163 auto colors_ptr =
colors.GetDataPtr<scalar_t>();
1164 auto neighbour_indices_ptr = indices.
GetDataPtr<int32_t>();
1165 auto neighbour_counts_ptr = counts.
GetDataPtr<int32_t>();
1166 auto color_gradients_ptr = color_gradients.GetDataPtr<scalar_t>();
1171 int32_t neighbour_offset = max_nn * workload_idx;
1173 int32_t neighbour_count =
1174 neighbour_counts_ptr[workload_idx];
1175 int32_t idx_offset = 3 * workload_idx;
1178 points_ptr, normals_ptr, colors_ptr,
1180 neighbour_indices_ptr + neighbour_offset,
1181 neighbour_count, color_gradients_ptr);
1188 #if defined(__CUDACC__)
1189 void EstimateColorGradientsUsingKNNSearchCUDA
1197 const int64_t& max_nn) {
1199 int64_t n =
points.GetLength();
1212 int64_t nn_count = indices.
GetShape()[1];
1216 "Not enough neighbors to compute Covariances / Normals. "
1218 "changing the search parameter.");
1222 auto points_ptr =
points.GetDataPtr<scalar_t>();
1223 auto normals_ptr =
normals.GetDataPtr<scalar_t>();
1224 auto colors_ptr =
colors.GetDataPtr<scalar_t>();
1225 auto neighbour_indices_ptr = indices.
GetDataPtr<int32_t>();
1226 auto color_gradients_ptr = color_gradients.GetDataPtr<scalar_t>();
1230 int32_t neighbour_offset = max_nn * workload_idx;
1231 int32_t idx_offset = 3 * workload_idx;
1234 points_ptr, normals_ptr, colors_ptr,
1236 neighbour_indices_ptr + neighbour_offset,
1237 nn_count, color_gradients_ptr);
1244 #if defined(__CUDACC__)
1245 void EstimateColorGradientsUsingRadiusSearchCUDA
1253 const double& radius) {
1255 int64_t n =
points.GetLength();
1265 std::tie(indices, distance, counts) =
1272 auto points_ptr =
points.GetDataPtr<scalar_t>();
1273 auto normals_ptr =
normals.GetDataPtr<scalar_t>();
1274 auto colors_ptr =
colors.GetDataPtr<scalar_t>();
1275 auto neighbour_indices_ptr = indices.
GetDataPtr<int32_t>();
1276 auto neighbour_counts_ptr = counts.
GetDataPtr<int32_t>();
1277 auto color_gradients_ptr = color_gradients.GetDataPtr<scalar_t>();
1281 int32_t neighbour_offset =
1282 neighbour_counts_ptr[workload_idx];
1284 const int32_t neighbour_count =
1285 (neighbour_counts_ptr[workload_idx + 1] -
1286 neighbour_counts_ptr[workload_idx]);
1287 int32_t idx_offset = 3 * workload_idx;
1290 points_ptr, normals_ptr, colors_ptr,
1292 neighbour_indices_ptr + neighbour_offset,
1293 neighbour_count, color_gradients_ptr);
#define CLOUDVIEWER_HOST_DEVICE
#define CLOUDVIEWER_DEVICE
#define DISPATCH_DTYPE_TO_TEMPLATE(DTYPE,...)
#define DISPATCH_FLOAT_DTYPE_TO_TEMPLATE(DTYPE,...)
Tensor Contiguous() const
Tensor Transpose(int64_t dim0, int64_t dim1) const
Transpose a Tensor by swapping dimension dim0 and dim1.
SizeVector GetShape() const
Tensor Div(const Tensor &value) const
Divides a tensor and returns the resulting tensor.
Tensor To(Dtype dtype, bool copy=false) const
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)
CLOUDVIEWER_HOST_DEVICE index_t GetShape(int i) const
__host__ __device__ int2 abs(int2 v)
static CLOUDVIEWER_DEVICE CLOUDVIEWER_FORCE_INLINE void matmul3x3_3x1(const scalar_t &m00, const scalar_t &m01, const scalar_t &m02, const scalar_t &m10, const scalar_t &m11, const scalar_t &m12, const scalar_t &m20, const scalar_t &m21, const scalar_t &m22, const scalar_t &v0, const scalar_t &v1, const scalar_t &v2, scalar_t &o0, scalar_t &o1, scalar_t &o2)
CLOUDVIEWER_HOST_DEVICE CLOUDVIEWER_FORCE_INLINE void cross_3x1(const scalar_t *A_3x1_input, const scalar_t *B_3x1_input, scalar_t *C_3x1_output)
CLOUDVIEWER_DEVICE CLOUDVIEWER_FORCE_INLINE void solve_svd3x3(const scalar_t *A_3x3, const scalar_t *B_3x1, scalar_t *X_3x1)
CLOUDVIEWER_HOST_DEVICE CLOUDVIEWER_FORCE_INLINE scalar_t dot_3x1(const scalar_t *A_3x1_input, const scalar_t *B_3x1_input)
void ParallelFor(const Device &device, int64_t n, const func_t &func)
CLOUDVIEWER_HOST_DEVICE void Swap(scalar_t *x, scalar_t *y)
CLOUDVIEWER_HOST_DEVICE void EstimatePointWiseColorGradientKernel(const scalar_t *points_ptr, const scalar_t *normals_ptr, const scalar_t *colors_ptr, const int32_t &idx_offset, const int32_t *indices_ptr, const int32_t &indices_count, scalar_t *color_gradients_ptr)
CLOUDVIEWER_HOST_DEVICE void Heapify(scalar_t *arr, int n, int root)
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 EstimateNormalsFromCovariancesCPU(const core::Tensor &covariances, core::Tensor &normals, const bool has_normals)
void GetPointMaskWithinOBBCPU(const core::Tensor &points, const core::Tensor ¢er, const core::Tensor &rotation, const core::Tensor &extent, core::Tensor &mask)
CLOUDVIEWER_HOST_DEVICE void GetCoordinateSystemOnPlane(const scalar_t *query, scalar_t *u, scalar_t *v)
void EstimateColorGradientsUsingRadiusSearchCPU(const core::Tensor &points, const core::Tensor &normals, const core::Tensor &colors, core::Tensor &color_gradient, const double &radius)
CLOUDVIEWER_HOST_DEVICE void HeapSort(scalar_t *arr, int n)
CLOUDVIEWER_HOST_DEVICE void EstimatePointWiseNormalsWithFastEigen3x3(const scalar_t *covariance_ptr, scalar_t *normals_ptr)
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)
CLOUDVIEWER_HOST_DEVICE bool IsBoundaryPoints(const scalar_t *angles, int counts, double angle_threshold)
void UnprojectCPU(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 EstimateCovariancesUsingHybridSearchCPU(const core::Tensor &points, core::Tensor &covariances, const double &radius, const int64_t &max_nn)
void EstimateCovariancesUsingRadiusSearchCPU(const core::Tensor &points, core::Tensor &covariances, const double &radius)
CLOUDVIEWER_HOST_DEVICE void EstimatePointWiseRobustNormalizedCovarianceKernel(const scalar_t *points_ptr, const int32_t *indices_ptr, const int32_t &indices_count, scalar_t *covariance_ptr)
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)
void GetPointMaskWithinAABBCPU(const core::Tensor &points, const core::Tensor &min_bound, const core::Tensor &max_bound, core::Tensor &mask)
CLOUDVIEWER_HOST_DEVICE void ComputeEigenvector0(const scalar_t *A, const scalar_t eval0, scalar_t *eigen_vector0)
CLOUDVIEWER_HOST_DEVICE void ComputeEigenvector1(const scalar_t *A, const scalar_t *evec0, const scalar_t eval1, scalar_t *eigen_vector1)
TArrayIndexer< int64_t > NDArrayIndexer
core::Tensor InverseTransformation(const core::Tensor &T)
TODO(wei): find a proper place for such functionalities.
Generic file read and write utility for python interface.