Open3D (C++ API)  0.13.0
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
GeometryIndexer.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26 
27 #pragma once
28 
29 #include <unordered_map>
30 
31 #include "open3d/core/Tensor.h"
32 #include "open3d/utility/Console.h"
33 #include "open3d/utility/Helper.h"
34 #include "open3d/utility/Timer.h"
35 
36 namespace open3d {
37 namespace t {
38 namespace geometry {
39 namespace kernel {
40 
43 public:
46  TransformIndexer(const core::Tensor& intrinsics,
47  const core::Tensor& extrinsics,
48  float scale = 1.0f) {
49  intrinsics.AssertShape({3, 3});
51  intrinsics.AssertDevice(core::Device("CPU:0"));
52  if (!intrinsics.IsContiguous()) {
53  utility::LogError("Intrinsics is not contiguous");
54  }
55 
56  extrinsics.AssertShape({4, 4});
58  extrinsics.AssertDevice(core::Device("CPU:0"));
59  if (!extrinsics.IsContiguous()) {
60  utility::LogError("Extrinsics is not contiguous");
61  }
62 
63  const double* intrinsic_ptr = intrinsics.GetDataPtr<double>();
64  const double* extrinsic_ptr = extrinsics.GetDataPtr<double>();
65  for (int i = 0; i < 3; ++i) {
66  for (int j = 0; j < 4; ++j) {
67  extrinsic_[i][j] = extrinsic_ptr[i * 4 + j];
68  }
69  }
70 
71  fx_ = intrinsic_ptr[0 * 3 + 0];
72  fy_ = intrinsic_ptr[1 * 3 + 1];
73  cx_ = intrinsic_ptr[0 * 3 + 2];
74  cy_ = intrinsic_ptr[1 * 3 + 2];
75  scale_ = scale;
76  }
77 
80  float y_in,
81  float z_in,
82  float* x_out,
83  float* y_out,
84  float* z_out) const {
85  x_in *= scale_;
86  y_in *= scale_;
87  z_in *= scale_;
88 
89  *x_out = x_in * extrinsic_[0][0] + y_in * extrinsic_[0][1] +
90  z_in * extrinsic_[0][2] + extrinsic_[0][3];
91  *y_out = x_in * extrinsic_[1][0] + y_in * extrinsic_[1][1] +
92  z_in * extrinsic_[1][2] + extrinsic_[1][3];
93  *z_out = x_in * extrinsic_[2][0] + y_in * extrinsic_[2][1] +
94  z_in * extrinsic_[2][2] + extrinsic_[2][3];
95  }
96 
98  OPEN3D_HOST_DEVICE void Rotate(float x_in,
99  float y_in,
100  float z_in,
101  float* x_out,
102  float* y_out,
103  float* z_out) const {
104  x_in *= scale_;
105  y_in *= scale_;
106  z_in *= scale_;
107 
108  *x_out = x_in * extrinsic_[0][0] + y_in * extrinsic_[0][1] +
109  z_in * extrinsic_[0][2];
110  *y_out = x_in * extrinsic_[1][0] + y_in * extrinsic_[1][1] +
111  z_in * extrinsic_[1][2];
112  *z_out = x_in * extrinsic_[2][0] + y_in * extrinsic_[2][1] +
113  z_in * extrinsic_[2][2];
114  }
115 
117  OPEN3D_HOST_DEVICE void Project(float x_in,
118  float y_in,
119  float z_in,
120  float* u_out,
121  float* v_out) const {
122  float inv_z = 1.0f / z_in;
123  *u_out = fx_ * x_in * inv_z + cx_;
124  *v_out = fy_ * y_in * inv_z + cy_;
125  }
126 
128  OPEN3D_HOST_DEVICE void Unproject(float u_in,
129  float v_in,
130  float d_in,
131  float* x_out,
132  float* y_out,
133  float* z_out) const {
134  *x_out = (u_in - cx_) * d_in / fx_;
135  *y_out = (v_in - cy_) * d_in / fy_;
136  *z_out = d_in;
137  }
138 
139  OPEN3D_HOST_DEVICE void GetFocalLength(float* fx, float* fy) const {
140  *fx = fx_;
141  *fy = fy_;
142  }
143 
144 private:
145  float extrinsic_[3][4];
146 
147  float fx_;
148  float fy_;
149  float cx_;
150  float cy_;
151 
152  float scale_;
153 };
154 
167 const int64_t MAX_RESOLUTION_DIMS = 4;
169 public:
170  NDArrayIndexer() : ptr_(nullptr), element_byte_size_(0), active_dims_(0) {
171  for (int i = 0; i < MAX_RESOLUTION_DIMS; ++i) {
172  shape_[i] = 0;
173  }
174  }
175 
176  NDArrayIndexer(const core::Tensor& ndarray, int64_t active_dims) {
177  if (!ndarray.IsContiguous()) {
179  "[NDArrayIndexer] Only support contiguous tensors for "
180  "general operations.");
181  }
182 
183  core::SizeVector shape = ndarray.GetShape();
184  int64_t n = ndarray.NumDims();
185  if (active_dims > MAX_RESOLUTION_DIMS || active_dims > n) {
187  "[NDArrayIndexer] Tensor shape too large, only <= {} and "
188  "<= {} array dim is supported, but received {}.",
189  MAX_RESOLUTION_DIMS, n, active_dims);
190  }
191 
192  // Leading dimensions are coordinates
193  active_dims_ = active_dims;
194  for (int64_t i = 0; i < active_dims_; ++i) {
195  shape_[i] = shape[i];
196  }
197  // Trailing dimensions are channels
198  element_byte_size_ = ndarray.GetDtype().ByteSize();
199  for (int64_t i = active_dims_; i < n; ++i) {
200  element_byte_size_ *= shape[i];
201  }
202 
203  // Fill-in rest to make compiler happy, not actually used.
204  for (int64_t i = active_dims_; i < MAX_RESOLUTION_DIMS; ++i) {
205  shape_[i] = 0;
206  }
207  ptr_ = const_cast<void*>(ndarray.GetDataPtr());
208  }
209 
212  int64_t n = static_cast<int64_t>(shape.size());
213  if (n > MAX_RESOLUTION_DIMS) {
215  "[NDArrayIndexer] SizeVector too large, only <= {} is "
216  "supported, but received {}.",
217  MAX_RESOLUTION_DIMS, n);
218  }
219  active_dims_ = n;
220  for (int64_t i = 0; i < active_dims_; ++i) {
221  shape_[i] = shape[i];
222  }
223 
224  // Fill-in rest to make compiler happy, not actually used.
225  for (int64_t i = active_dims_; i < MAX_RESOLUTION_DIMS; ++i) {
226  shape_[i] = 0;
227  }
228 
229  // Reserved
230  element_byte_size_ = 0;
231  ptr_ = nullptr;
232  }
233 
234  OPEN3D_HOST_DEVICE int64_t ElementByteSize() { return element_byte_size_; }
235 
237  int64_t num_elems = 1;
238  for (int64_t i = 0; i < active_dims_; ++i) {
239  num_elems *= shape_[i];
240  }
241  return num_elems;
242  }
243 
245  inline OPEN3D_HOST_DEVICE void CoordToWorkload(int64_t x_in,
246  int64_t y_in,
247  int64_t* workload) const {
248  *workload = y_in * shape_[1] + x_in;
249  }
250 
252  inline OPEN3D_HOST_DEVICE void CoordToWorkload(int64_t x_in,
253  int64_t y_in,
254  int64_t z_in,
255  int64_t* workload) const {
256  *workload = (z_in * shape_[1] + y_in) * shape_[2] + x_in;
257  }
258 
260  inline OPEN3D_HOST_DEVICE void CoordToWorkload(int64_t x_in,
261  int64_t y_in,
262  int64_t z_in,
263  int64_t t_in,
264  int64_t* workload) const {
265  *workload = ((t_in * shape_[1] + z_in) * shape_[2] + y_in) * shape_[3] +
266  x_in;
267  }
268 
270  inline OPEN3D_HOST_DEVICE void WorkloadToCoord(int64_t workload,
271  int64_t* x_out,
272  int64_t* y_out) const {
273  *x_out = workload % shape_[1];
274  *y_out = workload / shape_[1];
275  }
276 
278  inline OPEN3D_HOST_DEVICE void WorkloadToCoord(int64_t workload,
279  int64_t* x_out,
280  int64_t* y_out,
281  int64_t* z_out) const {
282  *x_out = workload % shape_[2];
283  workload = (workload - *x_out) / shape_[2];
284  *y_out = workload % shape_[1];
285  *z_out = workload / shape_[1];
286  }
287 
289  inline OPEN3D_HOST_DEVICE void WorkloadToCoord(int64_t workload,
290  int64_t* x_out,
291  int64_t* y_out,
292  int64_t* z_out,
293  int64_t* t_out) const {
294  *x_out = workload % shape_[3];
295  workload = (workload - *x_out) / shape_[3];
296  *y_out = workload % shape_[2];
297  workload = (workload - *y_out) / shape_[2];
298  *z_out = workload % shape_[1];
299  *t_out = workload / shape_[1];
300  }
301 
302  inline OPEN3D_HOST_DEVICE bool InBoundary(float x, float y) const {
303  return y >= 0 && x >= 0 && y <= shape_[0] - 1.0f &&
304  x <= shape_[1] - 1.0f;
305  }
306  inline OPEN3D_HOST_DEVICE bool InBoundary(float x, float y, float z) const {
307  return z >= 0 && y >= 0 && x >= 0 && z <= shape_[0] - 1.0f &&
308  y <= shape_[1] - 1.0f && x <= shape_[2] - 1.0f;
309  }
310  inline OPEN3D_HOST_DEVICE bool InBoundary(float x,
311  float y,
312  float z,
313  float t) const {
314  return t >= 0 && z >= 0 && y >= 0 && x >= 0 && t <= shape_[0] - 1.0f &&
315  z <= shape_[1] - 1.0f && y <= shape_[2] - 1.0f &&
316  x <= shape_[3] - 1.0f;
317  }
318 
319  inline OPEN3D_HOST_DEVICE int64_t GetShape(int i) const {
320  return shape_[i];
321  }
322 
323  template <typename T>
324  inline OPEN3D_HOST_DEVICE T* GetDataPtr(int64_t x) const {
325  return static_cast<T*>(static_cast<void*>(static_cast<uint8_t*>(ptr_) +
326  x * element_byte_size_));
327  }
328 
329  template <typename T>
330  inline OPEN3D_HOST_DEVICE T* GetDataPtr(int64_t x, int64_t y) const {
331  int64_t workload;
332  CoordToWorkload(x, y, &workload);
333  return static_cast<T*>(static_cast<void*>(
334  static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
335  }
336 
337  template <typename T>
338  inline OPEN3D_HOST_DEVICE T* GetDataPtr(int64_t x,
339  int64_t y,
340  int64_t z) const {
341  int64_t workload;
342  CoordToWorkload(x, y, z, &workload);
343  return static_cast<T*>(static_cast<void*>(
344  static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
345  }
346 
347  template <typename T>
348  inline OPEN3D_HOST_DEVICE T* GetDataPtr(int64_t x,
349  int64_t y,
350  int64_t z,
351  int64_t t) const {
352  int64_t workload;
353  CoordToWorkload(x, y, z, t, &workload);
354  return static_cast<T*>(static_cast<void*>(
355  static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
356  }
357 
358 private:
359  void* ptr_;
360  int64_t element_byte_size_;
361  int64_t active_dims_;
362 
363  int64_t shape_[MAX_RESOLUTION_DIMS];
364 };
365 
366 } // namespace kernel
367 } // namespace geometry
368 } // namespace t
369 } // namespace open3d
TransformIndexer(const core::Tensor &intrinsics, const core::Tensor &extrinsics, float scale=1.0f)
Definition: GeometryIndexer.h:46
OPEN3D_HOST_DEVICE void CoordToWorkload(int64_t x_in, int64_t y_in, int64_t z_in, int64_t t_in, int64_t *workload) const
4D coordinate => workload
Definition: GeometryIndexer.h:260
OPEN3D_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.
Definition: GeometryIndexer.h:98
int64_t NumDims() const
Definition: Tensor.h:1033
NDArrayIndexer(const core::Tensor &ndarray, int64_t active_dims)
Definition: GeometryIndexer.h:176
Definition: GeometryIndexer.h:168
OPEN3D_HOST_DEVICE void WorkloadToCoord(int64_t workload, int64_t *x_out, int64_t *y_out, int64_t *z_out) const
Workload => 3D coordinate.
Definition: GeometryIndexer.h:278
OPEN3D_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.
Definition: GeometryIndexer.h:117
Helper class for converting coordinates/indices between 3D/3D, 3D/2D, 2D/3D.
Definition: GeometryIndexer.h:42
const int64_t MAX_RESOLUTION_DIMS
Definition: GeometryIndexer.h:167
OPEN3D_HOST_DEVICE void CoordToWorkload(int64_t x_in, int64_t y_in, int64_t z_in, int64_t *workload) const
3D coordinate => workload
Definition: GeometryIndexer.h:252
NDArrayIndexer()
Definition: GeometryIndexer.h:170
Definition: SizeVector.h:102
#define LogError(...)
Definition: Console.h:79
Dtype GetDtype() const
Definition: Tensor.h:1025
OPEN3D_HOST_DEVICE T * GetDataPtr(int64_t x, int64_t y, int64_t z, int64_t t) const
Definition: GeometryIndexer.h:348
OPEN3D_HOST_DEVICE void WorkloadToCoord(int64_t workload, int64_t *x_out, int64_t *y_out, int64_t *z_out, int64_t *t_out) const
Workload => 4D coordinate.
Definition: GeometryIndexer.h:289
OPEN3D_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.
Definition: GeometryIndexer.h:128
OPEN3D_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.
Definition: GeometryIndexer.h:79
OPEN3D_HOST_DEVICE T * GetDataPtr(int64_t x) const
Definition: GeometryIndexer.h:324
#define OPEN3D_HOST_DEVICE
Definition: CUDAUtils.h:56
OPEN3D_HOST_DEVICE void GetFocalLength(float *fx, float *fy) const
Definition: GeometryIndexer.h:139
Definition: Device.h:39
OPEN3D_HOST_DEVICE int64_t GetShape(int i) const
Definition: GeometryIndexer.h:319
bool IsContiguous() const
Definition: Tensor.h:897
OPEN3D_HOST_DEVICE T * GetDataPtr(int64_t x, int64_t y) const
Definition: GeometryIndexer.h:330
OPEN3D_HOST_DEVICE T * GetDataPtr(int64_t x, int64_t y, int64_t z) const
Definition: GeometryIndexer.h:338
void AssertDtype(const Dtype &expected_dtype, const std::string &error_msg="") const
Assert that the Tensor has the specified dtype.
Definition: Tensor.cpp:1534
OPEN3D_HOST_DEVICE bool InBoundary(float x, float y, float z) const
Definition: GeometryIndexer.h:306
SizeVector GetShape() const
Definition: Tensor.h:988
OPEN3D_HOST_DEVICE bool InBoundary(float x, float y, float z, float t) const
Definition: GeometryIndexer.h:310
Definition: PinholeCameraIntrinsic.cpp:35
Definition: Tensor.h:50
OPEN3D_HOST_DEVICE void WorkloadToCoord(int64_t workload, int64_t *x_out, int64_t *y_out) const
Workload => 2D coordinate.
Definition: GeometryIndexer.h:270
int64_t ByteSize() const
Definition: Dtype.h:75
NDArrayIndexer(const core::SizeVector &shape)
Only used for simple shapes.
Definition: GeometryIndexer.h:211
OPEN3D_HOST_DEVICE int64_t ElementByteSize()
Definition: GeometryIndexer.h:234
T * GetDataPtr()
Definition: Tensor.h:1005
void AssertDevice(const Device &expected_device, const std::string &error_msg="") const
Assert that the Tensor has the specified device.
Definition: Tensor.cpp:1518
OPEN3D_HOST_DEVICE bool InBoundary(float x, float y) const
Definition: GeometryIndexer.h:302
OPEN3D_HOST_DEVICE int64_t NumElements()
Definition: GeometryIndexer.h:236
static const Dtype Float64
Definition: Dtype.h:43
OPEN3D_HOST_DEVICE void CoordToWorkload(int64_t x_in, int64_t y_in, int64_t *workload) const
2D coordinate => workload
Definition: GeometryIndexer.h:245
void AssertShape(const SizeVector &expected_shape, const std::string &error_msg="") const
Assert that the Tensor has the specified shape.
Definition: Tensor.cpp:1498