ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PointCloudCUDA.cu
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include <Logging.h>
9 
10 #include "core/Dispatch.h"
11 #include "core/Dtype.h"
12 #include "core/MemoryManager.h"
13 #include "core/ParallelFor.h"
14 #include "core/SizeVector.h"
15 #include "core/Tensor.h"
16 #include "t/geometry/kernel/GeometryIndexer.h"
17 #include "t/geometry/kernel/GeometryMacros.h"
18 #include "t/geometry/kernel/PointCloud.h"
19 #include "t/geometry/kernel/PointCloudImpl.h"
20 
21 namespace cloudViewer {
22 namespace t {
23 namespace geometry {
24 namespace kernel {
25 namespace pointcloud {
26 
27 void ProjectCUDA(
28  core::Tensor& depth,
29  utility::optional<std::reference_wrapper<core::Tensor>> image_colors,
30  const core::Tensor& points,
31  utility::optional<std::reference_wrapper<const core::Tensor>> colors,
32  const core::Tensor& intrinsics,
33  const core::Tensor& extrinsics,
34  float depth_scale,
35  float depth_max) {
36  const bool has_colors = image_colors.has_value();
37 
38  int64_t n = points.GetLength();
39 
40  const float* points_ptr = points.GetDataPtr<float>();
41  const float* point_colors_ptr =
42  has_colors ? colors.value().get().GetDataPtr<float>() : nullptr;
43 
44  TransformIndexer transform_indexer(intrinsics, extrinsics, 1.0f);
45  NDArrayIndexer depth_indexer(depth, 2);
46 
47  // Pass 1: depth map
48  core::ParallelFor(
49  depth.GetDevice(), n, [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
50  float x = points_ptr[3 * workload_idx + 0];
51  float y = points_ptr[3 * workload_idx + 1];
52  float z = points_ptr[3 * workload_idx + 2];
53 
54  // coordinate in camera (in voxel -> in meter)
55  float xc, yc, zc, u, v;
56  transform_indexer.RigidTransform(x, y, z, &xc, &yc, &zc);
57 
58  // coordinate in image (in pixel)
59  transform_indexer.Project(xc, yc, zc, &u, &v);
60  if (!depth_indexer.InBoundary(u, v) || zc <= 0 ||
61  zc > depth_max) {
62  return;
63  }
64 
65  float* depth_ptr = depth_indexer.GetDataPtr<float>(
66  static_cast<int64_t>(u), static_cast<int64_t>(v));
67  float d = zc * depth_scale;
68  float d_old = atomicExch(depth_ptr, d);
69  if (d_old > 0) {
70  atomicMinf(depth_ptr, d_old);
71  }
72  });
73 
74  // Pass 2: color map
75  if (!has_colors) return;
76 
77  NDArrayIndexer color_indexer(image_colors.value().get(), 2);
78  float precision_bound = depth_scale * 1e-4;
79  core::ParallelFor(
80  depth.GetDevice(), n, [=] CLOUDVIEWER_DEVICE(int64_t workload_idx) {
81  float x = points_ptr[3 * workload_idx + 0];
82  float y = points_ptr[3 * workload_idx + 1];
83  float z = points_ptr[3 * workload_idx + 2];
84 
85  // coordinate in camera (in voxel -> in meter)
86  float xc, yc, zc, u, v;
87  transform_indexer.RigidTransform(x, y, z, &xc, &yc, &zc);
88 
89  // coordinate in image (in pixel)
90  transform_indexer.Project(xc, yc, zc, &u, &v);
91  if (!depth_indexer.InBoundary(u, v) || zc <= 0 ||
92  zc > depth_max) {
93  return;
94  }
95 
96  float dmap = *depth_indexer.GetDataPtr<float>(
97  static_cast<int64_t>(u), static_cast<int64_t>(v));
98  float d = zc * depth_scale;
99  if (d < dmap + precision_bound) {
100  uint8_t* color_ptr = color_indexer.GetDataPtr<uint8_t>(
101  static_cast<int64_t>(u), static_cast<int64_t>(v));
102  color_ptr[0] = static_cast<uint8_t>(
103  point_colors_ptr[3 * workload_idx + 0] * 255.0);
104  color_ptr[1] = static_cast<uint8_t>(
105  point_colors_ptr[3 * workload_idx + 1] * 255.0);
106  color_ptr[2] = static_cast<uint8_t>(
107  point_colors_ptr[3 * workload_idx + 2] * 255.0);
108  }
109  });
110 }
111 
112 } // namespace pointcloud
113 } // namespace kernel
114 } // namespace geometry
115 } // namespace t
116 } // namespace cloudViewer