Loading [MathJax]/extensions/TeX/AMSsymbols.js
Open3D (C++ API)  0.16.0
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ImageImpl.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-2021 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 #include <limits>
28 
29 #include "open3d/core/CUDAUtils.h"
30 #include "open3d/core/Dispatch.h"
31 #include "open3d/core/Indexer.h"
32 #include "open3d/core/Tensor.h"
35 
36 namespace open3d {
37 namespace t {
38 namespace geometry {
39 namespace kernel {
40 namespace image {
41 
42 #ifndef __CUDACC__
43 using std::isinf;
44 using std::isnan;
45 #endif
46 
47 #ifdef __CUDACC__
48 void ToCUDA
49 #else
50 void ToCPU
51 #endif
52  (const core::Tensor& src,
53  core::Tensor& dst,
54  double scale,
55  double offset) {
56  core::Indexer indexer({src}, dst, core::DtypePolicy::NONE);
57  // elem_t: corresponds to dst_dtype.
58  // scalar_t: corresponds to src_dtype.
59  // calc_t: calculation type for intermediate results.
60 #define LINEAR_SATURATE(elem_t, calc_t) \
61  elem_t limits[2] = {std::numeric_limits<elem_t>::min(), \
62  std::numeric_limits<elem_t>::max()}; \
63  calc_t c_scale = static_cast<calc_t>(scale); \
64  calc_t c_offset = static_cast<calc_t>(offset); \
65  DISPATCH_DTYPE_TO_TEMPLATE(src.GetDtype(), [&]() { \
66  core::ParallelFor( \
67  src.GetDevice(), indexer.NumWorkloads(), \
68  [=] OPEN3D_DEVICE(int64_t workload_idx) { \
69  auto src_ptr = \
70  indexer.GetInputPtr<scalar_t>(0, workload_idx); \
71  auto dst_ptr = indexer.GetOutputPtr<elem_t>(workload_idx); \
72  calc_t out = static_cast<calc_t>(*src_ptr) * c_scale + \
73  c_offset; \
74  out = out < limits[0] ? limits[0] : out; \
75  out = out > limits[1] ? limits[1] : out; \
76  *dst_ptr = static_cast<elem_t>(out); \
77  }); \
78  });
79  core::Dtype dst_dtype = dst.GetDtype();
80  if (dst_dtype == core::Float32) {
81  LINEAR_SATURATE(float, float)
82  } else if (dst_dtype == core::Float64) {
83  LINEAR_SATURATE(double, double)
84  } else if (dst_dtype == core::Int8) {
85  LINEAR_SATURATE(int8_t, float)
86  } else if (dst_dtype == core::UInt8) {
87  LINEAR_SATURATE(uint8_t, float)
88  } else if (dst_dtype == core::Int16) {
89  LINEAR_SATURATE(int16_t, float)
90  } else if (dst_dtype == core::UInt16) {
91  LINEAR_SATURATE(uint16_t, float)
92  } else if (dst_dtype == core::Int32) {
93  LINEAR_SATURATE(int32_t, double)
94  } else if (dst_dtype == core::UInt32) {
95  LINEAR_SATURATE(uint32_t, double)
96  } else if (dst_dtype == core::Int64) {
97  LINEAR_SATURATE(int64_t, double)
98  } else if (dst_dtype == core::UInt64) {
99  LINEAR_SATURATE(uint64_t, double)
100  }
101 #undef LINEAR_SATURATE
102 }
103 
104 #ifdef __CUDACC__
105 void ClipTransformCUDA
106 #else
107 void ClipTransformCPU
108 #endif
109  (const core::Tensor& src,
110  core::Tensor& dst,
111  float scale,
112  float min_value,
113  float max_value,
114  float clip_fill) {
115  NDArrayIndexer src_indexer(src, 2);
116  NDArrayIndexer dst_indexer(dst, 2);
117 
118  int64_t rows = src.GetShape(0);
119  int64_t cols = dst.GetShape(1);
120  int64_t n = rows * cols;
121 
122  DISPATCH_DTYPE_TO_TEMPLATE(src.GetDtype(), [&]() {
123  core::ParallelFor(src.GetDevice(), n,
124  [=] OPEN3D_DEVICE(int64_t workload_idx) {
125  int64_t y = workload_idx / cols;
126  int64_t x = workload_idx % cols;
127 
128  float in = static_cast<float>(
129  *src_indexer.GetDataPtr<scalar_t>(x, y));
130  float out = in / scale;
131  out = out <= min_value ? clip_fill : out;
132  out = out >= max_value ? clip_fill : out;
133  *dst_indexer.GetDataPtr<float>(x, y) = out;
134  });
135  });
136 }
137 
138 // Reimplementation of the reference:
139 // https://github.com/mp3guy/ICPCUDA/blob/master/Cuda/pyrdown.cu#L41
140 #ifdef __CUDACC__
141 void PyrDownDepthCUDA
142 #else
143 void PyrDownDepthCPU
144 #endif
145  (const core::Tensor& src,
146  core::Tensor& dst,
147  float depth_diff,
148  float invalid_fill) {
149  NDArrayIndexer src_indexer(src, 2);
150  NDArrayIndexer dst_indexer(dst, 2);
151 
152  int rows = src_indexer.GetShape(0);
153  int cols = src_indexer.GetShape(1);
154 
155  int rows_down = dst_indexer.GetShape(0);
156  int cols_down = dst_indexer.GetShape(1);
157  int n = rows_down * cols_down;
158 
159  // Gaussian filter window size
160  // Gaussian filter weights
161  const int gkernel_size = 5;
162  const int gkernel_size_2 = gkernel_size / 2;
163  const float gweights[3] = {0.375f, 0.25f, 0.0625f};
164 
165 #ifndef __CUDACC__
166  using std::abs;
167  using std::max;
168  using std::min;
169 #endif
170 
172  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
173  int y = workload_idx / cols_down;
174  int x = workload_idx % cols_down;
175 
176  int y_src = 2 * y;
177  int x_src = 2 * x;
178 
179  float v_center = *src_indexer.GetDataPtr<float>(x_src, y_src);
180  if (v_center == invalid_fill) {
181  *dst_indexer.GetDataPtr<float>(x, y) = invalid_fill;
182  return;
183  }
184 
185  int x_min = max(0, x_src - gkernel_size_2);
186  int y_min = max(0, y_src - gkernel_size_2);
187 
188  int x_max = min(cols - 1, x_src + gkernel_size_2);
189  int y_max = min(rows - 1, y_src + gkernel_size_2);
190 
191  float v_sum = 0;
192  float w_sum = 0;
193  for (int yk = y_min; yk <= y_max; ++yk) {
194  for (int xk = x_min; xk <= x_max; ++xk) {
195  float v = *src_indexer.GetDataPtr<float>(xk, yk);
196  int dy = abs(yk - y_src);
197  int dx = abs(xk - x_src);
198 
199  if (v != invalid_fill &&
200  abs(v - v_center) < depth_diff) {
201  float w = gweights[dx] * gweights[dy];
202  v_sum += w * v;
203  w_sum += w;
204  }
205  }
206  }
207 
208  *dst_indexer.GetDataPtr<float>(x, y) =
209  w_sum == 0 ? invalid_fill : v_sum / w_sum;
210  });
211 }
212 
213 #ifdef __CUDACC__
214 void CreateVertexMapCUDA
215 #else
217 #endif
218  (const core::Tensor& src,
219  core::Tensor& dst,
220  const core::Tensor& intrinsics,
221  float invalid_fill) {
222  NDArrayIndexer src_indexer(src, 2);
223  NDArrayIndexer dst_indexer(dst, 2);
225  core::Device("CPU:0")));
226 
227  int64_t rows = src.GetShape(0);
228  int64_t cols = src.GetShape(1);
229  int64_t n = rows * cols;
230 
231 #ifndef __CUDACC__
232  using std::isinf;
233  using std::isnan;
234 #endif
235 
237  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
238  auto is_invalid = [invalid_fill] OPEN3D_DEVICE(float v) {
239  if (isinf(invalid_fill)) return isinf(v);
240  if (isnan(invalid_fill)) return isnan(v);
241  return v == invalid_fill;
242  };
243 
244  int64_t y = workload_idx / cols;
245  int64_t x = workload_idx % cols;
246 
247  float d = *src_indexer.GetDataPtr<float>(x, y);
248 
249  float* vertex = dst_indexer.GetDataPtr<float>(x, y);
250  if (!is_invalid(d)) {
251  ti.Unproject(static_cast<float>(x), static_cast<float>(y),
252  d, vertex + 0, vertex + 1, vertex + 2);
253  } else {
254  vertex[0] = invalid_fill;
255  vertex[1] = invalid_fill;
256  vertex[2] = invalid_fill;
257  }
258  });
259 }
260 #ifdef __CUDACC__
261 void CreateNormalMapCUDA
262 #else
264 #endif
265  (const core::Tensor& src, core::Tensor& dst, float invalid_fill) {
266  NDArrayIndexer src_indexer(src, 2);
267  NDArrayIndexer dst_indexer(dst, 2);
268 
269  int64_t rows = src_indexer.GetShape(0);
270  int64_t cols = src_indexer.GetShape(1);
271  int64_t n = rows * cols;
272 
274  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
275  int64_t y = workload_idx / cols;
276  int64_t x = workload_idx % cols;
277 
278  float* normal = dst_indexer.GetDataPtr<float>(x, y);
279 
280  if (y < rows - 1 && x < cols - 1) {
281  float* v00 = src_indexer.GetDataPtr<float>(x, y);
282  float* v10 = src_indexer.GetDataPtr<float>(x + 1, y);
283  float* v01 = src_indexer.GetDataPtr<float>(x, y + 1);
284 
285  if ((v00[0] == invalid_fill && v00[1] == invalid_fill &&
286  v00[2] == invalid_fill) ||
287  (v01[0] == invalid_fill && v01[1] == invalid_fill &&
288  v01[2] == invalid_fill) ||
289  (v10[0] == invalid_fill && v10[1] == invalid_fill &&
290  v10[2] == invalid_fill)) {
291  normal[0] = invalid_fill;
292  normal[1] = invalid_fill;
293  normal[2] = invalid_fill;
294  return;
295  }
296 
297  float dx0 = v01[0] - v00[0];
298  float dy0 = v01[1] - v00[1];
299  float dz0 = v01[2] - v00[2];
300 
301  float dx1 = v10[0] - v00[0];
302  float dy1 = v10[1] - v00[1];
303  float dz1 = v10[2] - v00[2];
304 
305  normal[0] = dy0 * dz1 - dz0 * dy1;
306  normal[1] = dz0 * dx1 - dx0 * dz1;
307  normal[2] = dx0 * dy1 - dy0 * dx1;
308 
309  constexpr float EPSILON = 1e-5f;
310  float normal_norm =
311  sqrt(normal[0] * normal[0] + normal[1] * normal[1] +
312  normal[2] * normal[2]);
313  normal_norm = std::max(normal_norm, EPSILON);
314  normal[0] /= normal_norm;
315  normal[1] /= normal_norm;
316  normal[2] /= normal_norm;
317  } else {
318  normal[0] = invalid_fill;
319  normal[1] = invalid_fill;
320  normal[2] = invalid_fill;
321  }
322  });
323 }
324 
325 #ifdef __CUDACC__
326 void ColorizeDepthCUDA
327 #else
328 void ColorizeDepthCPU
329 #endif
330  (const core::Tensor& src,
331  core::Tensor& dst,
332  float scale,
333  float min_value,
334  float max_value) {
335  NDArrayIndexer src_indexer(src, 2);
336  NDArrayIndexer dst_indexer(dst, 2);
337 
338  int64_t rows = src.GetShape(0);
339  int64_t cols = dst.GetShape(1);
340  int64_t n = rows * cols;
341 
342  float inv_interval = 255.0f / (max_value - min_value);
343  DISPATCH_DTYPE_TO_TEMPLATE(src.GetDtype(), [&]() {
345  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
346  int64_t y = workload_idx / cols;
347  int64_t x = workload_idx % cols;
348 
349  float in = static_cast<float>(
350  *src_indexer.GetDataPtr<scalar_t>(x, y));
351  float out = in / scale;
352  out = out <= min_value ? min_value : out;
353  out = out >= max_value ? max_value : out;
354 
355  int idx =
356  static_cast<int>(inv_interval * (out - min_value));
357  uint8_t* out_ptr = dst_indexer.GetDataPtr<uint8_t>(x, y);
358  out_ptr[0] = turbo_srgb_bytes[idx][0];
359  out_ptr[1] = turbo_srgb_bytes[idx][1];
360  out_ptr[2] = turbo_srgb_bytes[idx][2];
361  });
362  });
363 }
364 
365 } // namespace image
366 } // namespace kernel
367 } // namespace geometry
368 } // namespace t
369 } // namespace open3d
OPEN3D_HOST_DEVICE index_t GetShape(int i) const
Definition: GeometryIndexer.h:330
const Dtype UInt8
Definition: Dtype.cpp:67
void ToCPU(const core::Tensor &src, core::Tensor &dst, double scale, double offset)
Definition: ImageImpl.h:52
Definition: GeometryIndexer.h:180
const Dtype Int64
Definition: Dtype.cpp:66
const char const char value recording_handle imu_sample recording_handle uint8_t size_t data_size k4a_record_configuration_t config target_format k4a_capture_t capture_handle k4a_imu_sample_t imu_sample playback_handle k4a_logging_message_cb_t void min_level device_handle k4a_imu_sample_t timeout_in_ms capture_handle capture_handle capture_handle image_handle temperature_c k4a_image_t image_handle uint8_t image_handle image_handle image_handle image_handle uint32_t
Definition: K4aPlugin.cpp:567
OPEN3D_HOST_DEVICE void * GetDataPtr() const
Definition: GeometryIndexer.h:334
Definition: Dtype.h:39
Helper class for converting coordinates/indices between 3D/3D, 3D/2D, 2D/3D.
Definition: GeometryIndexer.h:44
void ColorizeDepthCPU(const core::Tensor &src, core::Tensor &dst, float scale, float min_value, float max_value)
Definition: ImageImpl.h:330
void ParallelFor(const Device &device, int64_t n, const func_t &func)
Definition: ParallelFor.h:122
const Dtype UInt64
Definition: Dtype.cpp:70
const char const char value recording_handle imu_sample recording_handle uint8_t size_t data_size k4a_record_configuration_t config target_format k4a_capture_t capture_handle k4a_imu_sample_t imu_sample playback_handle k4a_logging_message_cb_t void min_level device_handle k4a_imu_sample_t timeout_in_ms capture_handle capture_handle capture_handle image_handle temperature_c k4a_image_t image_handle uint8_t image_handle image_handle image_handle image_handle image_handle timestamp_usec white_balance image_handle k4a_device_configuration_t config device_handle char size_t serial_number_size bool int32_t int32_t max_value
Definition: K4aPlugin.cpp:658
const char const char value recording_handle imu_sample recording_handle uint8_t size_t data_size k4a_record_configuration_t config target_format k4a_capture_t capture_handle k4a_imu_sample_t imu_sample playback_handle k4a_logging_message_cb_t void min_level device_handle k4a_imu_sample_t int32_t
Definition: K4aPlugin.cpp:408
const Dtype Float32
Definition: Dtype.cpp:61
const char const char value recording_handle imu_sample recording_handle uint8_t size_t data_size k4a_record_configuration_t config target_format k4a_capture_t capture_handle k4a_imu_sample_t imu_sample uint64_t
Definition: K4aPlugin.cpp:362
Dtype GetDtype() const
Definition: Tensor.h:1169
Device GetDevice() const override
Definition: Tensor.cpp:1384
#define OPEN3D_DEVICE
Definition: CUDAUtils.h:64
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:130
const Dtype Int32
Definition: Dtype.cpp:65
const Dtype UInt16
Definition: Dtype.cpp:68
Definition: Device.h:37
int offset
Definition: FilePCD.cpp:64
void PyrDownDepthCPU(const core::Tensor &src, core::Tensor &dst, float diff_threshold, float invalid_fill)
Definition: ImageImpl.h:145
void CreateVertexMapCPU(const core::Tensor &src, core::Tensor &dst, const core::Tensor &intrinsics, float invalid_fill)
Definition: ImageImpl.h:218
void ClipTransformCPU(const core::Tensor &src, core::Tensor &dst, float scale, float min_value, float max_value, float clip_fill=0.0f)
Definition: ImageImpl.h:109
SizeVector GetShape() const
Definition: Tensor.h:1132
#define DISPATCH_DTYPE_TO_TEMPLATE(DTYPE,...)
Definition: Dispatch.h:49
Definition: PinholeCameraIntrinsic.cpp:35
const Dtype Int16
Definition: Dtype.cpp:64
void CreateNormalMapCPU(const core::Tensor &src, core::Tensor &dst, float invalid_fill)
Definition: ImageImpl.h:265
const Dtype UInt32
Definition: Dtype.cpp:69
const Dtype Int8
Definition: Dtype.cpp:63
const Dtype Float64
Definition: Dtype.cpp:62
static Tensor Eye(int64_t n, Dtype dtype, const Device &device)
Create an identity matrix of size n x n.
Definition: Tensor.cpp:404
#define LINEAR_SATURATE(elem_t, calc_t)
Definition: Indexer.h:280
Common CUDA utilities.
const char const char value recording_handle imu_sample recording_handle uint8_t size_t data_size k4a_record_configuration_t config target_format k4a_capture_t capture_handle k4a_imu_sample_t imu_sample playback_handle k4a_logging_message_cb_t void min_level device_handle k4a_imu_sample_t timeout_in_ms capture_handle capture_handle capture_handle image_handle temperature_c k4a_image_t image_handle uint8_t image_handle image_handle image_handle image_handle image_handle timestamp_usec white_balance image_handle k4a_device_configuration_t config device_handle char size_t serial_number_size bool int32_t min_value
Definition: K4aPlugin.cpp:658
std::shared_ptr< core::Tensor > image
Definition: FilamentRenderer.cpp:202