ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
GeometryIndexer.h
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 #pragma once
9 
10 #include <Helper.h>
11 #include <Logging.h>
12 #include <Timer.h>
13 
14 #include <unordered_map>
15 
19 
20 namespace cloudViewer {
21 namespace t {
22 namespace geometry {
23 namespace kernel {
24 
27 public:
30  TransformIndexer(const core::Tensor& intrinsics,
31  const core::Tensor& extrinsics,
32  float scale = 1.0f) {
33  core::AssertTensorShape(intrinsics, {3, 3});
35  core::AssertTensorDevice(intrinsics, core::Device("CPU:0"));
36  if (!intrinsics.IsContiguous()) {
37  utility::LogError("Intrinsics is not contiguous");
38  }
39 
40  core::AssertTensorShape(extrinsics, {4, 4});
42  core::AssertTensorDevice(extrinsics, core::Device("CPU:0"));
43  if (!extrinsics.IsContiguous()) {
44  utility::LogError("Extrinsics is not contiguous");
45  }
46 
47  const double* intrinsic_ptr = intrinsics.GetDataPtr<double>();
48  const double* extrinsic_ptr = extrinsics.GetDataPtr<double>();
49  for (int i = 0; i < 3; ++i) {
50  for (int j = 0; j < 4; ++j) {
51  extrinsic_[i][j] = extrinsic_ptr[i * 4 + j];
52  }
53  }
54 
55  fx_ = intrinsic_ptr[0 * 3 + 0];
56  fy_ = intrinsic_ptr[1 * 3 + 1];
57  cx_ = intrinsic_ptr[0 * 3 + 2];
58  cy_ = intrinsic_ptr[1 * 3 + 2];
59  scale_ = scale;
60  }
61 
64  float y_in,
65  float z_in,
66  float* x_out,
67  float* y_out,
68  float* z_out) const {
69  x_in *= scale_;
70  y_in *= scale_;
71  z_in *= scale_;
72 
73  *x_out = x_in * extrinsic_[0][0] + y_in * extrinsic_[0][1] +
74  z_in * extrinsic_[0][2] + extrinsic_[0][3];
75  *y_out = x_in * extrinsic_[1][0] + y_in * extrinsic_[1][1] +
76  z_in * extrinsic_[1][2] + extrinsic_[1][3];
77  *z_out = x_in * extrinsic_[2][0] + y_in * extrinsic_[2][1] +
78  z_in * extrinsic_[2][2] + extrinsic_[2][3];
79  }
80 
83  float y_in,
84  float z_in,
85  float* x_out,
86  float* y_out,
87  float* z_out) const {
88  x_in *= scale_;
89  y_in *= scale_;
90  z_in *= scale_;
91 
92  *x_out = x_in * extrinsic_[0][0] + y_in * extrinsic_[0][1] +
93  z_in * extrinsic_[0][2];
94  *y_out = x_in * extrinsic_[1][0] + y_in * extrinsic_[1][1] +
95  z_in * extrinsic_[1][2];
96  *z_out = x_in * extrinsic_[2][0] + y_in * extrinsic_[2][1] +
97  z_in * extrinsic_[2][2];
98  }
99 
102  float y_in,
103  float z_in,
104  float* u_out,
105  float* v_out) const {
106  float inv_z = 1.0f / z_in;
107  *u_out = fx_ * x_in * inv_z + cx_;
108  *v_out = fy_ * y_in * inv_z + cy_;
109  }
110 
113  float v_in,
114  float d_in,
115  float* x_out,
116  float* y_out,
117  float* z_out) const {
118  *x_out = (u_in - cx_) * d_in / fx_;
119  *y_out = (v_in - cy_) * d_in / fy_;
120  *z_out = d_in;
121  }
122 
123  CLOUDVIEWER_HOST_DEVICE void GetFocalLength(float* fx, float* fy) const {
124  *fx = fx_;
125  *fy = fy_;
126  }
127 
129  float* y,
130  float* z) const {
131  *x = extrinsic_[0][3];
132  *y = extrinsic_[1][3];
133  *z = extrinsic_[2][3];
134  }
135 
136 private:
137  float extrinsic_[3][4];
138 
139  float fx_;
140  float fy_;
141  float cx_;
142  float cy_;
143 
144  float scale_;
145 };
146 
159 const int64_t MAX_RESOLUTION_DIMS = 4;
160 
161 template <typename index_t>
163 public:
164  TArrayIndexer() : ptr_(nullptr), element_byte_size_(0), active_dims_(0) {
165  for (index_t i = 0; i < MAX_RESOLUTION_DIMS; ++i) {
166  shape_[i] = 0;
167  }
168  }
169 
170  TArrayIndexer(const core::Tensor& ndarray, index_t active_dims) {
171  if (!ndarray.IsContiguous()) {
173  "Only support contiguous tensors for general operations.");
174  }
175 
176  core::SizeVector shape = ndarray.GetShape();
177  index_t n = ndarray.NumDims();
178  if (active_dims > MAX_RESOLUTION_DIMS || active_dims > n) {
180  "Tensor shape too large, only <= {} and <= {} array dim is "
181  "supported, but received {}.",
182  MAX_RESOLUTION_DIMS, n, active_dims);
183  }
184 
185  // Leading dimensions are coordinates
186  active_dims_ = active_dims;
187  for (index_t i = 0; i < active_dims_; ++i) {
188  shape_[i] = shape[i];
189  }
190  // Trailing dimensions are channels
191  element_byte_size_ = ndarray.GetDtype().ByteSize();
192  for (index_t i = active_dims_; i < n; ++i) {
193  element_byte_size_ *= shape[i];
194  }
195 
196  // Fill-in rest to make compiler happy, not actually used.
197  for (index_t i = active_dims_; i < MAX_RESOLUTION_DIMS; ++i) {
198  shape_[i] = 0;
199  }
200  ptr_ = const_cast<void*>(ndarray.GetDataPtr());
201  }
202 
205  index_t n = static_cast<index_t>(shape.size());
206  if (n > MAX_RESOLUTION_DIMS) {
208  "SizeVector too large, only <= {} is supported, but "
209  "received {}.",
211  }
212  active_dims_ = n;
213  for (index_t i = 0; i < active_dims_; ++i) {
214  shape_[i] = shape[i];
215  }
216 
217  // Fill-in rest to make compiler happy, not actually used.
218  for (index_t i = active_dims_; i < MAX_RESOLUTION_DIMS; ++i) {
219  shape_[i] = 0;
220  }
221 
222  // Reserved
223  element_byte_size_ = 0;
224  ptr_ = nullptr;
225  }
226 
228  return element_byte_size_;
229  }
230 
232  index_t num_elems = 1;
233  for (index_t i = 0; i < active_dims_; ++i) {
234  num_elems *= shape_[i];
235  }
236  return num_elems;
237  }
238 
241  index_t x_in, index_t y_in, index_t* workload) const {
242  *workload = y_in * shape_[1] + x_in;
243  }
244 
247  index_t x_in, index_t y_in, index_t z_in, index_t* workload) const {
248  *workload = (z_in * shape_[1] + y_in) * shape_[2] + x_in;
249  }
250 
253  index_t x_in,
254  index_t y_in,
255  index_t z_in,
256  index_t t_in,
257  index_t* workload) const {
258  *workload = ((t_in * shape_[1] + z_in) * shape_[2] + y_in) * shape_[3] +
259  x_in;
260  }
261 
264  index_t* x_out,
265  index_t* y_out) const {
266  *x_out = workload % shape_[1];
267  *y_out = workload / shape_[1];
268  }
269 
272  index_t* x_out,
273  index_t* y_out,
274  index_t* z_out) const {
275  *x_out = workload % shape_[2];
276  workload = (workload - *x_out) / shape_[2];
277  *y_out = workload % shape_[1];
278  *z_out = workload / shape_[1];
279  }
280 
283  index_t* x_out,
284  index_t* y_out,
285  index_t* z_out,
286  index_t* t_out) const {
287  *x_out = workload % shape_[3];
288  workload = (workload - *x_out) / shape_[3];
289  *y_out = workload % shape_[2];
290  workload = (workload - *y_out) / shape_[2];
291  *z_out = workload % shape_[1];
292  *t_out = workload / shape_[1];
293  }
294 
295  inline CLOUDVIEWER_HOST_DEVICE bool InBoundary(float x, float y) const {
296  return y >= 0 && x >= 0 && y <= shape_[0] - 1.0f &&
297  x <= shape_[1] - 1.0f;
298  }
299  inline CLOUDVIEWER_HOST_DEVICE bool InBoundary(float x,
300  float y,
301  float z) const {
302  return z >= 0 && y >= 0 && x >= 0 && z <= shape_[0] - 1.0f &&
303  y <= shape_[1] - 1.0f && x <= shape_[2] - 1.0f;
304  }
305  inline CLOUDVIEWER_HOST_DEVICE bool InBoundary(float x,
306  float y,
307  float z,
308  float t) const {
309  return t >= 0 && z >= 0 && y >= 0 && x >= 0 && t <= shape_[0] - 1.0f &&
310  z <= shape_[1] - 1.0f && y <= shape_[2] - 1.0f &&
311  x <= shape_[3] - 1.0f;
312  }
313 
315  return shape_[i];
316  }
317 
318  inline CLOUDVIEWER_HOST_DEVICE void* GetDataPtr() const { return ptr_; }
319 
320  template <typename T>
322  return static_cast<T*>(static_cast<void*>(static_cast<uint8_t*>(ptr_) +
323  x * element_byte_size_));
324  }
325 
326  template <typename T>
328  index_t workload;
329  CoordToWorkload(x, y, &workload);
330  return static_cast<T*>(static_cast<void*>(
331  static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
332  }
333 
334  template <typename T>
336  index_t y,
337  index_t z) const {
338  index_t workload;
339  CoordToWorkload(x, y, z, &workload);
340  return static_cast<T*>(static_cast<void*>(
341  static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
342  }
343 
344  template <typename T>
346  index_t y,
347  index_t z,
348  index_t t) const {
349  index_t workload;
350  CoordToWorkload(x, y, z, t, &workload);
351  return static_cast<T*>(static_cast<void*>(
352  static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
353  }
354 
355 private:
356  void* ptr_;
357  index_t element_byte_size_;
358  index_t active_dims_;
359 
361 };
362 
364 
365 } // namespace kernel
366 } // namespace geometry
367 } // namespace t
368 } // namespace cloudViewer
Common CUDA utilities.
#define CLOUDVIEWER_HOST_DEVICE
Definition: CUDAUtils.h:44
#define AssertTensorDevice(tensor,...)
Definition: TensorCheck.h:45
#define AssertTensorDtype(tensor,...)
Definition: TensorCheck.h:21
#define AssertTensorShape(tensor,...)
Definition: TensorCheck.h:61
int64_t ByteSize() const
Definition: Dtype.h:59
int64_t NumDims() const
Definition: Tensor.h:1172
bool IsContiguous() const
Definition: Tensor.h:1036
Dtype GetDtype() const
Definition: Tensor.h:1164
SizeVector GetShape() const
Definition: Tensor.h:1127
CLOUDVIEWER_HOST_DEVICE T * GetDataPtr(index_t x, index_t y, index_t z) const
CLOUDVIEWER_HOST_DEVICE T * GetDataPtr(index_t x, index_t y, index_t z, index_t t) const
CLOUDVIEWER_HOST_DEVICE void WorkloadToCoord(index_t workload, index_t *x_out, index_t *y_out) const
Workload => 2D coordinate.
CLOUDVIEWER_HOST_DEVICE index_t NumElements()
CLOUDVIEWER_HOST_DEVICE void * GetDataPtr() const
CLOUDVIEWER_HOST_DEVICE void CoordToWorkload(index_t x_in, index_t y_in, index_t *workload) const
2D coordinate => workload
CLOUDVIEWER_HOST_DEVICE void CoordToWorkload(index_t x_in, index_t y_in, index_t z_in, index_t *workload) const
3D coordinate => workload
CLOUDVIEWER_HOST_DEVICE index_t ElementByteSize()
CLOUDVIEWER_HOST_DEVICE bool InBoundary(float x, float y) const
CLOUDVIEWER_HOST_DEVICE void WorkloadToCoord(index_t workload, index_t *x_out, index_t *y_out, index_t *z_out, index_t *t_out) const
Workload => 4D coordinate.
TArrayIndexer(const core::SizeVector &shape)
Only used for simple shapes.
CLOUDVIEWER_HOST_DEVICE bool InBoundary(float x, float y, float z) const
CLOUDVIEWER_HOST_DEVICE T * GetDataPtr(index_t x, index_t y) const
CLOUDVIEWER_HOST_DEVICE void WorkloadToCoord(index_t workload, index_t *x_out, index_t *y_out, index_t *z_out) const
Workload => 3D coordinate.
CLOUDVIEWER_HOST_DEVICE void CoordToWorkload(index_t x_in, index_t y_in, index_t z_in, index_t t_in, index_t *workload) const
4D coordinate => workload
CLOUDVIEWER_HOST_DEVICE bool InBoundary(float x, float y, float z, float t) const
CLOUDVIEWER_HOST_DEVICE T * GetDataPtr(index_t x) const
TArrayIndexer(const core::Tensor &ndarray, index_t active_dims)
CLOUDVIEWER_HOST_DEVICE index_t GetShape(int i) const
Helper class for converting coordinates/indices between 3D/3D, 3D/2D, 2D/3D.
CLOUDVIEWER_HOST_DEVICE void Unproject(float u_in, float v_in, float d_in, float *x_out, float *y_out, float *z_out) const
Unproject a 2D uv coordinate with depth to 3D in camera coordinate.
TransformIndexer(const core::Tensor &intrinsics, const core::Tensor &extrinsics, float scale=1.0f)
CLOUDVIEWER_HOST_DEVICE void GetFocalLength(float *fx, float *fy) const
CLOUDVIEWER_HOST_DEVICE void Rotate(float x_in, float y_in, float z_in, float *x_out, float *y_out, float *z_out) const
Transform a 3D coordinate in camera coordinate to world coordinate.
CLOUDVIEWER_HOST_DEVICE void RigidTransform(float x_in, float y_in, float z_in, float *x_out, float *y_out, float *z_out) const
Transform a 3D coordinate in camera coordinate to world coordinate.
CLOUDVIEWER_HOST_DEVICE void GetCameraPosition(float *x, float *y, float *z) const
CLOUDVIEWER_HOST_DEVICE void Project(float x_in, float y_in, float z_in, float *u_out, float *v_out) const
Project a 3D coordinate in camera coordinate to a 2D uv coordinate.
#define LogError(...)
Definition: Logging.h:60
Helper functions for the ml ops.
const Dtype Float64
Definition: Dtype.cpp:43
Generic file read and write utility for python interface.