ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
voxel_block_grid.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 
8 #include <string>
9 #include <unordered_map>
10 
13 #include "pybind/docstring.h"
16 
17 namespace cloudViewer {
18 namespace t {
19 namespace geometry {
20 
21 void pybind_voxel_block_grid(py::module& m) {
22  py::class_<VoxelBlockGrid> vbg(
23  m, "VoxelBlockGrid",
24  "A voxel block grid is a sparse grid of voxel blocks. Each voxel "
25  "block is a dense 3D array, preserving local data distribution. If "
26  "the block_resolution is set to 1, then the VoxelBlockGrid "
27  "degenerates to a sparse voxel grid.");
28 
29  vbg.def(py::init<const std::vector<std::string>&,
30  const std::vector<core::Dtype>&,
31  const std::vector<core::SizeVector>&, float, int64_t,
32  int64_t, const core::Device&>(),
33  "attr_names"_a, "attr_dtypes"_a, "attr_channels"_a,
34  "voxel_size"_a = 0.0058, "block_resolution"_a = 16,
35  "block_count"_a = 10000, "device"_a = core::Device("CPU:0"));
36 
37  vbg.def("hashmap", &VoxelBlockGrid::GetHashMap,
38  "Get the underlying hash map from 3d block coordinates to block "
39  "voxel grids.");
40 
41  vbg.def("attribute", &VoxelBlockGrid::GetAttribute,
42  "Get the attribute tensor to be indexed with voxel_indices.",
43  "attribute_name"_a);
44 
45  vbg.def("voxel_indices",
46  py::overload_cast<const core::Tensor&>(
47  &VoxelBlockGrid::GetVoxelIndices, py::const_),
48  "Get a (4, N), Int64 index tensor for input buffer indices, used "
49  "for advanced indexing. "
50  "Returned index tensor can access selected value buffer"
51  "in the order of "
52  "(buf_index, index_voxel_x, index_voxel_y, index_voxel_z). "
53  "Example: "
54  "For a voxel block grid with (2, 2, 2) block resolution, "
55  "if the active block coordinates are at buffer index {(2, 4)} "
56  "given by active_indices() from the underlying hash map, "
57  "the returned result will be a (4, 2 x 8) tensor: "
58  "{ "
59  "(2, 0, 0, 0), (2, 1, 0, 0), (2, 0, 1, 0), (2, 1, 1, 0), "
60  "(2, 0, 0, 1), (2, 1, 0, 1), (2, 0, 1, 1), (2, 1, 1, 1), "
61  "(4, 0, 0, 0), (4, 1, 0, 0), (4, 0, 1, 0), (4, 1, 1, 0), "
62  "(4, 0, 0, 1), (4, 1, 0, 1), (4, 0, 1, 1), (4, 1, 1, 1), "
63  "}"
64  "Note: the slicing order is z-y-x.");
65 
66  vbg.def("voxel_indices",
67  py::overload_cast<>(&VoxelBlockGrid::GetVoxelIndices, py::const_),
68  "Get a (4, N) Int64 idnex tensor for all the active voxels stored "
69  "in the hash map, used for advanced indexing.");
70 
71  vbg.def("voxel_coordinates", &VoxelBlockGrid::GetVoxelCoordinates,
72  "Get a (3, hashmap.Size() * resolution^3) coordinate tensor of "
73  "active"
74  "voxels per block, used for geometry transformation jointly with "
75  "indices from voxel_indices. "
76  "Example: "
77  "For a voxel block grid with (2, 2, 2) block resolution, "
78  "if the active block coordinates are {(-1, 3, 2), (0, 2, 4)}, "
79  "the returned result will be a (3, 2 x 8) tensor given by: "
80  "{ "
81  "key_tensor[voxel_indices[0]] * block_resolution_ + "
82  "voxel_indices[1] "
83  "key_tensor[voxel_indices[0]] * block_resolution_ + "
84  "voxel_indices[2] "
85  "key_tensor[voxel_indices[0]] * block_resolution_ + "
86  "voxel_indices[3] "
87  "} "
88  "Note: the coordinates are VOXEL COORDINATES in Int64. To access "
89  "metric"
90  "coordinates, multiply by voxel size.",
91  "voxel_indices"_a);
92 
93  vbg.def("voxel_coordinates_and_flattened_indices",
94  py::overload_cast<const core::Tensor&>(
96  "Get a (buf_indices.shape[0] * resolution^3, 3), Float32 voxel "
97  "coordinate tensor,"
98  "and a (buf_indices.shape[0] * resolution^3, 1), Int64 voxel index "
99  "tensor.",
100  "buf_indices"_a);
101 
102  vbg.def("voxel_coordinates_and_flattened_indices",
103  py::overload_cast<>(
105  "Get a (hashmap.size() * resolution^3, 3), Float32 voxel "
106  "coordinate tensor,"
107  "and a (hashmap.size() * resolution^3, 1), Int64 voxel index "
108  "tensor.");
109 
110  vbg.def("compute_unique_block_coordinates",
111  py::overload_cast<const Image&, const core::Tensor&,
112  const core::Tensor&, float, float, float>(
114  "Get a (3, M) active block coordinates from a depth image, with "
115  "potential duplicates removed."
116  "Note: these coordinates are not activated in the internal sparse "
117  "voxel block. They need to be inserted in the hash map.",
118  "depth"_a, "intrinsic"_a, "extrinsic"_a, "depth_scale"_a = 1000.0f,
119  "depth_max"_a = 3.0f, "trunc_voxel_multiplier"_a = 8.0);
120 
121  vbg.def("compute_unique_block_coordinates",
122  py::overload_cast<const PointCloud&, float>(
124  "Obtain active block coordinates from a point cloud.", "pcd"_a,
125  "trunc_voxel_multiplier"_a = 8.0);
126 
127  vbg.def("integrate",
128  py::overload_cast<const core::Tensor&, const Image&, const Image&,
129  const core::Tensor&, const core::Tensor&,
130  const core::Tensor&, float, float, float>(
132  "Specific operation for TSDF volumes."
133  "Integrate an RGB-D frame in the selected block coordinates using "
134  "pinhole camera model.",
135  "block_coords"_a, "depth"_a, "color"_a, "depth_intrinsic"_a,
136  "color_intrinsic"_a, "extrinsic"_a,
137  "depth_scale"_a.noconvert() = 1000.0f,
138  "depth_max"_a.noconvert() = 3.0f,
139  "trunc_voxel_multiplier"_a.noconvert() = 8.0f);
140 
141  vbg.def("integrate",
142  py::overload_cast<const core::Tensor&, const Image&, const Image&,
143  const core::Tensor&, const core::Tensor&, float,
144  float, float>(&VoxelBlockGrid::Integrate),
145  "Specific operation for TSDF volumes."
146  "Integrate an RGB-D frame in the selected block coordinates using "
147  "pinhole camera model.",
148  "block_coords"_a, "depth"_a, "color"_a, "intrinsic"_a,
149  "extrinsic"_a, "depth_scale"_a.noconvert() = 1000.0f,
150  "depth_max"_a.noconvert() = 3.0f,
151  "trunc_voxel_multiplier"_a.noconvert() = 8.0f);
152 
153  vbg.def("integrate",
154  py::overload_cast<const core::Tensor&, const Image&,
155  const core::Tensor&, const core::Tensor&, float,
156  float, float>(&VoxelBlockGrid::Integrate),
157  "Specific operation for TSDF volumes."
158  "Similar to RGB-D integration, but only applied to depth images.",
159  "block_coords"_a, "depth"_a, "intrinsic"_a, "extrinsic"_a,
160  "depth_scale"_a.noconvert() = 1000.0f,
161  "depth_max"_a.noconvert() = 3.0f,
162  "trunc_voxel_multiplier"_a.noconvert() = 8.0f);
163 
164  vbg.def("ray_cast", &VoxelBlockGrid::RayCast,
165  "Specific operation for TSDF volumes."
166  "Perform volumetric ray casting in the selected block coordinates."
167  "The block coordinates in the frustum can be taken from"
168  "compute_unique_block_coordinates"
169  "All the block coordinates can be taken from "
170  "hashmap().key_tensor()",
171  "block_coords"_a, "intrinsic"_a, "extrinsic"_a, "width"_a,
172  "height"_a,
173  "render_attributes"_a = std::vector<std::string>{"depth", "color"},
174  "depth_scale"_a = 1000.0f, "depth_min"_a = 0.1f,
175  "depth_max"_a = 3.0f, "weight_threshold"_a = 3.0f,
176  "trunc_voxel_multiplier"_a = 8.0f, "range_map_down_factor"_a = 8);
177 
178  vbg.def("extract_point_cloud", &VoxelBlockGrid::ExtractPointCloud,
179  "Specific operation for TSDF volumes."
180  "Extract point cloud at isosurface points.",
181  "weight_threshold"_a = 3.0f, "estimated_point_number"_a = -1);
182 
183  vbg.def("extract_triangle_mesh", &VoxelBlockGrid::ExtractTriangleMesh,
184  "Specific operation for TSDF volumes."
185  "Extract triangle mesh at isosurface points.",
186  "weight_threshold"_a = 3.0f, "estimated_vertex_number"_a = -1);
187 
188  // Device transfers.
189  vbg.def("to", &VoxelBlockGrid::To,
190  "Transfer the voxel block grid to a specified device.", "device"_a,
191  "copy"_a = false);
192 
193  vbg.def(
194  "cpu",
195  [](const VoxelBlockGrid& voxelBlockGrid) {
196  return voxelBlockGrid.To(core::Device("CPU:0"));
197  },
198  "Transfer the voxel block grid to CPU. If the voxel block grid is "
199  "already on CPU, no copy will be performed.");
200  vbg.def(
201  "cuda",
202  [](const VoxelBlockGrid& voxelBlockGrid, int device_id) {
203  return voxelBlockGrid.To(core::Device("CUDA", device_id));
204  },
205  "Transfer the voxel block grid to a CUDA device. If the voxel "
206  "block grid is already on the specified CUDA device, no copy "
207  "will be performed.",
208  "device_id"_a = 0);
209 
210  vbg.def("save", &VoxelBlockGrid::Save,
211  "Save the voxel block grid to a npz file.", "file_name"_a);
212  vbg.def_static("load", &VoxelBlockGrid::Load,
213  "Load a voxel block grid from a npz file.", "file_name"_a);
214 }
215 
216 } // namespace geometry
217 } // namespace t
218 } // namespace cloudViewer
Common CUDA utilities.
The Image class stores image with customizable rows, cols, channels, dtype and device.
Definition: Image.h:29
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)
void pybind_voxel_block_grid(py::module &m)
Generic file read and write utility for python interface.