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 <FileSystem.h>
11 
18 
19 namespace cloudViewer {
20 namespace t {
21 namespace geometry {
22 
23 static std::pair<core::Tensor, core::Tensor> BufferRadiusNeighbors(
24  std::shared_ptr<core::HashMap> &hashmap,
25  const core::Tensor &active_buf_indices) {
26  // Fixed radius search for spatially hashed voxel blocks.
27  // A generalization will be implementing dense/sparse fixed radius
28  // search with coordinates as hashmap keys.
29  core::Tensor key_buffer_int3_tensor = hashmap->GetKeyTensor();
30 
31  core::Tensor active_keys = key_buffer_int3_tensor.IndexGet(
32  {active_buf_indices.To(core::Int64)});
33  int64_t n = active_keys.GetShape()[0];
34 
35  // Fill in radius nearest neighbors.
36  core::Tensor keys_nb({27, n, 3}, core::Int32, hashmap->GetDevice());
37  for (int nb = 0; nb < 27; ++nb) {
38  int dz = nb / 9;
39  int dy = (nb % 9) / 3;
40  int dx = nb % 3;
41  core::Tensor dt =
42  core::Tensor(std::vector<int>{dx - 1, dy - 1, dz - 1}, {1, 3},
43  core::Int32, hashmap->GetDevice());
44  keys_nb[nb] = active_keys + dt;
45  }
46  keys_nb = keys_nb.View({27 * n, 3});
47 
48  core::Tensor buf_indices_nb, masks_nb;
49  hashmap->Find(keys_nb, buf_indices_nb, masks_nb);
50  return std::make_pair(buf_indices_nb.View({27, n, 1}),
51  masks_nb.View({27, n, 1}));
52 }
53 
55  const core::HashMap &block_hashmap,
56  std::unordered_map<std::string, int> name_attr_map) {
57  TensorMap tensor_map("tsdf");
58  for (auto &v : name_attr_map) {
59  std::string name = v.first;
60  int buf_idx = v.second;
61  tensor_map[name] = block_hashmap.GetValueTensor(buf_idx);
62  }
63  return tensor_map;
64 }
65 
67  const std::vector<std::string> &attr_names,
68  const std::vector<core::Dtype> &attr_dtypes,
69  const std::vector<core::SizeVector> &attr_channels,
70  float voxel_size,
71  int64_t block_resolution,
72  int64_t block_count,
73  const core::Device &device,
74  const core::HashBackendType &backend)
75  : voxel_size_(voxel_size), block_resolution_(block_resolution) {
76  // Sanity check
77  if (voxel_size <= 0) {
78  utility::LogError("voxel size must be positive, but got {}",
79  voxel_size);
80  }
81  if (block_resolution <= 0) {
82  utility::LogError("block resolution must be positive, but got {}",
83  block_resolution);
84  }
85 
86  // Check property lengths
87  size_t n_attrs = attr_names.size();
88  if (attr_dtypes.size() != n_attrs) {
90  "Number of attribute dtypes ({}) mismatch with names ({}).",
91  attr_dtypes.size(), n_attrs);
92  }
93  if (attr_channels.size() != n_attrs) {
95  "Number of attribute channels ({}) mismatch with names ({}).",
96  attr_channels.size(), n_attrs);
97  }
98 
99  // Specify block element shapes and attribute names.
100  std::vector<core::SizeVector> attr_element_shapes;
101  core::SizeVector block_shape{block_resolution, block_resolution,
102  block_resolution};
103  for (size_t i = 0; i < n_attrs; ++i) {
104  // Construct element shapes.
105  core::SizeVector attr_channel = attr_channels[i];
106  core::SizeVector block_shape_copy = block_shape;
107  block_shape_copy.insert(block_shape_copy.end(), attr_channel.begin(),
108  attr_channel.end());
109  attr_element_shapes.emplace_back(block_shape_copy);
110 
111  // Used for easier accessing via attribute names.
112  name_attr_map_[attr_names[i]] = i;
113  }
114 
115  block_hashmap_ = std::make_shared<core::HashMap>(
116  block_count, core::Int32, core::SizeVector{3}, attr_dtypes,
117  attr_element_shapes, device, backend);
118 }
119 
120 core::Tensor VoxelBlockGrid::GetAttribute(const std::string &attr_name) const {
121  AssertInitialized();
122  if (name_attr_map_.count(attr_name) == 0) {
123  utility::LogWarning("Attribute {} not found, return empty tensor.",
124  attr_name);
125  return core::Tensor();
126  }
127  int buffer_idx = name_attr_map_.at(attr_name);
128  return block_hashmap_->GetValueTensor(buffer_idx);
129 }
130 
132  const core::Tensor &voxel_indices) const {
133  AssertInitialized();
134  core::Tensor key_tensor = block_hashmap_->GetKeyTensor();
135 
136  core::Tensor voxel_coords =
137  key_tensor.IndexGet({voxel_indices[0]}).T().To(core::Int64) *
138  block_resolution_;
139  voxel_coords[0] += voxel_indices[1];
140  voxel_coords[1] += voxel_indices[2];
141  voxel_coords[2] += voxel_indices[3];
142 
143  return voxel_coords;
144 }
145 
147  const core::Tensor &buf_indices) const {
148  AssertInitialized();
149  core::Device device = block_hashmap_->GetDevice();
150 
151  int64_t n_blocks = buf_indices.GetLength();
152 
153  int64_t resolution = block_resolution_;
154  int64_t resolution2 = resolution * resolution;
155  int64_t resolution3 = resolution2 * resolution;
156 
157  // Non-kernel version.
159  core::Tensor linear_coordinates = core::Tensor::Arange(
160  0, n_blocks * resolution3, 1, core::Int64, device);
161 
162  core::Tensor block_idx = linear_coordinates / resolution3;
163  core::Tensor remainder = linear_coordinates - block_idx * resolution3;
164 
166  core::Tensor voxel_z = remainder / resolution2;
167  remainder = remainder - voxel_z * resolution2;
168  core::Tensor voxel_y = remainder / resolution;
169  core::Tensor voxel_x = remainder - voxel_y * resolution;
170 
171  core::Tensor voxel_indices = core::Tensor({4, n_blocks * resolution3},
172  core::Dtype::Int64, device);
173  voxel_indices[0] = buf_indices.IndexGet({block_idx}).To(core::Dtype::Int64);
174  voxel_indices[1] = voxel_x;
175  voxel_indices[2] = voxel_y;
176  voxel_indices[3] = voxel_z;
177 
178  return voxel_indices;
179 }
180 
182  AssertInitialized();
183  return GetVoxelIndices(block_hashmap_->GetActiveIndices());
184 }
185 
186 std::pair<core::Tensor, core::Tensor>
188  AssertInitialized();
190  block_hashmap_->GetActiveIndices());
191 }
192 
193 std::pair<core::Tensor, core::Tensor>
195  const core::Tensor &buf_indices) {
196  AssertInitialized();
197  // (N x resolution^3, 3) Float32; (N x resolution^3, 1) Int64
198  int64_t n = buf_indices.GetLength();
199 
200  int64_t resolution3 =
201  block_resolution_ * block_resolution_ * block_resolution_;
202 
203  core::Device device = block_hashmap_->GetDevice();
204  core::Tensor voxel_coords({n * resolution3, 3}, core::Float32, device);
205  core::Tensor flattened_indices({n * resolution3}, core::Int64, device);
206 
208  buf_indices, block_hashmap_->GetKeyTensor(), voxel_coords,
209  flattened_indices, block_resolution_, voxel_size_);
210  return std::make_pair(voxel_coords, flattened_indices);
211 }
212 
214  const Image &depth,
215  const core::Tensor &intrinsic,
216  const core::Tensor &extrinsic,
217  float depth_scale,
218  float depth_max,
219  float trunc_voxel_multiplier) {
220  AssertInitialized();
221  CheckDepthTensor(depth.AsTensor());
222  CheckIntrinsicTensor(intrinsic);
223  CheckExtrinsicTensor(extrinsic);
224 
225  const int64_t down_factor = 4;
226  const int64_t est_sample_multiplier = 4;
227  if (frustum_hashmap_ == nullptr) {
228  int64_t capacity = (depth.GetCols() / down_factor) *
229  (depth.GetRows() / down_factor) *
230  est_sample_multiplier;
231  frustum_hashmap_ = std::make_shared<core::HashMap>(
233  core::SizeVector{1}, block_hashmap_->GetDevice());
234  } else {
235  frustum_hashmap_->Clear();
236  }
237 
238  core::Tensor block_coords;
239  kernel::voxel_grid::DepthTouch(frustum_hashmap_, depth.AsTensor(),
240  intrinsic, extrinsic, block_coords,
241  block_resolution_, voxel_size_,
242  voxel_size_ * trunc_voxel_multiplier,
243  depth_scale, depth_max, down_factor);
244 
245  return block_coords;
246 }
247 
249  const PointCloud &pcd, float trunc_voxel_multiplier) {
250  AssertInitialized();
251  core::Tensor positions = pcd.GetPointPositions();
252 
253  const int64_t est_neighbor_multiplier = 8;
254  if (frustum_hashmap_ == nullptr) {
255  int64_t capacity = positions.GetLength() * est_neighbor_multiplier;
256  frustum_hashmap_ = std::make_shared<core::HashMap>(
258  core::SizeVector{1}, block_hashmap_->GetDevice());
259  } else {
260  frustum_hashmap_->Clear();
261  }
262 
263  core::Tensor block_coords;
265  frustum_hashmap_, positions, block_coords, block_resolution_,
266  voxel_size_, voxel_size_ * trunc_voxel_multiplier);
267  return block_coords;
268 }
269 
270 void VoxelBlockGrid::Integrate(const core::Tensor &block_coords,
271  const Image &depth,
272  const core::Tensor &intrinsic,
273  const core::Tensor &extrinsic,
274  float depth_scale,
275  float depth_max,
276  float trunc_voxel_multiplier) {
277  Integrate(block_coords, depth, Image(), intrinsic, intrinsic, extrinsic,
278  depth_scale, depth_max, trunc_voxel_multiplier);
279 }
280 
281 void VoxelBlockGrid::Integrate(const core::Tensor &block_coords,
282  const Image &depth,
283  const Image &color,
284  const core::Tensor &intrinsic,
285  const core::Tensor &extrinsic,
286  float depth_scale,
287  float depth_max,
288  float trunc_voxel_multiplier) {
289  Integrate(block_coords, depth, color, intrinsic, intrinsic, extrinsic,
290  depth_scale, depth_max, trunc_voxel_multiplier);
291 }
292 
293 void VoxelBlockGrid::Integrate(const core::Tensor &block_coords,
294  const Image &depth,
295  const Image &color,
296  const core::Tensor &depth_intrinsic,
297  const core::Tensor &color_intrinsic,
298  const core::Tensor &extrinsic,
299  float depth_scale,
300  float depth_max,
301  float trunc_voxel_multiplier) {
302  AssertInitialized();
303  bool integrate_color = color.AsTensor().NumElements() > 0;
304 
305  CheckBlockCoordinates(block_coords);
306  CheckDepthTensor(depth.AsTensor());
307  if (integrate_color) {
308  CheckColorTensor(color.AsTensor());
309  }
310  CheckIntrinsicTensor(depth_intrinsic);
311  CheckIntrinsicTensor(color_intrinsic);
312  CheckExtrinsicTensor(extrinsic);
313 
314  core::Tensor buf_indices, masks;
315  block_hashmap_->Activate(block_coords, buf_indices, masks);
316  block_hashmap_->Find(block_coords, buf_indices, masks);
317 
318  core::Tensor block_keys = block_hashmap_->GetKeyTensor();
319  TensorMap block_value_map =
320  ConstructTensorMap(*block_hashmap_, name_attr_map_);
321 
323  depth.AsTensor(), color.AsTensor(), buf_indices, block_keys,
324  block_value_map, depth_intrinsic, color_intrinsic, extrinsic,
325  block_resolution_, voxel_size_,
326  voxel_size_ * trunc_voxel_multiplier, depth_scale, depth_max);
327 }
328 
330  const core::Tensor &intrinsic,
331  const core::Tensor &extrinsic,
332  int width,
333  int height,
334  const std::vector<std::string> attrs,
335  float depth_scale,
336  float depth_min,
337  float depth_max,
338  float weight_threshold,
339  float trunc_voxel_multiplier,
340  int range_map_down_factor) {
341  AssertInitialized();
342  CheckBlockCoordinates(block_coords);
343  CheckIntrinsicTensor(intrinsic);
344  CheckExtrinsicTensor(extrinsic);
345 
346  // Extrinsic: world to camera -> pose: camera to world
347  core::Device device = block_hashmap_->GetDevice();
348 
349  core::Tensor range_minmax_map;
351  block_coords, range_minmax_map, intrinsic, extrinsic, height, width,
352  range_map_down_factor, block_resolution_, voxel_size_, depth_min,
353  depth_max, fragment_buffer_);
354 
355  static const std::unordered_map<std::string, int> kAttrChannelMap = {
356  // Conventional rendering
357  {"vertex", 3},
358  {"normal", 3},
359  {"depth", 1},
360  {"color", 3},
361  // Diff rendering
362  // Each pixel corresponds to info at 8 neighbor grid points
363  {"index", 8},
364  {"mask", 8},
365  {"interp_ratio", 8},
366  {"interp_ratio_dx", 8},
367  {"interp_ratio_dy", 8},
368  {"interp_ratio_dz", 8}};
369 
370  auto get_dtype = [&](const std::string &attr_name) -> core::Dtype {
371  if (attr_name == "mask") {
372  return core::Dtype::Bool;
373  } else if (attr_name == "index") {
374  return core::Dtype::Int64;
375  } else {
376  return core::Dtype::Float32;
377  }
378  };
379 
380  TensorMap renderings_map("range");
381  renderings_map["range"] = range_minmax_map;
382  for (const auto &attr : attrs) {
383  if (kAttrChannelMap.count(attr) == 0) {
385  "Unsupported attribute {}, please implement customized ray "
386  "casting.");
387  }
388  int channel = kAttrChannelMap.at(attr);
389  core::Dtype dtype = get_dtype(attr);
390  renderings_map[attr] =
391  core::Tensor({height, width, channel}, dtype, device);
392  }
393 
394  TensorMap block_value_map =
395  ConstructTensorMap(*block_hashmap_, name_attr_map_);
397  block_hashmap_, block_value_map, range_minmax_map, renderings_map,
398  intrinsic, extrinsic, height, width, block_resolution_, voxel_size_,
399  depth_scale, depth_min, depth_max, weight_threshold,
400  trunc_voxel_multiplier, range_map_down_factor);
401 
402  return renderings_map;
403 }
404 
406  int estimated_point_number) {
407  AssertInitialized();
408  core::Tensor active_buf_indices;
409  block_hashmap_->GetActiveIndices(active_buf_indices);
410 
411  core::Tensor active_nb_buf_indices, active_nb_masks;
412  std::tie(active_nb_buf_indices, active_nb_masks) =
413  BufferRadiusNeighbors(block_hashmap_, active_buf_indices);
414 
415  // Extract points around zero-crossings.
417 
418  core::Tensor block_keys = block_hashmap_->GetKeyTensor();
419  TensorMap block_value_map =
420  ConstructTensorMap(*block_hashmap_, name_attr_map_);
422  active_buf_indices, active_nb_buf_indices, active_nb_masks,
423  block_keys, block_value_map, points, normals, colors,
424  block_resolution_, voxel_size_, weight_threshold,
425  estimated_point_number);
426 
427  auto pcd = PointCloud(points.Slice(0, 0, estimated_point_number));
428  pcd.SetPointNormals(normals.Slice(0, 0, estimated_point_number));
429 
430  if (colors.GetLength() == normals.GetLength()) {
431  pcd.SetPointColors(colors.Slice(0, 0, estimated_point_number));
432  }
433 
434  return pcd;
435 }
436 
438  int estimated_vertex_number) {
439  AssertInitialized();
440  core::Tensor active_buf_indices_i32 = block_hashmap_->GetActiveIndices();
441  core::Tensor active_nb_buf_indices, active_nb_masks;
442  std::tie(active_nb_buf_indices, active_nb_masks) =
443  BufferRadiusNeighbors(block_hashmap_, active_buf_indices_i32);
444 
445  core::Device device = block_hashmap_->GetDevice();
446  // Map active indices to [0, num_blocks] to be allocated for surface mesh.
447  int64_t num_blocks = block_hashmap_->Size();
448  core::Tensor inverse_index_map({block_hashmap_->GetCapacity()}, core::Int32,
449  device);
450  core::Tensor iota_map =
451  core::Tensor::Arange(0, num_blocks, 1, core::Int32, device);
452  inverse_index_map.IndexSet({active_buf_indices_i32.To(core::Int64)},
453  iota_map);
454 
455  core::Tensor vertices, triangles, vertex_normals, vertex_colors;
456 
457  core::Tensor block_keys = block_hashmap_->GetKeyTensor();
458  TensorMap block_value_map =
459  ConstructTensorMap(*block_hashmap_, name_attr_map_);
461  active_buf_indices_i32, inverse_index_map, active_nb_buf_indices,
462  active_nb_masks, block_keys, block_value_map, vertices, triangles,
463  vertex_normals, vertex_colors, block_resolution_, voxel_size_,
464  weight_threshold, estimated_vertex_number);
465 
466  TriangleMesh mesh(vertices, triangles);
467  mesh.SetVertexNormals(vertex_normals);
468  if (vertex_colors.GetLength() == vertices.GetLength()) {
469  mesh.SetVertexColors(vertex_colors);
470  }
471 
472  return mesh;
473 }
474 
475 void VoxelBlockGrid::Save(const std::string &file_name) const {
476  AssertInitialized();
477  // TODO(wei): provide 'GetActiveKeyValues' functionality.
478  core::Tensor keys = block_hashmap_->GetKeyTensor();
479  std::vector<core::Tensor> values = block_hashmap_->GetValueTensors();
480 
481  core::Device host("CPU:0");
482 
483  core::Tensor active_buf_indices_i32 = block_hashmap_->GetActiveIndices();
484  core::Tensor active_indices = active_buf_indices_i32.To(core::Int64);
485 
486  std::unordered_map<std::string, core::Tensor> output;
487 
488  // Save name attributes
489  output.emplace("voxel_size", core::Tensor(std::vector<float>{voxel_size_},
490  {1}, core::Float32, host));
491  output.emplace("block_resolution",
492  core::Tensor(std::vector<int64_t>{block_resolution_}, {1},
493  core::Int64, host));
494  // Placeholder
495  output.emplace(block_hashmap_->GetDevice().ToString(),
497 
498  for (auto &it : name_attr_map_) {
499  // Workaround, as we don't support char tensors now.
500  output.emplace(fmt::format("attr_name_{}", it.first),
501  core::Tensor(std::vector<int>{it.second}, {1},
502  core::Int32, host));
503  }
504 
505  // Save keys
506  core::Tensor active_keys = keys.IndexGet({active_indices}).To(host);
507  output.emplace("key", active_keys);
508 
509  // Save SoA values and name attributes
510  for (auto &it : name_attr_map_) {
511  int value_id = it.second;
512  core::Tensor active_value_i =
513  values[value_id].IndexGet({active_indices}).To(host);
514  output.emplace(fmt::format("value_{:03d}", value_id), active_value_i);
515  }
516 
517  std::string ext =
519  if (ext != "npz") {
521  "File name for a voxel grid should be with the extension "
522  ".npz. Saving to {}.npz",
523  file_name);
524  t::io::WriteNpz(file_name + ".npz", output);
525  } else {
526  t::io::WriteNpz(file_name, output);
527  }
528 }
529 
531  if (!copy && block_hashmap_->GetDevice() == device) {
532  return *this;
533  }
534 
535  auto device_hashmap =
536  std::make_shared<core::HashMap>(this->block_hashmap_->To(device));
537  return VoxelBlockGrid(voxel_size_, block_resolution_, device_hashmap,
538  name_attr_map_);
539 }
540 
541 VoxelBlockGrid VoxelBlockGrid::Load(const std::string &file_name) {
542  std::unordered_map<std::string, core::Tensor> tensor_map =
543  t::io::ReadNpz(file_name);
544 
545  std::string prefix = "attr_name_";
546  std::unordered_map<int, std::string> inv_attr_map;
547 
548  std::string kCPU = "CPU";
549  std::string kCUDA = "CUDA";
550 
551  std::string device_str = "CPU:0";
552  for (auto &it : tensor_map) {
553  if (!it.first.compare(0, prefix.size(), prefix)) {
554  int value_id = it.second[0].Item<int>();
555  inv_attr_map.emplace(value_id, it.first.substr(prefix.size()));
556  }
557  if (!it.first.compare(0, kCPU.size(), kCPU) ||
558  !it.first.compare(0, kCUDA.size(), kCUDA)) {
559  device_str = it.first;
560  }
561  }
562  if (inv_attr_map.size() == 0) {
564  "Attribute names not found, not a valid file for voxel block "
565  "grids.");
566  }
567 
568  core::Device device(device_str);
569 
570  std::vector<std::string> attr_names(inv_attr_map.size());
571 
572  std::vector<core::Tensor> soa_value_tensor(inv_attr_map.size());
573  std::vector<core::Dtype> attr_dtypes(inv_attr_map.size());
574  std::vector<core::SizeVector> attr_channels(inv_attr_map.size());
575 
576  // Not an ideal way to use an unordered map. Assume all the indices are
577  // stored.
578  for (auto &v : inv_attr_map) {
579  int value_id = v.first;
580  attr_names[value_id] = v.second;
581 
582  core::Tensor value_i =
583  tensor_map.at(fmt::format("value_{:03d}", value_id));
584 
585  soa_value_tensor[value_id] = value_i.To(device);
586  attr_dtypes[value_id] = value_i.GetDtype();
587 
588  core::SizeVector value_i_shape = value_i.GetShape();
589  // capacity, res, res, res
590  value_i_shape.erase(value_i_shape.begin(), value_i_shape.begin() + 4);
591  attr_channels[value_id] = value_i_shape;
592  }
593 
594  core::Tensor keys = tensor_map.at("key").To(device);
595  float voxel_size = tensor_map.at("voxel_size")[0].Item<float>();
596  int block_resolution = tensor_map.at("block_resolution")[0].Item<int64_t>();
597 
598  VoxelBlockGrid vbg(attr_names, attr_dtypes, attr_channels, voxel_size,
599  block_resolution, keys.GetLength(), device);
600  auto block_hashmap = vbg.GetHashMap();
601  block_hashmap.Insert(keys, soa_value_tensor);
602  return vbg;
603 }
604 
605 void VoxelBlockGrid::AssertInitialized() const {
606  if (block_hashmap_ == nullptr) {
607  utility::LogError("VoxelBlockGrid not initialized.");
608  }
609 }
610 
611 } // namespace geometry
612 } // namespace t
613 } // namespace cloudViewer
filament::Texture::InternalFormat format
int width
std::string name
int height
int points
math::float4 color
bool copy
Definition: VtkUtils.cpp:74
static const Dtype UInt8
Definition: Dtype.h:30
static const Dtype Float32
Definition: Dtype.h:24
static const Dtype Int64
Definition: Dtype.h:29
static const Dtype Bool
Definition: Dtype.h:34
Tensor GetValueTensor(size_t index=0) const
Definition: HashMap.cpp:294
iterator erase(const_iterator CI)
Definition: SmallVector.h:779
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:853
static Tensor Arange(const Scalar start, const Scalar stop, const Scalar step=1, const Dtype dtype=core::Int64, const Device &device=core::Device("CPU:0"))
Create a 1D tensor with evenly spaced values in the given interval.
Definition: Tensor.cpp:436
int64_t GetLength() const
Definition: Tensor.h:1125
Dtype GetDtype() const
Definition: Tensor.h:1164
Tensor IndexGet(const std::vector< Tensor > &index_tensors) const
Advanced indexing getter. This will always allocate a new Tensor.
Definition: Tensor.cpp:905
static Tensor Zeros(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor fill with zeros.
Definition: Tensor.cpp:406
Tensor View(const SizeVector &dst_shape) const
Definition: Tensor.cpp:721
SizeVector GetShape() const
Definition: Tensor.h:1127
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
The Image class stores image with customizable rows, cols, channels, dtype and device.
Definition: Image.h:29
core::Tensor AsTensor() const
Returns the underlying Tensor of the Image.
Definition: Image.h:124
int64_t GetCols() const
Get the number of columns of the image.
Definition: Image.h:87
int64_t GetRows() const
Get the number of rows of the image.
Definition: Image.h:84
A point cloud contains a list of 3D points.
Definition: PointCloud.h:82
core::Tensor & GetPointPositions()
Get the value of the "positions" attribute. Convenience function.
Definition: PointCloud.h:124
A triangle mesh contains vertices and triangles.
Definition: TriangleMesh.h:98
void SetVertexNormals(const core::Tensor &value)
Definition: TriangleMesh.h:275
void SetVertexColors(const core::Tensor &value)
Definition: TriangleMesh.h:268
PointCloud ExtractPointCloud(float weight_threshold=3.0f, int estimated_point_number=-1)
void Save(const std::string &file_name) const
Save a voxel block grid to a .npz file.
VoxelBlockGrid To(const core::Device &device, bool copy=false) const
Convert the hash map to another device.
static VoxelBlockGrid Load(const std::string &file_name)
Load a voxel block grid from a .npz file.
TensorMap RayCast(const core::Tensor &block_coords, const core::Tensor &intrinsic, const core::Tensor &extrinsic, int width, int height, const std::vector< std::string > attrs={"depth", "color"}, float depth_scale=1000.0f, float depth_min=0.1f, float depth_max=3.0f, float weight_threshold=3.0f, float trunc_voxel_multiplier=8.0f, int range_map_down_factor=8)
core::Tensor GetVoxelIndices() const
Get all active voxel indices.
core::Tensor GetVoxelCoordinates(const core::Tensor &voxel_indices) const
std::pair< core::Tensor, core::Tensor > GetVoxelCoordinatesAndFlattenedIndices()
TriangleMesh ExtractTriangleMesh(float weight_threshold=3.0f, int estimated_vertex_numer=-1)
void Integrate(const core::Tensor &block_coords, const Image &depth, const Image &color, const core::Tensor &depth_intrinsic, const core::Tensor &color_intrinsic, const core::Tensor &extrinsic, float depth_scale=1000.0f, float depth_max=3.0f, float trunc_voxel_multiplier=8.0f)
core::Tensor GetAttribute(const std::string &attr_name) const
core::Tensor GetUniqueBlockCoordinates(const Image &depth, const core::Tensor &intrinsic, const core::Tensor &extrinsic, float depth_scale=1000.0f, float depth_max=3.0f, float trunc_voxel_multiplier=8.0)
double colors[3]
double normals[3]
#define LogWarning(...)
Definition: Logging.h:72
#define LogError(...)
Definition: Logging.h:60
const Dtype Int64
Definition: Dtype.cpp:47
CLOUDVIEWER_HOST_DEVICE Pair< First, Second > make_pair(const First &_first, const Second &_second)
Definition: SlabTraits.h:49
const Dtype Int32
Definition: Dtype.cpp:46
const Dtype Float32
Definition: Dtype.cpp:42
::ccPointCloud PointCloud
Definition: PointCloud.h:19
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 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 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 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)
void CheckDepthTensor(const core::Tensor &depth)
Definition: Utility.h:17
void CheckExtrinsicTensor(const core::Tensor &extrinsic)
Definition: Utility.h:53
void CheckIntrinsicTensor(const core::Tensor &intrinsic)
Definition: Utility.h:37
void CheckBlockCoordinates(const core::Tensor &block_coords)
Definition: Utility.h:69
static TensorMap ConstructTensorMap(const core::HashMap &block_hashmap, std::unordered_map< std::string, int > name_attr_map)
static std::pair< core::Tensor, core::Tensor > BufferRadiusNeighbors(std::shared_ptr< core::HashMap > &hashmap, const core::Tensor &active_buf_indices)
void CheckColorTensor(const core::Tensor &color)
Definition: Utility.h:27
std::unordered_map< std::string, core::Tensor > ReadNpz(const std::string &file_name)
Definition: NumpyIO.cpp:675
void WriteNpz(const std::string &file_name, const std::unordered_map< std::string, core::Tensor > &tensor_map)
Definition: NumpyIO.cpp:759
std::string GetFileExtensionInLowerCase(const std::string &filename)
Definition: FileSystem.cpp:281
Generic file read and write utility for python interface.