ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
RGBDOdometry.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
16 
17 namespace cloudViewer {
18 namespace t {
19 namespace pipelines {
20 namespace odometry {
21 
22 using core::Tensor;
23 using t::geometry::Image;
25 
27  const RGBDImage& source,
28  const RGBDImage& target,
29  const Tensor& intrinsics,
30  const Tensor& trans,
31  const float depth_scale,
32  const float depth_max,
33  const std::vector<OdometryConvergenceCriteria>& criteria,
34  const OdometryLossParams& params);
35 
37  const RGBDImage& source,
38  const RGBDImage& target,
39  const Tensor& intrinsic,
40  const Tensor& trans,
41  const float depth_scale,
42  const float depth_max,
43  const std::vector<OdometryConvergenceCriteria>& criteria,
44  const OdometryLossParams& params);
45 
47  const RGBDImage& source,
48  const RGBDImage& target,
49  const Tensor& intrinsics,
50  const Tensor& trans,
51  const float depth_scale,
52  const float depth_max,
53  const std::vector<OdometryConvergenceCriteria>& criteria,
54  const OdometryLossParams& params);
55 
57  const RGBDImage& source,
58  const RGBDImage& target,
59  const Tensor& intrinsics,
60  const Tensor& init_source_to_target,
61  const float depth_scale,
62  const float depth_max,
63  const std::vector<OdometryConvergenceCriteria>& criteria,
64  const Method method,
65  const OdometryLossParams& params) {
66  // TODO (wei): more device check
67  const core::Device device = source.depth_.GetDevice();
68  core::AssertTensorDevice(target.depth_.AsTensor(), device);
69 
70  core::AssertTensorShape(intrinsics, {3, 3});
71  core::AssertTensorShape(init_source_to_target, {4, 4});
72 
73  // 4x4 transformations are always float64 and stay on CPU.
74  const core::Device host("CPU:0");
75  const Tensor intrinsics_d = intrinsics.To(host, core::Float64).Clone();
76  const Tensor trans_d =
77  init_source_to_target.To(host, core::Float64).Clone();
78 
79  Image source_depth = source.depth_;
80  Image target_depth = target.depth_;
81 
82  Image source_depth_processed =
83  source_depth.ClipTransform(depth_scale, 0, depth_max, NAN);
84  Image target_depth_processed =
85  target_depth.ClipTransform(depth_scale, 0, depth_max, NAN);
86 
87  RGBDImage source_processed(source.color_, source_depth_processed);
88  RGBDImage target_processed(target.color_, target_depth_processed);
89 
90  if (method == Method::PointToPlane) {
92  source_processed, target_processed, intrinsics_d, trans_d,
93  depth_scale, depth_max, criteria, params);
94  } else if (method == Method::Intensity) {
96  source_processed, target_processed, intrinsics_d, trans_d,
97  depth_scale, depth_max, criteria, params);
98  } else if (method == Method::Hybrid) {
99  return RGBDOdometryMultiScaleHybrid(source_processed, target_processed,
100  intrinsics_d, trans_d, depth_scale,
101  depth_max, criteria, params);
102  } else {
103  utility::LogError("Odometry method not implemented.");
104  }
105 
106  return OdometryResult(trans_d);
107 }
108 
110  const RGBDImage& source,
111  const RGBDImage& target,
112  const Tensor& intrinsics,
113  const Tensor& trans,
114  const float depth_scale,
115  const float depth_max,
116  const std::vector<OdometryConvergenceCriteria>& criteria,
117  const OdometryLossParams& params) {
118  int64_t n_levels = int64_t(criteria.size());
119  std::vector<Tensor> source_vertex_maps(n_levels);
120  std::vector<Tensor> target_vertex_maps(n_levels);
121  std::vector<Tensor> target_normal_maps(n_levels);
122  std::vector<Tensor> intrinsic_matrices(n_levels);
123 
124  Image source_depth_curr = source.depth_;
125  Image target_depth_curr = target.depth_;
126 
127  Tensor intrinsics_pyr = intrinsics;
128 
129  // Create image pyramid.
130  for (int64_t i = 0; i < n_levels; ++i) {
131  Image source_vertex_map =
132  source_depth_curr.CreateVertexMap(intrinsics_pyr, NAN);
133  Image target_vertex_map =
134  target_depth_curr.CreateVertexMap(intrinsics_pyr, NAN);
135 
136  Image target_depth_curr_smooth =
137  target_depth_curr.FilterBilateral(5, 5, 10);
138  Image target_vertex_map_smooth =
139  target_depth_curr_smooth.CreateVertexMap(intrinsics_pyr, NAN);
140  Image target_normal_map = target_vertex_map_smooth.CreateNormalMap(NAN);
141 
142  source_vertex_maps[n_levels - 1 - i] = source_vertex_map.AsTensor();
143  target_vertex_maps[n_levels - 1 - i] = target_vertex_map.AsTensor();
144  target_normal_maps[n_levels - 1 - i] = target_normal_map.AsTensor();
145 
146  intrinsic_matrices[n_levels - 1 - i] = intrinsics_pyr.Clone();
147 
148  if (i != n_levels - 1) {
149  source_depth_curr = source_depth_curr.PyrDownDepth(
150  params.depth_outlier_trunc_ * 2, NAN);
151  target_depth_curr = target_depth_curr.PyrDownDepth(
152  params.depth_outlier_trunc_ * 2, NAN);
153 
154  intrinsics_pyr /= 2;
155  intrinsics_pyr[-1][-1] = 1;
156  }
157  }
158 
159  OdometryResult result(trans, /*prev rmse*/ 0.0, /*prev fitness*/ 1.0);
160  for (int64_t i = 0; i < n_levels; ++i) {
161  for (int iter = 0; iter < criteria[i].max_iteration_; ++iter) {
162  auto delta_result = ComputeOdometryResultPointToPlane(
163  source_vertex_maps[i], target_vertex_maps[i],
164  target_normal_maps[i], intrinsic_matrices[i],
165  result.transformation_, params.depth_outlier_trunc_,
166  params.depth_huber_delta_);
167  result.transformation_ =
168  delta_result.transformation_.Matmul(result.transformation_);
169  utility::LogDebug("level {}, iter {}: rmse = {}, fitness = {}", i,
170  iter, delta_result.inlier_rmse_,
171  delta_result.fitness_);
172 
173  if (std::abs(result.fitness_ - delta_result.fitness_) /
174  result.fitness_ <
175  criteria[i].relative_fitness_ &&
176  std::abs(result.inlier_rmse_ - delta_result.inlier_rmse_) /
177  result.inlier_rmse_ <
178  criteria[i].relative_rmse_) {
179  utility::LogDebug("Early exit at level {}, iter {}", i, iter);
180  break;
181  }
182  result.inlier_rmse_ = delta_result.inlier_rmse_;
183  result.fitness_ = delta_result.fitness_;
184  }
185  }
186 
187  return result;
188 }
189 
191  const RGBDImage& source,
192  const RGBDImage& target,
193  const Tensor& intrinsics,
194  const Tensor& trans,
195  const float depth_scale,
196  const float depth_max,
197  const std::vector<OdometryConvergenceCriteria>& criteria,
198  const OdometryLossParams& params) {
199  int64_t n_levels = int64_t(criteria.size());
200  std::vector<Tensor> source_intensity(n_levels);
201  std::vector<Tensor> target_intensity(n_levels);
202 
203  std::vector<Tensor> source_depth(n_levels);
204  std::vector<Tensor> target_depth(n_levels);
205  std::vector<Tensor> target_intensity_dx(n_levels);
206  std::vector<Tensor> target_intensity_dy(n_levels);
207 
208  std::vector<Tensor> source_vertex_maps(n_levels);
209 
210  std::vector<Tensor> intrinsic_matrices(n_levels);
211 
212  Image source_depth_curr = source.depth_;
213  Image target_depth_curr = target.depth_;
214 
215  Image source_intensity_curr = source.color_.RGBToGray().To(core::Float32);
216  Image target_intensity_curr = target.color_.RGBToGray().To(core::Float32);
217 
218  Tensor intrinsics_pyr = intrinsics;
219 
220  // Create image pyramid
221  for (int64_t i = 0; i < n_levels; ++i) {
222  source_depth[n_levels - 1 - i] = source_depth_curr.AsTensor().Clone();
223  target_depth[n_levels - 1 - i] = target_depth_curr.AsTensor().Clone();
224 
225  source_intensity[n_levels - 1 - i] =
226  source_intensity_curr.AsTensor().Clone();
227  target_intensity[n_levels - 1 - i] =
228  target_intensity_curr.AsTensor().Clone();
229 
230  Image source_vertex_map =
231  source_depth_curr.CreateVertexMap(intrinsics_pyr, NAN);
232  source_vertex_maps[n_levels - 1 - i] = source_vertex_map.AsTensor();
233 
234  auto target_intensity_grad = target_intensity_curr.FilterSobel();
235  target_intensity_dx[n_levels - 1 - i] =
236  target_intensity_grad.first.AsTensor();
237  target_intensity_dy[n_levels - 1 - i] =
238  target_intensity_grad.second.AsTensor();
239 
240  intrinsic_matrices[n_levels - 1 - i] = intrinsics_pyr.Clone();
241 
242  if (i != n_levels - 1) {
243  source_depth_curr = source_depth_curr.PyrDownDepth(
244  params.depth_outlier_trunc_ * 2, NAN);
245  target_depth_curr = target_depth_curr.PyrDownDepth(
246  params.depth_outlier_trunc_ * 2, NAN);
247  source_intensity_curr = source_intensity_curr.PyrDown();
248  target_intensity_curr = target_intensity_curr.PyrDown();
249 
250  intrinsics_pyr /= 2;
251  intrinsics_pyr[-1][-1] = 1;
252  }
253  }
254 
255  // Odometry
256  OdometryResult result(trans, /*prev rmse*/ 0.0, /*prev fitness*/ 1.0);
257  for (int64_t i = 0; i < n_levels; ++i) {
258  for (int iter = 0; iter < criteria[i].max_iteration_; ++iter) {
259  auto delta_result = ComputeOdometryResultIntensity(
260  source_depth[i], target_depth[i], source_intensity[i],
261  target_intensity[i], target_intensity_dx[i],
262  target_intensity_dy[i], source_vertex_maps[i],
263  intrinsic_matrices[i], result.transformation_,
264  params.depth_outlier_trunc_, params.intensity_huber_delta_);
265  result.transformation_ =
266  delta_result.transformation_.Matmul(result.transformation_);
267  utility::LogDebug("level {}, iter {}: rmse = {}, fitness = {}", i,
268  iter, delta_result.inlier_rmse_,
269  delta_result.fitness_);
270 
271  if (std::abs(result.fitness_ - delta_result.fitness_) /
272  result.fitness_ <
273  criteria[i].relative_fitness_ &&
274  std::abs(result.inlier_rmse_ - delta_result.inlier_rmse_) /
275  result.inlier_rmse_ <
276  criteria[i].relative_rmse_) {
277  utility::LogDebug("Early exit at level {}, iter {}", i, iter);
278  break;
279  }
280  result.inlier_rmse_ = delta_result.inlier_rmse_;
281  result.fitness_ = delta_result.fitness_;
282  }
283  }
284 
285  return result;
286 }
287 
289  const RGBDImage& source,
290  const RGBDImage& target,
291  const Tensor& intrinsics,
292  const Tensor& trans,
293  const float depth_scale,
294  const float depth_max,
295  const std::vector<OdometryConvergenceCriteria>& criteria,
296  const OdometryLossParams& params) {
297  int64_t n_levels = int64_t(criteria.size());
298  std::vector<Tensor> source_intensity(n_levels);
299  std::vector<Tensor> target_intensity(n_levels);
300 
301  std::vector<Tensor> source_depth(n_levels);
302  std::vector<Tensor> target_depth(n_levels);
303  std::vector<Tensor> target_intensity_dx(n_levels);
304  std::vector<Tensor> target_intensity_dy(n_levels);
305 
306  std::vector<Tensor> target_depth_dx(n_levels);
307  std::vector<Tensor> target_depth_dy(n_levels);
308 
309  std::vector<Tensor> source_vertex_maps(n_levels);
310 
311  std::vector<Tensor> intrinsic_matrices(n_levels);
312 
313  Image source_depth_curr(source.depth_);
314  Image target_depth_curr(target.depth_);
315 
316  Image source_intensity_curr = source.color_.RGBToGray().To(core::Float32);
317  Image target_intensity_curr = target.color_.RGBToGray().To(core::Float32);
318 
319  Tensor intrinsics_pyr = intrinsics;
320  // Create image pyramid
321  for (int64_t i = 0; i < n_levels; ++i) {
322  source_depth[n_levels - 1 - i] = source_depth_curr.AsTensor().Clone();
323  target_depth[n_levels - 1 - i] = target_depth_curr.AsTensor().Clone();
324 
325  source_intensity[n_levels - 1 - i] =
326  source_intensity_curr.AsTensor().Clone();
327  target_intensity[n_levels - 1 - i] =
328  target_intensity_curr.AsTensor().Clone();
329 
330  Image source_vertex_map =
331  source_depth_curr.CreateVertexMap(intrinsics_pyr, NAN);
332  source_vertex_maps[n_levels - 1 - i] = source_vertex_map.AsTensor();
333 
334  auto target_intensity_grad = target_intensity_curr.FilterSobel();
335  target_intensity_dx[n_levels - 1 - i] =
336  target_intensity_grad.first.AsTensor();
337  target_intensity_dy[n_levels - 1 - i] =
338  target_intensity_grad.second.AsTensor();
339 
340  auto target_depth_grad = target_depth_curr.FilterSobel();
341  target_depth_dx[n_levels - 1 - i] = target_depth_grad.first.AsTensor();
342  target_depth_dy[n_levels - 1 - i] = target_depth_grad.second.AsTensor();
343 
344  intrinsic_matrices[n_levels - 1 - i] = intrinsics_pyr.Clone();
345  if (i != n_levels - 1) {
346  source_depth_curr = source_depth_curr.PyrDownDepth(
347  params.depth_outlier_trunc_ * 2, NAN);
348  target_depth_curr = target_depth_curr.PyrDownDepth(
349  params.depth_outlier_trunc_ * 2, NAN);
350  source_intensity_curr = source_intensity_curr.PyrDown();
351  target_intensity_curr = target_intensity_curr.PyrDown();
352 
353  intrinsics_pyr /= 2;
354  intrinsics_pyr[-1][-1] = 1;
355  }
356  }
357 
358  // Odometry
359  OdometryResult result(trans, /*prev rmse*/ 0.0, /*prev fitness*/ 1.0);
360  for (int64_t i = 0; i < n_levels; ++i) {
361  for (int iter = 0; iter < criteria[i].max_iteration_; ++iter) {
362  auto delta_result = ComputeOdometryResultHybrid(
363  source_depth[i], target_depth[i], source_intensity[i],
364  target_intensity[i], target_depth_dx[i], target_depth_dy[i],
365  target_intensity_dx[i], target_intensity_dy[i],
366  source_vertex_maps[i], intrinsic_matrices[i],
367  result.transformation_, params.depth_outlier_trunc_,
368  params.depth_huber_delta_, params.intensity_huber_delta_);
369  result.transformation_ =
370  delta_result.transformation_.Matmul(result.transformation_);
371  utility::LogDebug("level {}, iter {}: rmse = {}, fitness = {}", i,
372  iter, delta_result.inlier_rmse_,
373  delta_result.fitness_);
374 
375  if (std::abs(result.fitness_ - delta_result.fitness_) /
376  result.fitness_ <
377  criteria[i].relative_fitness_ &&
378  std::abs(result.inlier_rmse_ - delta_result.inlier_rmse_) /
379  result.inlier_rmse_ <
380  criteria[i].relative_rmse_) {
381  utility::LogDebug("Early exit at level {}, iter {}", i, iter);
382  break;
383  }
384  result.inlier_rmse_ = delta_result.inlier_rmse_;
385  result.fitness_ = delta_result.fitness_;
386  }
387  }
388 
389  return result;
390 }
391 
393  const Tensor& source_vertex_map,
394  const Tensor& target_vertex_map,
395  const Tensor& target_normal_map,
396  const Tensor& intrinsics,
397  const Tensor& init_source_to_target,
398  const float depth_outlier_trunc,
399  const float depth_huber_delta) {
400  // Delta target_to_source on host.
401  Tensor se3_delta;
402  float inlier_residual;
403  int inlier_count;
405  source_vertex_map, target_vertex_map, target_normal_map, intrinsics,
406  init_source_to_target, se3_delta, inlier_residual, inlier_count,
407  depth_outlier_trunc, depth_huber_delta);
408  // Check inlier_count, source_vertex_map's shape is non-zero guaranteed.
409  if (inlier_count <= 0) {
410  utility::LogError("Invalid inlier_count value {}, must be > 0.",
411  inlier_count);
412  }
413  return OdometryResult(
415  inlier_residual / inlier_count,
416  double(inlier_count) / double(source_vertex_map.GetShape(0) *
417  source_vertex_map.GetShape(1)));
418 }
419 
421  const Tensor& source_depth,
422  const Tensor& target_depth,
423  const Tensor& source_intensity,
424  const Tensor& target_intensity,
425  const Tensor& target_intensity_dx,
426  const Tensor& target_intensity_dy,
427  const Tensor& source_vertex_map,
428  const Tensor& intrinsics,
429  const Tensor& init_source_to_target,
430  const float depth_outlier_trunc,
431  const float intensity_huber_delta) {
432  // Delta target_to_source on host.
433  Tensor se3_delta;
434  float inlier_residual;
435  int inlier_count;
437  source_depth, target_depth, source_intensity, target_intensity,
438  target_intensity_dx, target_intensity_dy, source_vertex_map,
439  intrinsics, init_source_to_target, se3_delta, inlier_residual,
440  inlier_count, depth_outlier_trunc, intensity_huber_delta);
441  // Check inlier_count, source_vertex_map's shape is non-zero guaranteed.
442  if (inlier_count <= 0) {
443  utility::LogError("Invalid inlier_count value {}, must be > 0.",
444  inlier_count);
445  }
446  return OdometryResult(
448  inlier_residual / inlier_count,
449  double(inlier_count) / double(source_vertex_map.GetShape(0) *
450  source_vertex_map.GetShape(1)));
451 }
452 
454  const Tensor& target_depth,
455  const Tensor& source_intensity,
456  const Tensor& target_intensity,
457  const Tensor& target_depth_dx,
458  const Tensor& target_depth_dy,
459  const Tensor& target_intensity_dx,
460  const Tensor& target_intensity_dy,
461  const Tensor& source_vertex_map,
462  const Tensor& intrinsics,
463  const Tensor& init_source_to_target,
464  const float depth_outlier_trunc,
465  const float depth_huber_delta,
466  const float intensity_huber_delta) {
467  // Delta target_to_source on host.
468  Tensor se3_delta;
469  float inlier_residual;
470  int inlier_count;
472  source_depth, target_depth, source_intensity, target_intensity,
473  target_depth_dx, target_depth_dy, target_intensity_dx,
474  target_intensity_dy, source_vertex_map, intrinsics,
475  init_source_to_target, se3_delta, inlier_residual, inlier_count,
476  depth_outlier_trunc, depth_huber_delta, intensity_huber_delta);
477  // Check inlier_count, source_vertex_map's shape is non-zero guaranteed.
478  if (inlier_count <= 0) {
479  utility::LogError("Invalid inlier_count value {}, must be > 0.",
480  inlier_count);
481  }
482  return OdometryResult(
484  inlier_residual / inlier_count,
485  double(inlier_count) / double(source_vertex_map.GetShape(0) *
486  source_vertex_map.GetShape(1)));
487 }
488 
490  const geometry::Image& source_depth,
491  const geometry::Image& target_depth,
492  const core::Tensor& intrinsic,
493  const core::Tensor& source_to_target,
494  const float dist_thr,
495  const float depth_scale,
496  const float depth_max) {
497  core::Tensor information;
498 
499  Image source_depth_processed =
500  source_depth.ClipTransform(depth_scale, 0, depth_max, NAN);
501  Image target_depth_processed =
502  target_depth.ClipTransform(depth_scale, 0, depth_max, NAN);
503  Image source_vertex_map =
504  Image(source_depth_processed).CreateVertexMap(intrinsic, NAN);
505  Image target_vertex_map =
506  Image(target_depth_processed).CreateVertexMap(intrinsic, NAN);
507 
509  source_vertex_map.AsTensor(), target_vertex_map.AsTensor(),
510  intrinsic, source_to_target, dist_thr * dist_thr, information);
511  return information;
512 }
513 
514 } // namespace odometry
515 } // namespace pipelines
516 } // namespace t
517 } // namespace cloudViewer
cmdLineReadable * params[]
#define AssertTensorDevice(tensor,...)
Definition: TensorCheck.h:45
#define AssertTensorShape(tensor,...)
Definition: TensorCheck.h:61
core::Tensor result
Definition: VtkUtils.cpp:76
Tensor Clone() const
Copy Tensor to the same device.
Definition: Tensor.h:502
SizeVector GetShape() const
Definition: Tensor.h:1127
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
The Image class stores image with customizable rows, cols, channels, dtype and device.
Definition: Image.h:29
Image ClipTransform(float scale, float min_value, float max_value, float clip_fill=0.0f) const
Return new image after scaling and clipping image values.
Definition: Image.cpp:417
Image PyrDown() const
Return a new downsampled image with pyramid downsampling.
Definition: Image.cpp:395
Image PyrDownDepth(float diff_threshold, float invalid_fill=0.f) const
Edge and invalid value preserving downsampling by 2 specifically for depth images.
Definition: Image.cpp:400
Image CreateVertexMap(const core::Tensor &intrinsics, float invalid_fill=0.0f)
Create a vertex map from a depth image using unprojection.
Definition: Image.cpp:449
core::Device GetDevice() const override
Get device of the image.
Definition: Image.h:96
Image RGBToGray() const
Converts a 3-channel RGB image to a new 1-channel Grayscale image.
Definition: Image.cpp:120
Image To(const core::Device &device, bool copy=false) const
Transfer the image to a specified device.
Definition: Image.h:132
Image CreateNormalMap(float invalid_fill=0.0f)
Create a normal map from a vertex map.
Definition: Image.cpp:467
std::pair< Image, Image > FilterSobel(int kernel_size=3) const
Return a pair of new gradient images (dx, dy) after Sobel filtering.
Definition: Image.cpp:345
core::Tensor AsTensor() const
Returns the underlying Tensor of the Image.
Definition: Image.h:124
Image FilterBilateral(int kernel_size=3, float value_sigma=20.0f, float distance_sigma=10.0f) const
Return a new image after bilateral filtering.
Definition: Image.cpp:239
RGBDImage A pair of color and depth images.
Definition: RGBDImage.h:21
Image depth_
The depth image.
Definition: RGBDImage.h:106
Image color_
The color image.
Definition: RGBDImage.h:104
#define LogError(...)
Definition: Logging.h:60
#define LogDebug(...)
Definition: Logging.h:90
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
const Dtype Float64
Definition: Dtype.cpp:43
const Dtype Float32
Definition: Dtype.cpp:42
void ComputeOdometryResultIntensity(const core::Tensor &source_depth, const core::Tensor &target_depth, const core::Tensor &source_intensity, const core::Tensor &target_intensity, const core::Tensor &target_intensity_dx, const core::Tensor &target_intensity_dy, const core::Tensor &source_vertex_map, const core::Tensor &intrinsics, const core::Tensor &init_source_to_target, core::Tensor &delta, float &inlier_residual, int &inlier_count, const float depth_outlier_trunc, const float intensity_huber_delta)
void ComputeOdometryResultPointToPlane(const core::Tensor &source_vertex_map, const core::Tensor &target_vertex_map, const core::Tensor &target_normal_map, const core::Tensor &intrinsics, const core::Tensor &init_source_to_target, core::Tensor &delta, float &inlier_residual, int &inlier_count, const float depth_outlier_trunc, const float depth_huber_delta)
void ComputeOdometryInformationMatrix(const core::Tensor &source_vertex_map, const core::Tensor &target_vertex_map, const core::Tensor &intrinsic, const core::Tensor &source_to_target, const float square_dist_thr, core::Tensor &information)
void ComputeOdometryResultHybrid(const core::Tensor &source_depth, const core::Tensor &target_depth, const core::Tensor &source_intensity, const core::Tensor &target_intensity, const core::Tensor &target_depth_dx, const core::Tensor &target_depth_dy, const core::Tensor &target_intensity_dx, const core::Tensor &target_intensity_dy, const core::Tensor &source_vertex_map, const core::Tensor &intrinsics, const core::Tensor &init_source_to_target, core::Tensor &delta, float &inlier_residual, int &inlier_count, const float depth_outlier_trunc, const float depth_huber_delta, const float intensity_huber_delta)
core::Tensor PoseToTransformation(const core::Tensor &pose)
Convert pose to the transformation matrix.
OdometryResult RGBDOdometryMultiScale(const RGBDImage &source, const RGBDImage &target, const Tensor &intrinsics, const Tensor &init_source_to_target, const float depth_scale, const float depth_max, const std::vector< OdometryConvergenceCriteria > &criteria, const Method method, const OdometryLossParams &params)
Create an RGBD image pyramid given the original source and target RGBD images, and perform hierarchic...
OdometryResult RGBDOdometryMultiScalePointToPlane(const RGBDImage &source, const RGBDImage &target, const Tensor &intrinsics, const Tensor &trans, const float depth_scale, const float depth_max, const std::vector< OdometryConvergenceCriteria > &criteria, const OdometryLossParams &params)
core::Tensor ComputeOdometryInformationMatrix(const geometry::Image &source_depth, const geometry::Image &target_depth, const core::Tensor &intrinsic, const core::Tensor &source_to_target, const float dist_thr, const float depth_scale, const float depth_max)
OdometryResult RGBDOdometryMultiScaleIntensity(const RGBDImage &source, const RGBDImage &target, const Tensor &intrinsic, const Tensor &trans, const float depth_scale, const float depth_max, const std::vector< OdometryConvergenceCriteria > &criteria, const OdometryLossParams &params)
OdometryResult RGBDOdometryMultiScaleHybrid(const RGBDImage &source, const RGBDImage &target, const Tensor &intrinsics, const Tensor &trans, const float depth_scale, const float depth_max, const std::vector< OdometryConvergenceCriteria > &criteria, const OdometryLossParams &params)
OdometryResult ComputeOdometryResultPointToPlane(const Tensor &source_vertex_map, const Tensor &target_vertex_map, const Tensor &target_normal_map, const Tensor &intrinsics, const Tensor &init_source_to_target, const float depth_outlier_trunc, const float depth_huber_delta)
Estimates the 4x4 rigid transformation T from source to target, with inlier rmse and fitness....
OdometryResult ComputeOdometryResultHybrid(const Tensor &source_depth, const Tensor &target_depth, const Tensor &source_intensity, const Tensor &target_intensity, const Tensor &target_depth_dx, const Tensor &target_depth_dy, const Tensor &target_intensity_dx, const Tensor &target_intensity_dy, const Tensor &source_vertex_map, const Tensor &intrinsics, const Tensor &init_source_to_target, const float depth_outlier_trunc, const float depth_huber_delta, const float intensity_huber_delta)
Estimates the 4x4 rigid transformation T from source to target, with inlier rmse and fitness....
OdometryResult ComputeOdometryResultIntensity(const Tensor &source_depth, const Tensor &target_depth, const Tensor &source_intensity, const Tensor &target_intensity, const Tensor &target_intensity_dx, const Tensor &target_intensity_dy, const Tensor &source_vertex_map, const Tensor &intrinsics, const Tensor &init_source_to_target, const float depth_outlier_trunc, const float intensity_huber_delta)
Estimates the 4x4 rigid transformation T from source to target, with inlier rmse and fitness....
Generic file read and write utility for python interface.