ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
VoxelBlockGrid.cpp
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 
9 
10 #include <Logging.h>
11 
12 #include <vector>
13 
18 
19 namespace cloudViewer {
20 namespace t {
21 namespace geometry {
22 namespace kernel {
23 namespace voxel_grid {
24 
25 void PointCloudTouch(std::shared_ptr<core::HashMap>& hashmap,
26  const core::Tensor& points,
27  core::Tensor& voxel_block_coords,
28  index_t voxel_grid_resolution,
29  float voxel_size,
30  float sdf_trunc) {
31  if (hashmap->IsCPU()) {
32  PointCloudTouchCPU(hashmap, points, voxel_block_coords,
33  voxel_grid_resolution, voxel_size, sdf_trunc);
34  } else if (hashmap->IsCUDA()) {
35  CUDA_CALL(PointCloudTouchCUDA, hashmap, points, voxel_block_coords,
36  voxel_grid_resolution, voxel_size, sdf_trunc);
37  } else {
38  utility::LogError("Unimplemented device");
39  }
40 }
41 
42 void DepthTouch(std::shared_ptr<core::HashMap>& hashmap,
43  const core::Tensor& depth,
44  const core::Tensor& intrinsic,
45  const core::Tensor& extrinsic,
46  core::Tensor& voxel_block_coords,
47  index_t voxel_grid_resolution,
48  float voxel_size,
49  float sdf_trunc,
50  float depth_scale,
51  float depth_max,
52  index_t stride) {
53  if (hashmap->IsCPU()) {
54  DepthTouchCPU(hashmap, depth, intrinsic, extrinsic, voxel_block_coords,
55  voxel_grid_resolution, voxel_size, sdf_trunc, depth_scale,
56  depth_max, stride);
57  } else if (hashmap->IsCUDA()) {
58  CUDA_CALL(DepthTouchCUDA, hashmap, depth, intrinsic, extrinsic,
59  voxel_block_coords, voxel_grid_resolution, voxel_size,
60  sdf_trunc, depth_scale, depth_max, stride);
61  } else {
62  utility::LogError("Unimplemented device");
63  }
64 }
65 
67  const core::Tensor& block_keys,
68  core::Tensor& voxel_coords,
69  core::Tensor& flattened_indices,
70  index_t block_resolution,
71  float voxel_size) {
72  if (block_keys.IsCPU()) {
74  buf_indices, block_keys, voxel_coords, flattened_indices,
75  block_resolution, voxel_size);
76  } else if (block_keys.IsCUDA()) {
77  CUDA_CALL(GetVoxelCoordinatesAndFlattenedIndicesCUDA, buf_indices,
78  block_keys, voxel_coords, flattened_indices, block_resolution,
79  voxel_size);
80  } else {
81  utility::LogError("Unimplemented device");
82  }
83 }
84 
85 #define DISPATCH_VALUE_DTYPE_TO_TEMPLATE(WEIGHT_DTYPE, COLOR_DTYPE, ...) \
86  [&] { \
87  if (WEIGHT_DTYPE == cloudViewer::core::Float32 && \
88  COLOR_DTYPE == cloudViewer::core::Float32) { \
89  using weight_t = float; \
90  using color_t = float; \
91  return __VA_ARGS__(); \
92  } else if (WEIGHT_DTYPE == cloudViewer::core::UInt16 && \
93  COLOR_DTYPE == cloudViewer::core::UInt16) { \
94  using weight_t = uint16_t; \
95  using color_t = uint16_t; \
96  return __VA_ARGS__(); \
97  } else { \
98  utility::LogError( \
99  "Unsupported value data type combination. Expected " \
100  "(float, float) or (uint16, uint16), but received ({} " \
101  "{}).", \
102  WEIGHT_DTYPE.ToString(), COLOR_DTYPE.ToString()); \
103  } \
104  }()
105 
106 #define DISPATCH_INPUT_DTYPE_TO_TEMPLATE(DEPTH_DTYPE, COLOR_DTYPE, ...) \
107  [&] { \
108  if (DEPTH_DTYPE == cloudViewer::core::Float32 && \
109  COLOR_DTYPE == cloudViewer::core::Float32) { \
110  using input_depth_t = float; \
111  using input_color_t = float; \
112  return __VA_ARGS__(); \
113  } else if (DEPTH_DTYPE == cloudViewer::core::UInt16 && \
114  COLOR_DTYPE == cloudViewer::core::UInt8) { \
115  using input_depth_t = uint16_t; \
116  using input_color_t = uint8_t; \
117  return __VA_ARGS__(); \
118  } else { \
119  utility::LogError( \
120  "Unsupported input data type combination. Expected " \
121  "(float, float) or (uint16, uint8), but received ({} {})", \
122  DEPTH_DTYPE.ToString(), COLOR_DTYPE.ToString()); \
123  } \
124  }()
125 
126 void Integrate(const core::Tensor& depth,
127  const core::Tensor& color,
128  const core::Tensor& block_indices,
129  const core::Tensor& block_keys,
130  TensorMap& block_value_map,
131  const core::Tensor& depth_intrinsic,
132  const core::Tensor& color_intrinsic,
133  const core::Tensor& extrinsic,
134  index_t resolution,
135  float voxel_size,
136  float sdf_trunc,
137  float depth_scale,
138  float depth_max) {
139  using tsdf_t = float;
140  core::Dtype block_weight_dtype = core::Dtype::Float32;
141  core::Dtype block_color_dtype = core::Dtype::Float32;
142  if (block_value_map.Contains("weight")) {
143  block_weight_dtype = block_value_map.at("weight").GetDtype();
144  }
145  if (block_value_map.Contains("color")) {
146  block_color_dtype = block_value_map.at("color").GetDtype();
147  }
148 
149  core::Dtype input_depth_dtype = depth.GetDtype();
150  core::Dtype input_color_dtype = (input_depth_dtype == core::Dtype::Float32)
153  if (color.NumElements() > 0) {
154  input_color_dtype = color.GetDtype();
155  }
156 
157  if (depth.IsCPU()) {
159  input_depth_dtype, input_color_dtype, [&] {
161  block_weight_dtype, block_color_dtype, [&] {
162  IntegrateCPU<input_depth_t, input_color_t,
163  tsdf_t, weight_t, color_t>(
164  depth, color, block_indices, block_keys,
165  block_value_map, depth_intrinsic,
166  color_intrinsic, extrinsic, resolution,
167  voxel_size, sdf_trunc, depth_scale,
168  depth_max);
169  });
170  });
171  } else if (depth.IsCUDA()) {
172 #ifdef BUILD_CUDA_MODULE
174  input_depth_dtype, input_color_dtype, [&] {
176  block_weight_dtype, block_color_dtype, [&] {
177  IntegrateCUDA<input_depth_t, input_color_t,
178  tsdf_t, weight_t, color_t>(
179  depth, color, block_indices, block_keys,
180  block_value_map, depth_intrinsic,
181  color_intrinsic, extrinsic, resolution,
182  voxel_size, sdf_trunc, depth_scale,
183  depth_max);
184  });
185  });
186 #else
187  utility::LogError("Not compiled with CUDA, but CUDA device is used.");
188 #endif
189  } else {
190  utility::LogError("Unimplemented device");
191  }
192 }
193 
194 void EstimateRange(const core::Tensor& block_keys,
195  core::Tensor& range_minmax_map,
196  const core::Tensor& intrinsics,
197  const core::Tensor& extrinsics,
198  int h,
199  int w,
200  int down_factor,
201  int64_t block_resolution,
202  float voxel_size,
203  float depth_min,
204  float depth_max,
205  core::Tensor& fragment_buffer) {
206  static const core::Device host("CPU:0");
207  core::Tensor intrinsics_d = intrinsics.To(host, core::Float64).Contiguous();
208  core::Tensor extrinsics_d = extrinsics.To(host, core::Float64).Contiguous();
209 
210  if (block_keys.IsCPU()) {
211  EstimateRangeCPU(block_keys, range_minmax_map, intrinsics_d,
212  extrinsics_d, h, w, down_factor, block_resolution,
213  voxel_size, depth_min, depth_max, fragment_buffer);
214  } else if (block_keys.IsCUDA()) {
215 #ifdef BUILD_CUDA_MODULE
216  EstimateRangeCUDA(block_keys, range_minmax_map, intrinsics_d,
217  extrinsics_d, h, w, down_factor, block_resolution,
218  voxel_size, depth_min, depth_max, fragment_buffer);
219 #else
220  utility::LogError("Not compiled with CUDA, but CUDA device is used.");
221 #endif
222  } else {
223  utility::LogError("Unimplemented device");
224  }
225 }
226 
227 void RayCast(std::shared_ptr<core::HashMap>& hashmap,
228  const TensorMap& block_value_map,
229  const core::Tensor& range_map,
230  TensorMap& renderings_map,
231  const core::Tensor& intrinsic,
232  const core::Tensor& extrinsic,
233  index_t h,
234  index_t w,
235  index_t block_resolution,
236  float voxel_size,
237  float depth_scale,
238  float depth_min,
239  float depth_max,
240  float weight_threshold,
241  float trunc_voxel_multiplier,
242  int range_map_down_factor) {
243  using tsdf_t = float;
244  core::Dtype block_weight_dtype = core::Dtype::Float32;
245  core::Dtype block_color_dtype = core::Dtype::Float32;
246  if (block_value_map.Contains("weight")) {
247  block_weight_dtype = block_value_map.at("weight").GetDtype();
248  }
249  if (block_value_map.Contains("color")) {
250  block_color_dtype = block_value_map.at("color").GetDtype();
251  }
252 
253  if (hashmap->GetDevice().GetType() == core::Device::DeviceType::CPU) {
255  block_weight_dtype, block_color_dtype, [&] {
256  RayCastCPU<tsdf_t, weight_t, color_t>(
257  hashmap, block_value_map, range_map, renderings_map,
258  intrinsic, extrinsic, h, w, block_resolution,
259  voxel_size, depth_scale, depth_min, depth_max,
260  weight_threshold, trunc_voxel_multiplier,
261  range_map_down_factor);
262  });
263 
264  } else if (hashmap->GetDevice().GetType() ==
266 #ifdef BUILD_CUDA_MODULE
268  block_weight_dtype, block_color_dtype, [&] {
269  RayCastCUDA<tsdf_t, weight_t, color_t>(
270  hashmap, block_value_map, range_map, renderings_map,
271  intrinsic, extrinsic, h, w, block_resolution,
272  voxel_size, depth_scale, depth_min, depth_max,
273  weight_threshold, trunc_voxel_multiplier,
274  range_map_down_factor);
275  });
276 #else
277  utility::LogError("Not compiled with CUDA, but CUDA device is used.");
278 #endif
279  } else {
280  utility::LogError("Unimplemented device");
281  }
282 }
283 
284 void ExtractPointCloud(const core::Tensor& block_indices,
285  const core::Tensor& nb_block_indices,
286  const core::Tensor& nb_block_masks,
287  const core::Tensor& block_keys,
288  const TensorMap& block_value_map,
292  index_t block_resolution,
293  float voxel_size,
294  float weight_threshold,
295  int& valid_size) {
296  using tsdf_t = float;
297  core::Dtype block_weight_dtype = core::Dtype::Float32;
298  core::Dtype block_color_dtype = core::Dtype::Float32;
299  if (block_value_map.Contains("weight")) {
300  block_weight_dtype = block_value_map.at("weight").GetDtype();
301  }
302  if (block_value_map.Contains("color")) {
303  block_color_dtype = block_value_map.at("color").GetDtype();
304  }
305 
306  if (block_indices.IsCPU()) {
308  block_weight_dtype, block_color_dtype, [&] {
309  ExtractPointCloudCPU<tsdf_t, weight_t, color_t>(
310  block_indices, nb_block_indices, nb_block_masks,
311  block_keys, block_value_map, points, normals,
312  colors, block_resolution, voxel_size,
313  weight_threshold, valid_size);
314  });
315 
316  } else if (block_indices.IsCUDA()) {
317 #ifdef BUILD_CUDA_MODULE
319  block_weight_dtype, block_color_dtype, [&] {
320  ExtractPointCloudCUDA<tsdf_t, weight_t, color_t>(
321  block_indices, nb_block_indices, nb_block_masks,
322  block_keys, block_value_map, points, normals,
323  colors, block_resolution, voxel_size,
324  weight_threshold, valid_size);
325  });
326 #else
327  utility::LogError("Not compiled with CUDA, but CUDA device is used.");
328 #endif
329  } else {
330  utility::LogError("Unimplemented device");
331  }
332 }
333 
334 void ExtractTriangleMesh(const core::Tensor& block_indices,
335  const core::Tensor& inv_block_indices,
336  const core::Tensor& nb_block_indices,
337  const core::Tensor& nb_block_masks,
338  const core::Tensor& block_keys,
339  const TensorMap& block_value_map,
340  core::Tensor& vertices,
341  core::Tensor& triangles,
342  core::Tensor& vertex_normals,
343  core::Tensor& vertex_colors,
344  index_t block_resolution,
345  float voxel_size,
346  float weight_threshold,
347  int& vertex_count) {
348  using tsdf_t = float;
349  core::Dtype block_weight_dtype = core::Dtype::Float32;
350  core::Dtype block_color_dtype = core::Dtype::Float32;
351  if (block_value_map.Contains("weight")) {
352  block_weight_dtype = block_value_map.at("weight").GetDtype();
353  }
354  if (block_value_map.Contains("color")) {
355  block_color_dtype = block_value_map.at("color").GetDtype();
356  }
357 
358  if (block_indices.IsCPU()) {
360  block_weight_dtype, block_color_dtype, [&] {
361  ExtractTriangleMeshCPU<tsdf_t, weight_t, color_t>(
362  block_indices, inv_block_indices, nb_block_indices,
363  nb_block_masks, block_keys, block_value_map,
364  vertices, triangles, vertex_normals, vertex_colors,
365  block_resolution, voxel_size, weight_threshold,
366  vertex_count);
367  });
368  } else if (block_indices.IsCUDA()) {
369 #ifdef BUILD_CUDA_MODULE
371  block_weight_dtype, block_color_dtype, [&] {
372  ExtractTriangleMeshCUDA<tsdf_t, weight_t, color_t>(
373  block_indices, inv_block_indices, nb_block_indices,
374  nb_block_masks, block_keys, block_value_map,
375  vertices, triangles, vertex_normals, vertex_colors,
376  block_resolution, voxel_size, weight_threshold,
377  vertex_count);
378  });
379 #else
380  utility::LogError("Not compiled with CUDA, but CUDA device is used.");
381 #endif
382  } else {
383  utility::LogError("Unimplemented device");
384  }
385 }
386 
387 } // namespace voxel_grid
388 } // namespace kernel
389 } // namespace geometry
390 } // namespace t
391 } // namespace cloudViewer
Common CUDA utilities.
#define CUDA_CALL(cuda_function,...)
Definition: CUDAUtils.h:49
int points
math::float4 color
size_t stride
static const Dtype UInt8
Definition: Dtype.h:30
static const Dtype Float32
Definition: Dtype.h:24
bool IsCUDA() const
Definition: Device.h:99
bool IsCPU() const
Definition: Device.h:95
Tensor Contiguous() const
Definition: Tensor.cpp:772
Dtype GetDtype() const
Definition: Tensor.h:1164
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
bool Contains(const std::string &key) const
Definition: TensorMap.h:187
double colors[3]
double normals[3]
#define LogError(...)
Definition: Logging.h:60
#define DISPATCH_INPUT_DTYPE_TO_TEMPLATE(DEPTH_DTYPE, COLOR_DTYPE,...)
#define DISPATCH_VALUE_DTYPE_TO_TEMPLATE(WEIGHT_DTYPE, COLOR_DTYPE,...)
const Dtype Float64
Definition: Dtype.cpp:43
void Integrate(const core::Tensor &depth, const core::Tensor &color, const core::Tensor &block_indices, const core::Tensor &block_keys, TensorMap &block_value_map, const core::Tensor &depth_intrinsic, const core::Tensor &color_intrinsic, const core::Tensor &extrinsic, index_t resolution, float voxel_size, float sdf_trunc, float depth_scale, float depth_max)
void DepthTouchCPU(std::shared_ptr< core::HashMap > &hashmap, const core::Tensor &depth, const core::Tensor &intrinsic, const core::Tensor &extrinsic, core::Tensor &voxel_block_coords, index_t voxel_grid_resolution, float voxel_size, float sdf_trunc, float depth_scale, float depth_max, index_t stride)
void PointCloudTouchCPU(std::shared_ptr< core::HashMap > &hashmap, const core::Tensor &points, core::Tensor &voxel_block_coords, index_t voxel_grid_resolution, float voxel_size, float sdf_trunc)
CPU.
void GetVoxelCoordinatesAndFlattenedIndices(const core::Tensor &buf_indices, const core::Tensor &block_keys, core::Tensor &voxel_coords, core::Tensor &flattened_indices, index_t block_resolution, float voxel_size)
void EstimateRangeCPU(const core::Tensor &block_keys, core::Tensor &range_minmax_map, const core::Tensor &intrinsics, const core::Tensor &extrinsics, int h, int w, int down_factor, int64_t block_resolution, float voxel_size, float depth_min, float depth_max, core::Tensor &fragment_buffer)
void PointCloudTouch(std::shared_ptr< core::HashMap > &hashmap, const core::Tensor &points, core::Tensor &voxel_block_coords, index_t voxel_grid_resolution, float voxel_size, float sdf_trunc)
void ExtractPointCloud(const core::Tensor &block_indices, const core::Tensor &nb_block_indices, const core::Tensor &nb_block_masks, const core::Tensor &block_keys, const TensorMap &block_value_map, core::Tensor &points, core::Tensor &normals, core::Tensor &colors, index_t block_resolution, float voxel_size, float weight_threshold, int &valid_size)
void RayCast(std::shared_ptr< core::HashMap > &hashmap, const TensorMap &block_value_map, const core::Tensor &range_map, TensorMap &renderings_map, const core::Tensor &intrinsic, const core::Tensor &extrinsic, index_t h, index_t w, index_t block_resolution, float voxel_size, float depth_scale, float depth_min, float depth_max, float weight_threshold, float trunc_voxel_multiplier, int range_map_down_factor)
void DepthTouch(std::shared_ptr< core::HashMap > &hashmap, const core::Tensor &depth, const core::Tensor &intrinsic, const core::Tensor &extrinsic, core::Tensor &voxel_block_coords, index_t voxel_grid_resolution, float voxel_size, float sdf_trunc, float depth_scale, float depth_max, index_t stride)
void IntegrateCPU(const core::Tensor &depth, const core::Tensor &color, const core::Tensor &block_indices, const core::Tensor &block_keys, TensorMap &block_value_map, const core::Tensor &depth_intrinsic, const core::Tensor &color_intrinsic, const core::Tensor &extrinsic, index_t resolution, float voxel_size, float sdf_trunc, float depth_scale, float depth_max)
void GetVoxelCoordinatesAndFlattenedIndicesCPU(const core::Tensor &buf_indices, const core::Tensor &block_keys, core::Tensor &voxel_coords, core::Tensor &flattened_indices, index_t block_resolution, float voxel_size)
void ExtractTriangleMesh(const core::Tensor &block_indices, const core::Tensor &inv_block_indices, const core::Tensor &nb_block_indices, const core::Tensor &nb_block_masks, const core::Tensor &block_keys, const TensorMap &block_value_map, core::Tensor &vertices, core::Tensor &triangles, core::Tensor &vertex_normals, core::Tensor &vertex_colors, index_t block_resolution, float voxel_size, float weight_threshold, int &vertex_count)
void EstimateRange(const core::Tensor &block_keys, core::Tensor &range_minmax_map, const core::Tensor &intrinsics, const core::Tensor &extrinsics, int h, int w, int down_factor, int64_t block_resolution, float voxel_size, float depth_min, float depth_max, core::Tensor &fragment_buffer)
Generic file read and write utility for python interface.