Open3D (C++ API)  0.20.0
Loading...
Searching...
No Matches
GeometryIndexer.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2026 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7
8#pragma once
9
10#include <unordered_map>
11
13#include "open3d/core/Tensor.h"
18
19namespace open3d {
20namespace t {
21namespace geometry {
22namespace kernel {
23
26public:
29 TransformIndexer(const core::Tensor& intrinsics,
30 const core::Tensor& extrinsics,
31 float scale = 1.0f) {
32 // Move to CPU for host-side data extraction (the extracted float
33 // values are used in OPEN3D_HOST_DEVICE methods).
34 core::Tensor intrinsics_cpu =
35 intrinsics.To(core::Device("CPU:0")).Contiguous();
36 core::Tensor extrinsics_cpu =
37 extrinsics.To(core::Device("CPU:0")).Contiguous();
38
39 core::AssertTensorShape(intrinsics_cpu, {3, 3});
40 core::AssertTensorDtype(intrinsics_cpu, core::Float64);
41
42 core::AssertTensorShape(extrinsics_cpu, {4, 4});
43 core::AssertTensorDtype(extrinsics_cpu, core::Float64);
44
45 const double* intrinsic_ptr = intrinsics_cpu.GetDataPtr<double>();
46 const double* extrinsic_ptr = extrinsics_cpu.GetDataPtr<double>();
47 for (int i = 0; i < 3; ++i) {
48 for (int j = 0; j < 4; ++j) {
49 extrinsic_[i][j] = extrinsic_ptr[i * 4 + j];
50 }
51 }
52
53 fx_ = intrinsic_ptr[0 * 3 + 0];
54 fy_ = intrinsic_ptr[1 * 3 + 1];
55 cx_ = intrinsic_ptr[0 * 3 + 2];
56 cy_ = intrinsic_ptr[1 * 3 + 2];
57 scale_ = scale;
58 }
59
62 float y_in,
63 float z_in,
64 float* x_out,
65 float* y_out,
66 float* z_out) const {
67 x_in *= scale_;
68 y_in *= scale_;
69 z_in *= scale_;
70
71 *x_out = x_in * extrinsic_[0][0] + y_in * extrinsic_[0][1] +
72 z_in * extrinsic_[0][2] + extrinsic_[0][3];
73 *y_out = x_in * extrinsic_[1][0] + y_in * extrinsic_[1][1] +
74 z_in * extrinsic_[1][2] + extrinsic_[1][3];
75 *z_out = x_in * extrinsic_[2][0] + y_in * extrinsic_[2][1] +
76 z_in * extrinsic_[2][2] + extrinsic_[2][3];
77 }
78
80 OPEN3D_HOST_DEVICE void Rotate(float x_in,
81 float y_in,
82 float z_in,
83 float* x_out,
84 float* y_out,
85 float* z_out) const {
86 x_in *= scale_;
87 y_in *= scale_;
88 z_in *= scale_;
89
90 *x_out = x_in * extrinsic_[0][0] + y_in * extrinsic_[0][1] +
91 z_in * extrinsic_[0][2];
92 *y_out = x_in * extrinsic_[1][0] + y_in * extrinsic_[1][1] +
93 z_in * extrinsic_[1][2];
94 *z_out = x_in * extrinsic_[2][0] + y_in * extrinsic_[2][1] +
95 z_in * extrinsic_[2][2];
96 }
97
99 OPEN3D_HOST_DEVICE void Project(float x_in,
100 float y_in,
101 float z_in,
102 float* u_out,
103 float* v_out) const {
104 float inv_z = 1.0f / z_in;
105 *u_out = fx_ * x_in * inv_z + cx_;
106 *v_out = fy_ * y_in * inv_z + cy_;
107 }
108
111 float v_in,
112 float d_in,
113 float* x_out,
114 float* y_out,
115 float* z_out) const {
116 *x_out = (u_in - cx_) * d_in / fx_;
117 *y_out = (v_in - cy_) * d_in / fy_;
118 *z_out = d_in;
119 }
120
121 OPEN3D_HOST_DEVICE void GetFocalLength(float* fx, float* fy) const {
122 *fx = fx_;
123 *fy = fy_;
124 }
125
127 float* y,
128 float* z) const {
129 *x = extrinsic_[0][3];
130 *y = extrinsic_[1][3];
131 *z = extrinsic_[2][3];
132 }
133
134private:
135 float extrinsic_[3][4];
136
137 float fx_;
138 float fy_;
139 float cx_;
140 float cy_;
141
142 float scale_;
143};
144
157const int64_t MAX_RESOLUTION_DIMS = 4;
158
159template <typename index_t>
161public:
162 TArrayIndexer() : ptr_(nullptr), element_byte_size_(0), active_dims_(0) {
163 for (index_t i = 0; i < MAX_RESOLUTION_DIMS; ++i) {
164 shape_[i] = 0;
165 }
166 }
167
168 TArrayIndexer(const core::Tensor& ndarray, index_t active_dims) {
169 if (!ndarray.IsContiguous()) {
170 utility::LogError(
171 "Only support contiguous tensors for general operations.");
172 }
173
174 core::SizeVector shape = ndarray.GetShape();
175 index_t n = ndarray.NumDims();
176 if (active_dims > MAX_RESOLUTION_DIMS || active_dims > n) {
177 utility::LogError(
178 "Tensor shape too large, only <= {} and <= {} array dim is "
179 "supported, but received {}.",
180 MAX_RESOLUTION_DIMS, n, active_dims);
181 }
182
183 // Leading dimensions are coordinates
184 active_dims_ = active_dims;
185 for (index_t i = 0; i < active_dims_; ++i) {
186 shape_[i] = shape[i];
187 }
188 // Trailing dimensions are channels
189 element_byte_size_ = ndarray.GetDtype().ByteSize();
190 for (index_t i = active_dims_; i < n; ++i) {
191 element_byte_size_ *= shape[i];
192 }
193
194 // Fill-in rest to make compiler happy, not actually used.
195 for (index_t i = active_dims_; i < MAX_RESOLUTION_DIMS; ++i) {
196 shape_[i] = 0;
197 }
198 ptr_ = const_cast<void*>(ndarray.GetDataPtr());
199 }
200
203 index_t n = static_cast<index_t>(shape.size());
204 if (n > MAX_RESOLUTION_DIMS) {
205 utility::LogError(
206 "SizeVector too large, only <= {} is supported, but "
207 "received {}.",
209 }
210 active_dims_ = n;
211 for (index_t i = 0; i < active_dims_; ++i) {
212 shape_[i] = shape[i];
213 }
214
215 // Fill-in rest to make compiler happy, not actually used.
216 for (index_t i = active_dims_; i < MAX_RESOLUTION_DIMS; ++i) {
217 shape_[i] = 0;
218 }
219
220 // Reserved
221 element_byte_size_ = 0;
222 ptr_ = nullptr;
223 }
224
225 OPEN3D_HOST_DEVICE index_t ElementByteSize() { return element_byte_size_; }
226
228 index_t num_elems = 1;
229 for (index_t i = 0; i < active_dims_; ++i) {
230 num_elems *= shape_[i];
231 }
232 return num_elems;
233 }
234
236 inline OPEN3D_HOST_DEVICE void CoordToWorkload(index_t x_in,
237 index_t y_in,
238 index_t* workload) const {
239 *workload = y_in * shape_[1] + x_in;
240 }
241
243 inline OPEN3D_HOST_DEVICE void CoordToWorkload(index_t x_in,
244 index_t y_in,
245 index_t z_in,
246 index_t* workload) const {
247 *workload = (z_in * shape_[1] + y_in) * shape_[2] + x_in;
248 }
249
251 inline OPEN3D_HOST_DEVICE void CoordToWorkload(index_t x_in,
252 index_t y_in,
253 index_t z_in,
254 index_t t_in,
255 index_t* workload) const {
256 *workload = ((t_in * shape_[1] + z_in) * shape_[2] + y_in) * shape_[3] +
257 x_in;
258 }
259
261 inline OPEN3D_HOST_DEVICE void WorkloadToCoord(index_t workload,
262 index_t* x_out,
263 index_t* y_out) const {
264 *x_out = workload % shape_[1];
265 *y_out = workload / shape_[1];
266 }
267
269 inline OPEN3D_HOST_DEVICE void WorkloadToCoord(index_t workload,
270 index_t* x_out,
271 index_t* y_out,
272 index_t* z_out) const {
273 *x_out = workload % shape_[2];
274 workload = (workload - *x_out) / shape_[2];
275 *y_out = workload % shape_[1];
276 *z_out = workload / shape_[1];
277 }
278
280 inline OPEN3D_HOST_DEVICE void WorkloadToCoord(index_t workload,
281 index_t* x_out,
282 index_t* y_out,
283 index_t* z_out,
284 index_t* t_out) const {
285 *x_out = workload % shape_[3];
286 workload = (workload - *x_out) / shape_[3];
287 *y_out = workload % shape_[2];
288 workload = (workload - *y_out) / shape_[2];
289 *z_out = workload % shape_[1];
290 *t_out = workload / shape_[1];
291 }
292
293 inline OPEN3D_HOST_DEVICE bool InBoundary(float x, float y) const {
294 return y >= 0 && x >= 0 && y <= shape_[0] - 1.0f &&
295 x <= shape_[1] - 1.0f;
296 }
297 inline OPEN3D_HOST_DEVICE bool InBoundary(float x, float y, float z) const {
298 return z >= 0 && y >= 0 && x >= 0 && z <= shape_[0] - 1.0f &&
299 y <= shape_[1] - 1.0f && x <= shape_[2] - 1.0f;
300 }
301 inline OPEN3D_HOST_DEVICE bool InBoundary(float x,
302 float y,
303 float z,
304 float t) const {
305 return t >= 0 && z >= 0 && y >= 0 && x >= 0 && t <= shape_[0] - 1.0f &&
306 z <= shape_[1] - 1.0f && y <= shape_[2] - 1.0f &&
307 x <= shape_[3] - 1.0f;
308 }
309
310 inline OPEN3D_HOST_DEVICE index_t GetShape(int i) const {
311 return shape_[i];
312 }
313
314 inline OPEN3D_HOST_DEVICE void* GetDataPtr() const { return ptr_; }
315
316 template <typename T>
317 inline OPEN3D_HOST_DEVICE T* GetDataPtr(index_t x) const {
318 return static_cast<T*>(static_cast<void*>(static_cast<uint8_t*>(ptr_) +
319 x * element_byte_size_));
320 }
321
322 template <typename T>
323 inline OPEN3D_HOST_DEVICE T* GetDataPtr(index_t x, index_t y) const {
324 index_t workload;
325 CoordToWorkload(x, y, &workload);
326 return static_cast<T*>(static_cast<void*>(
327 static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
328 }
329
330 template <typename T>
331 inline OPEN3D_HOST_DEVICE T* GetDataPtr(index_t x,
332 index_t y,
333 index_t z) const {
334 index_t workload;
335 CoordToWorkload(x, y, z, &workload);
336 return static_cast<T*>(static_cast<void*>(
337 static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
338 }
339
340 template <typename T>
341 inline OPEN3D_HOST_DEVICE T* GetDataPtr(index_t x,
342 index_t y,
343 index_t z,
344 index_t t) const {
345 index_t workload;
346 CoordToWorkload(x, y, z, t, &workload);
347 return static_cast<T*>(static_cast<void*>(
348 static_cast<uint8_t*>(ptr_) + workload * element_byte_size_));
349 }
350
351private:
352 void* ptr_;
353 index_t element_byte_size_;
354 index_t active_dims_;
355
356 index_t shape_[MAX_RESOLUTION_DIMS];
357};
358
360
361} // namespace kernel
362} // namespace geometry
363} // namespace t
364} // namespace open3d
Common CUDA utilities.
#define OPEN3D_HOST_DEVICE
Definition CUDAUtils.h:43
std::int64_t y
Definition NormalDistributionsTransform.cpp:43
std::int64_t x
Definition NormalDistributionsTransform.cpp:42
std::int64_t z
Definition NormalDistributionsTransform.cpp:44
double t
Definition SurfaceReconstructionPoisson.cpp:175
Definition Device.h:18
int64_t ByteSize() const
Definition Dtype.h:58
Definition SizeVector.h:69
size_t size() const
Definition SmallVector.h:120
Definition Tensor.h:32
SizeVector GetShape() const
Definition Tensor.h:1186
T * GetDataPtr()
Definition Tensor.h:1203
Tensor Contiguous() const
Definition Tensor.cpp:817
int64_t NumDims() const
Definition Tensor.h:1231
bool IsContiguous() const
Definition Tensor.h:1093
Dtype GetDtype() const
Definition Tensor.h:1223
Tensor To(Dtype dtype, bool copy=false) const
Definition Tensor.cpp:784
Definition GeometryIndexer.h:160
OPEN3D_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.
Definition GeometryIndexer.h:280
OPEN3D_HOST_DEVICE bool InBoundary(float x, float y) const
Definition GeometryIndexer.h:293
TArrayIndexer()
Definition GeometryIndexer.h:162
OPEN3D_HOST_DEVICE T * GetDataPtr(index_t x, index_t y, index_t z, index_t t) const
Definition GeometryIndexer.h:341
OPEN3D_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
Definition GeometryIndexer.h:251
TArrayIndexer(const core::Tensor &ndarray, index_t active_dims)
Definition GeometryIndexer.h:168
OPEN3D_HOST_DEVICE void * GetDataPtr() const
Definition GeometryIndexer.h:314
OPEN3D_HOST_DEVICE void CoordToWorkload(index_t x_in, index_t y_in, index_t *workload) const
2D coordinate => workload
Definition GeometryIndexer.h:236
OPEN3D_HOST_DEVICE void WorkloadToCoord(index_t workload, index_t *x_out, index_t *y_out) const
Workload => 2D coordinate.
Definition GeometryIndexer.h:261
OPEN3D_HOST_DEVICE index_t ElementByteSize()
Definition GeometryIndexer.h:225
OPEN3D_HOST_DEVICE bool InBoundary(float x, float y, float z) const
Definition GeometryIndexer.h:297
OPEN3D_HOST_DEVICE void CoordToWorkload(index_t x_in, index_t y_in, index_t z_in, index_t *workload) const
3D coordinate => workload
Definition GeometryIndexer.h:243
OPEN3D_HOST_DEVICE T * GetDataPtr(index_t x) const
Definition GeometryIndexer.h:317
OPEN3D_HOST_DEVICE index_t GetShape(int i) const
Definition GeometryIndexer.h:310
OPEN3D_HOST_DEVICE T * GetDataPtr(index_t x, index_t y, index_t z) const
Definition GeometryIndexer.h:331
OPEN3D_HOST_DEVICE index_t NumElements()
Definition GeometryIndexer.h:227
OPEN3D_HOST_DEVICE T * GetDataPtr(index_t x, index_t y) const
Definition GeometryIndexer.h:323
OPEN3D_HOST_DEVICE bool InBoundary(float x, float y, float z, float t) const
Definition GeometryIndexer.h:301
OPEN3D_HOST_DEVICE void WorkloadToCoord(index_t workload, index_t *x_out, index_t *y_out, index_t *z_out) const
Workload => 3D coordinate.
Definition GeometryIndexer.h:269
TArrayIndexer(const core::SizeVector &shape)
Only used for simple shapes.
Definition GeometryIndexer.h:202
Helper class for converting coordinates/indices between 3D/3D, 3D/2D, 2D/3D.
Definition GeometryIndexer.h:25
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:99
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:80
TransformIndexer(const core::Tensor &intrinsics, const core::Tensor &extrinsics, float scale=1.0f)
Definition GeometryIndexer.h:29
OPEN3D_HOST_DEVICE void GetCameraPosition(float *x, float *y, float *z) const
Definition GeometryIndexer.h:126
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:61
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:110
OPEN3D_HOST_DEVICE void GetFocalLength(float *fx, float *fy) const
Definition GeometryIndexer.h:121
const Dtype Float64
Definition Dtype.cpp:43
const int64_t MAX_RESOLUTION_DIMS
Definition GeometryIndexer.h:157
Definition PinholeCameraIntrinsic.cpp:16