Loading [MathJax]/extensions/TeX/AMSsymbols.js
Open3D (C++ API)  0.14.1
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 "open3d/core/CUDAUtils.h"
28 #include "open3d/core/Dispatch.h"
29 #include "open3d/core/Tensor.h"
32 
33 namespace open3d {
34 namespace t {
35 namespace geometry {
36 namespace kernel {
37 namespace image {
38 
39 #ifndef __CUDACC__
40 using std::isinf;
41 using std::isnan;
42 #endif
43 
44 #ifdef __CUDACC__
45 void ClipTransformCUDA
46 #else
48 #endif
49  (const core::Tensor& src,
50  core::Tensor& dst,
51  float scale,
52  float min_value,
53  float max_value,
54  float clip_fill) {
55  NDArrayIndexer src_indexer(src, 2);
56  NDArrayIndexer dst_indexer(dst, 2);
57 
58  int64_t rows = src.GetShape(0);
59  int64_t cols = dst.GetShape(1);
60  int64_t n = rows * cols;
61 
64  [=] OPEN3D_DEVICE(int64_t workload_idx) {
65  int64_t y = workload_idx / cols;
66  int64_t x = workload_idx % cols;
67 
68  float in = static_cast<float>(
69  *src_indexer.GetDataPtr<scalar_t>(x, y));
70  float out = in / scale;
71  out = out <= min_value ? clip_fill : out;
72  out = out >= max_value ? clip_fill : out;
73  *dst_indexer.GetDataPtr<float>(x, y) = out;
74  });
75  });
76 }
77 
78 // Reimplementation of the reference:
79 // https://github.com/mp3guy/ICPCUDA/blob/master/Cuda/pyrdown.cu#L41
80 #ifdef __CUDACC__
81 void PyrDownDepthCUDA
82 #else
83 void PyrDownDepthCPU
84 #endif
85  (const core::Tensor& src,
86  core::Tensor& dst,
87  float depth_diff,
88  float invalid_fill) {
89  NDArrayIndexer src_indexer(src, 2);
90  NDArrayIndexer dst_indexer(dst, 2);
91 
92  int rows = src_indexer.GetShape(0);
93  int cols = src_indexer.GetShape(1);
94 
95  int rows_down = dst_indexer.GetShape(0);
96  int cols_down = dst_indexer.GetShape(1);
97  int n = rows_down * cols_down;
98 
99  // Gaussian filter window size
100  // Gaussian filter weights
101  const int gkernel_size = 5;
102  const int gkernel_size_2 = gkernel_size / 2;
103  const float gweights[3] = {0.375f, 0.25f, 0.0625f};
104 
105 #ifndef __CUDACC__
106  using std::abs;
107  using std::max;
108  using std::min;
109 #endif
110 
112  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
113  int y = workload_idx / cols_down;
114  int x = workload_idx % cols_down;
115 
116  int y_src = 2 * y;
117  int x_src = 2 * x;
118 
119  float v_center = *src_indexer.GetDataPtr<float>(x_src, y_src);
120  if (v_center == invalid_fill) {
121  *dst_indexer.GetDataPtr<float>(x, y) = invalid_fill;
122  return;
123  }
124 
125  int x_min = max(0, x_src - gkernel_size_2);
126  int y_min = max(0, y_src - gkernel_size_2);
127 
128  int x_max = min(cols - 1, x_src + gkernel_size_2);
129  int y_max = min(rows - 1, y_src + gkernel_size_2);
130 
131  float v_sum = 0;
132  float w_sum = 0;
133  for (int yk = y_min; yk <= y_max; ++yk) {
134  for (int xk = x_min; xk <= x_max; ++xk) {
135  float v = *src_indexer.GetDataPtr<float>(xk, yk);
136  int dy = abs(yk - y_src);
137  int dx = abs(xk - x_src);
138 
139  if (v != invalid_fill &&
140  abs(v - v_center) < depth_diff) {
141  float w = gweights[dx] * gweights[dy];
142  v_sum += w * v;
143  w_sum += w;
144  }
145  }
146  }
147 
148  *dst_indexer.GetDataPtr<float>(x, y) =
149  w_sum == 0 ? invalid_fill : v_sum / w_sum;
150  });
151 }
152 
153 #ifdef __CUDACC__
154 void CreateVertexMapCUDA
155 #else
157 #endif
158  (const core::Tensor& src,
159  core::Tensor& dst,
160  const core::Tensor& intrinsics,
161  float invalid_fill) {
162  NDArrayIndexer src_indexer(src, 2);
163  NDArrayIndexer dst_indexer(dst, 2);
165  core::Device("CPU:0")));
166 
167  int64_t rows = src.GetShape(0);
168  int64_t cols = src.GetShape(1);
169  int64_t n = rows * cols;
170 
171 #ifndef __CUDACC__
172  using std::isinf;
173  using std::isnan;
174 #endif
175 
177  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
178  auto is_invalid = [invalid_fill] OPEN3D_DEVICE(float v) {
179  if (isinf(invalid_fill)) return isinf(v);
180  if (isnan(invalid_fill)) return isnan(v);
181  return v == invalid_fill;
182  };
183 
184  int64_t y = workload_idx / cols;
185  int64_t x = workload_idx % cols;
186 
187  float d = *src_indexer.GetDataPtr<float>(x, y);
188 
189  float* vertex = dst_indexer.GetDataPtr<float>(x, y);
190  if (!is_invalid(d)) {
191  ti.Unproject(static_cast<float>(x), static_cast<float>(y),
192  d, vertex + 0, vertex + 1, vertex + 2);
193  } else {
194  vertex[0] = invalid_fill;
195  vertex[1] = invalid_fill;
196  vertex[2] = invalid_fill;
197  }
198  });
199 }
200 #ifdef __CUDACC__
201 void CreateNormalMapCUDA
202 #else
204 #endif
205  (const core::Tensor& src, core::Tensor& dst, float invalid_fill) {
206  NDArrayIndexer src_indexer(src, 2);
207  NDArrayIndexer dst_indexer(dst, 2);
208 
209  int64_t rows = src_indexer.GetShape(0);
210  int64_t cols = src_indexer.GetShape(1);
211  int64_t n = rows * cols;
212 
214  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
215  int64_t y = workload_idx / cols;
216  int64_t x = workload_idx % cols;
217 
218  float* normal = dst_indexer.GetDataPtr<float>(x, y);
219 
220  if (y < rows - 1 && x < cols - 1) {
221  float* v00 = src_indexer.GetDataPtr<float>(x, y);
222  float* v10 = src_indexer.GetDataPtr<float>(x + 1, y);
223  float* v01 = src_indexer.GetDataPtr<float>(x, y + 1);
224 
225  if ((v00[0] == invalid_fill && v00[1] == invalid_fill &&
226  v00[2] == invalid_fill) ||
227  (v01[0] == invalid_fill && v01[1] == invalid_fill &&
228  v01[2] == invalid_fill) ||
229  (v10[0] == invalid_fill && v10[1] == invalid_fill &&
230  v10[2] == invalid_fill)) {
231  normal[0] = invalid_fill;
232  normal[1] = invalid_fill;
233  normal[2] = invalid_fill;
234  return;
235  }
236 
237  float dx0 = v01[0] - v00[0];
238  float dy0 = v01[1] - v00[1];
239  float dz0 = v01[2] - v00[2];
240 
241  float dx1 = v10[0] - v00[0];
242  float dy1 = v10[1] - v00[1];
243  float dz1 = v10[2] - v00[2];
244 
245  normal[0] = dy0 * dz1 - dz0 * dy1;
246  normal[1] = dz0 * dx1 - dx0 * dz1;
247  normal[2] = dx0 * dy1 - dy0 * dx1;
248 
249  float normal_norm =
250  sqrt(normal[0] * normal[0] + normal[1] * normal[1] +
251  normal[2] * normal[2]);
252  normal[0] /= normal_norm;
253  normal[1] /= normal_norm;
254  normal[2] /= normal_norm;
255  } else {
256  normal[0] = invalid_fill;
257  normal[1] = invalid_fill;
258  normal[2] = invalid_fill;
259  }
260  });
261 }
262 
263 #ifdef __CUDACC__
264 void ColorizeDepthCUDA
265 #else
266 void ColorizeDepthCPU
267 #endif
268  (const core::Tensor& src,
269  core::Tensor& dst,
270  float scale,
271  float min_value,
272  float max_value) {
273  NDArrayIndexer src_indexer(src, 2);
274  NDArrayIndexer dst_indexer(dst, 2);
275 
276  int64_t rows = src.GetShape(0);
277  int64_t cols = dst.GetShape(1);
278  int64_t n = rows * cols;
279 
280  float inv_interval = 255.0f / (max_value - min_value);
281  DISPATCH_DTYPE_TO_TEMPLATE(src.GetDtype(), [&]() {
283  src.GetDevice(), n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
284  int64_t y = workload_idx / cols;
285  int64_t x = workload_idx % cols;
286 
287  float in = static_cast<float>(
288  *src_indexer.GetDataPtr<scalar_t>(x, y));
289  float out = in / scale;
290  out = out <= min_value ? min_value : out;
291  out = out >= max_value ? max_value : out;
292 
293  int idx =
294  static_cast<int>(inv_interval * (out - min_value));
295  uint8_t* out_ptr = dst_indexer.GetDataPtr<uint8_t>(x, y);
296  out_ptr[0] = turbo_srgb_bytes[idx][0];
297  out_ptr[1] = turbo_srgb_bytes[idx][1];
298  out_ptr[2] = turbo_srgb_bytes[idx][2];
299  });
300  });
301 }
302 
303 } // namespace image
304 } // namespace kernel
305 } // namespace geometry
306 } // namespace t
307 } // namespace open3d
OPEN3D_HOST_DEVICE index_t GetShape(int i) const
Definition: GeometryIndexer.h:331
Definition: GeometryIndexer.h:180
OPEN3D_HOST_DEVICE void * GetDataPtr() const
Definition: GeometryIndexer.h:335
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:268
void ParallelFor(const Device &device, int64_t n, const func_t &func)
Definition: ParallelFor.h:122
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:648
Device GetDevice() const
Definition: Tensor.cpp:1365
Dtype GetDtype() const
Definition: Tensor.h:1094
#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
Definition: Device.h:39
void PyrDownDepthCPU(const core::Tensor &src, core::Tensor &dst, float diff_threshold, float invalid_fill)
Definition: ImageImpl.h:85
void CreateVertexMapCPU(const core::Tensor &src, core::Tensor &dst, const core::Tensor &intrinsics, float invalid_fill)
Definition: ImageImpl.h:158
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:49
SizeVector GetShape() const
Definition: Tensor.h:1057
#define DISPATCH_DTYPE_TO_TEMPLATE(DTYPE,...)
Definition: Dispatch.h:49
Definition: PinholeCameraIntrinsic.cpp:35
void CreateNormalMapCPU(const core::Tensor &src, core::Tensor &dst, float invalid_fill)
Definition: ImageImpl.h:205
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:392
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:648
std::shared_ptr< core::Tensor > image
Definition: FilamentRenderer.cpp:228