Open3D (C++ API)  0.13.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 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 
62 #if defined(__CUDACC__)
63  core::kernel::CUDALauncher launcher;
64 #else
66 #endif
67 
69  launcher.LaunchGeneralKernel(
70  n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
71  int64_t y = workload_idx / cols;
72  int64_t x = workload_idx % cols;
73 
74  float in = static_cast<float>(
75  *src_indexer.GetDataPtr<scalar_t>(x, y));
76  float out = in / scale;
77  out = out <= min_value ? clip_fill : out;
78  out = out >= max_value ? clip_fill : out;
79  *dst_indexer.GetDataPtr<float>(x, y) = out;
80  });
81  });
82 }
83 
84 // Reimplementation of the reference:
85 // https://github.com/mp3guy/ICPCUDA/blob/master/Cuda/pyrdown.cu#L41
86 #ifdef __CUDACC__
87 void PyrDownDepthCUDA
88 #else
89 void PyrDownDepthCPU
90 #endif
91  (const core::Tensor& src,
92  core::Tensor& dst,
93  float depth_diff,
94  float invalid_fill) {
95  NDArrayIndexer src_indexer(src, 2);
96  NDArrayIndexer dst_indexer(dst, 2);
97 
98  int rows = src_indexer.GetShape(0);
99  int cols = src_indexer.GetShape(1);
100 
101  int rows_down = dst_indexer.GetShape(0);
102  int cols_down = dst_indexer.GetShape(1);
103  int n = rows_down * cols_down;
104 
105  // Gaussian filter window size
106  // Gaussian filter weights
107  const int gkernel_size = 5;
108  const int gkernel_size_2 = gkernel_size / 2;
109  const float gweights[3] = {0.375f, 0.25f, 0.0625f};
110 
111 #if defined(__CUDACC__)
112  core::kernel::CUDALauncher launcher;
113 #else
114  core::kernel::CPULauncher launcher;
115  using std::abs;
116  using std::max;
117  using std::min;
118 #endif
119 
120  launcher.LaunchGeneralKernel(n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
121  int y = workload_idx / cols_down;
122  int x = workload_idx % cols_down;
123 
124  int y_src = 2 * y;
125  int x_src = 2 * x;
126 
127  float v_center = *src_indexer.GetDataPtr<float>(x_src, y_src);
128  if (v_center == invalid_fill) {
129  *dst_indexer.GetDataPtr<float>(x, y) = invalid_fill;
130  return;
131  }
132 
133  int x_min = max(0, x_src - gkernel_size_2);
134  int y_min = max(0, y_src - gkernel_size_2);
135 
136  int x_max = min(cols - 1, x_src + gkernel_size_2);
137  int y_max = min(rows - 1, y_src + gkernel_size_2);
138 
139  float v_sum = 0;
140  float w_sum = 0;
141  for (int yk = y_min; yk <= y_max; ++yk) {
142  for (int xk = x_min; xk <= x_max; ++xk) {
143  float v = *src_indexer.GetDataPtr<float>(xk, yk);
144  int dy = abs(yk - y_src);
145  int dx = abs(xk - x_src);
146 
147  if (v != invalid_fill && abs(v - v_center) < depth_diff) {
148  float w = gweights[dx] * gweights[dy];
149  v_sum += w * v;
150  w_sum += w;
151  }
152  }
153  }
154 
155  *dst_indexer.GetDataPtr<float>(x, y) = v_sum / w_sum;
156  });
157 }
158 
159 #ifdef __CUDACC__
160 void CreateVertexMapCUDA
161 #else
163 #endif
164  (const core::Tensor& src,
165  core::Tensor& dst,
166  const core::Tensor& intrinsics,
167  float invalid_fill) {
168  NDArrayIndexer src_indexer(src, 2);
169  NDArrayIndexer dst_indexer(dst, 2);
171  core::Device("CPU:0")));
172 
173  int64_t rows = src.GetShape(0);
174  int64_t cols = src.GetShape(1);
175  int64_t n = rows * cols;
176 
177 #if defined(__CUDACC__)
178  core::kernel::CUDALauncher launcher;
179 #else
180  core::kernel::CPULauncher launcher;
181  using std::isinf;
182  using std::isnan;
183 #endif
184  launcher.LaunchGeneralKernel(n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
185  auto is_invalid = [invalid_fill] OPEN3D_DEVICE(float v) {
186  if (isinf(invalid_fill)) return isinf(v);
187  if (isnan(invalid_fill)) return isnan(v);
188  return v == invalid_fill;
189  };
190 
191  int64_t y = workload_idx / cols;
192  int64_t x = workload_idx % cols;
193 
194  float d = *src_indexer.GetDataPtr<float>(x, y);
195 
196  float* vertex = dst_indexer.GetDataPtr<float>(x, y);
197  if (!is_invalid(d)) {
198  ti.Unproject(static_cast<float>(x), static_cast<float>(y), d,
199  vertex + 0, vertex + 1, vertex + 2);
200  } else {
201  vertex[0] = invalid_fill;
202  vertex[1] = invalid_fill;
203  vertex[2] = invalid_fill;
204  }
205  });
206 }
207 #ifdef __CUDACC__
208 void CreateNormalMapCUDA
209 #else
211 #endif
212  (const core::Tensor& src, core::Tensor& dst, float invalid_fill) {
213  NDArrayIndexer src_indexer(src, 2);
214  NDArrayIndexer dst_indexer(dst, 2);
215 
216  int64_t rows = src_indexer.GetShape(0);
217  int64_t cols = src_indexer.GetShape(1);
218  int64_t n = rows * cols;
219 
220 #if defined(__CUDACC__)
221  core::kernel::CUDALauncher launcher;
222 #else
223  core::kernel::CPULauncher launcher;
224 #endif
225 
226  launcher.LaunchGeneralKernel(n, [=] OPEN3D_DEVICE(int64_t workload_idx) {
227  int64_t y = workload_idx / cols;
228  int64_t x = workload_idx % cols;
229 
230  float* normal = dst_indexer.GetDataPtr<float>(x, y);
231 
232  if (y < rows - 1 && x < cols - 1) {
233  float* v00 = src_indexer.GetDataPtr<float>(x, y);
234  float* v10 = src_indexer.GetDataPtr<float>(x + 1, y);
235  float* v01 = src_indexer.GetDataPtr<float>(x, y + 1);
236 
237  if ((v00[0] == invalid_fill && v00[1] == invalid_fill &&
238  v00[2] == invalid_fill) ||
239  (v01[0] == invalid_fill && v01[1] == invalid_fill &&
240  v01[2] == invalid_fill) ||
241  (v10[0] == invalid_fill && v10[1] == invalid_fill &&
242  v10[2] == invalid_fill)) {
243  normal[0] = invalid_fill;
244  normal[1] = invalid_fill;
245  normal[2] = invalid_fill;
246  return;
247  }
248 
249  float dx0 = v01[0] - v00[0];
250  float dy0 = v01[1] - v00[1];
251  float dz0 = v01[2] - v00[2];
252 
253  float dx1 = v10[0] - v00[0];
254  float dy1 = v10[1] - v00[1];
255  float dz1 = v10[2] - v00[2];
256 
257  normal[0] = dy0 * dz1 - dz0 * dy1;
258  normal[1] = dz0 * dx1 - dx0 * dz1;
259  normal[2] = dx0 * dy1 - dy0 * dx1;
260 
261  float normal_norm =
262  sqrt(normal[0] * normal[0] + normal[1] * normal[1] +
263  normal[2] * normal[2]);
264  normal[0] /= normal_norm;
265  normal[1] /= normal_norm;
266  normal[2] /= normal_norm;
267  } else {
268  normal[0] = invalid_fill;
269  normal[1] = invalid_fill;
270  normal[2] = invalid_fill;
271  }
272  });
273 }
274 
275 #ifdef __CUDACC__
276 void ColorizeDepthCUDA
277 #else
278 void ColorizeDepthCPU
279 #endif
280  (const core::Tensor& src,
281  core::Tensor& dst,
282  float scale,
283  float min_value,
284  float max_value) {
285  NDArrayIndexer src_indexer(src, 2);
286  NDArrayIndexer dst_indexer(dst, 2);
287 
288  int64_t rows = src.GetShape(0);
289  int64_t cols = dst.GetShape(1);
290  int64_t n = rows * cols;
291 
292 #if defined(__CUDACC__)
293  core::kernel::CUDALauncher launcher;
294 #else
295  core::kernel::CPULauncher launcher;
296 #endif
297 
298  float inv_interval = 255.0f / (max_value - min_value);
299  DISPATCH_DTYPE_TO_TEMPLATE(src.GetDtype(), [&]() {
300  launcher.LaunchGeneralKernel(n, [=] OPEN3D_DEVICE(
301  int64_t workload_idx) {
302  int64_t y = workload_idx / cols;
303  int64_t x = workload_idx % cols;
304 
305  float in =
306  static_cast<float>(*src_indexer.GetDataPtr<scalar_t>(x, y));
307  float out = in / scale;
308  out = out <= min_value ? min_value : out;
309  out = out >= max_value ? max_value : out;
310 
311  int idx = static_cast<int>(inv_interval * (out - min_value));
312  uint8_t* out_ptr = dst_indexer.GetDataPtr<uint8_t>(x, y);
313  out_ptr[0] = turbo_srgb_bytes[idx][0];
314  out_ptr[1] = turbo_srgb_bytes[idx][1];
315  out_ptr[2] = turbo_srgb_bytes[idx][2];
316  });
317  });
318 }
319 
320 } // namespace image
321 } // namespace kernel
322 } // namespace geometry
323 } // namespace t
324 } // namespace open3d
Definition: GeometryIndexer.h:168
Definition: CPULauncher.h:42
Helper class for converting coordinates/indices between 3D/3D, 3D/2D, 2D/3D.
Definition: GeometryIndexer.h:42
void ColorizeDepthCPU(const core::Tensor &src, core::Tensor &dst, float scale, float min_value, float max_value)
Definition: ImageImpl.h:280
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
Dtype GetDtype() const
Definition: Tensor.h:1025
#define OPEN3D_DEVICE
Definition: CUDAUtils.h:57
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 T * GetDataPtr(int64_t x) const
Definition: GeometryIndexer.h:324
Definition: Device.h:39
OPEN3D_HOST_DEVICE int64_t GetShape(int i) const
Definition: GeometryIndexer.h:319
void PyrDownDepthCPU(const core::Tensor &src, core::Tensor &dst, float diff_threshold, float invalid_fill)
Definition: ImageImpl.h:91
void CreateVertexMapCPU(const core::Tensor &src, core::Tensor &dst, const core::Tensor &intrinsics, float invalid_fill)
Definition: ImageImpl.h:164
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
static void LaunchGeneralKernel(int64_t n, func_t element_kernel)
General kernels with non-conventional indexers.
Definition: CPULauncher.h:176
SizeVector GetShape() const
Definition: Tensor.h:988
#define DISPATCH_DTYPE_TO_TEMPLATE(DTYPE,...)
Definition: Dispatch.h:49
Definition: PinholeCameraIntrinsic.cpp:35
Definition: Tensor.h:50
void CreateNormalMapCPU(const core::Tensor &src, core::Tensor &dst, float invalid_fill)
Definition: ImageImpl.h:212
static Tensor Eye(int64_t n, Dtype dtype, const Device &device)
Create an identity matrix of size n x n.
Definition: Tensor.cpp:252
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
static const Dtype Float64
Definition: Dtype.h:43
#define max(x, y)
Definition: SVD3x3CPU.h:38
std::shared_ptr< core::Tensor > image
Definition: FilamentRenderer.cpp:228