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 
10 #include <benchmark/benchmark.h>
11 
20 
21 namespace cloudViewer {
22 namespace t {
23 namespace pipelines {
24 namespace odometry {
25 
29  auto focal_length = intrinsic.GetFocalLength();
30  auto principal_point = intrinsic.GetPrincipalPoint();
31  return core::Tensor::Init<double>(
32  {{(focal_length.first), 0, (principal_point.first)},
33  {0, (focal_length.second), (principal_point.second)},
34  {0, 0, 1}});
35 }
36 
37 static void ComputeOdometryResultPointToPlane(benchmark::State& state,
38  const core::Device& device) {
39  if (!t::geometry::Image::HAVE_IPP && device.IsCPU()) {
40  return;
41  }
42 
43  const float depth_scale = 1000.0;
44  const float depth_diff = 0.07;
45  const float depth_max = 3.0;
46 
47  data::SampleRedwoodRGBDImages redwood_data;
48  t::geometry::Image src_depth =
49  *t::io::CreateImageFromFile(redwood_data.GetDepthPaths()[0]);
50  t::geometry::Image dst_depth =
51  *t::io::CreateImageFromFile(redwood_data.GetDepthPaths()[2]);
52 
53  src_depth = src_depth.To(device);
54  dst_depth = dst_depth.To(device);
55 
56  core::Tensor intrinsic_t = CreateIntrisicTensor();
57  t::geometry::Image src_depth_processed =
58  src_depth.ClipTransform(depth_scale, 0.0, depth_max, NAN);
59  t::geometry::Image src_vertex_map =
60  src_depth_processed.CreateVertexMap(intrinsic_t, NAN);
61  t::geometry::Image src_normal_map = src_vertex_map.CreateNormalMap(NAN);
62 
63  t::geometry::Image dst_depth_processed =
64  dst_depth.ClipTransform(depth_scale, 0.0, depth_max, NAN);
65  t::geometry::Image dst_vertex_map =
66  dst_depth_processed.CreateVertexMap(intrinsic_t, NAN);
67 
68  core::Tensor trans =
70 
71  for (int i = 0; i < 20; ++i) {
73  src_vertex_map.AsTensor(), dst_vertex_map.AsTensor(),
74  src_normal_map.AsTensor(), intrinsic_t, trans, depth_diff,
75  depth_diff * 0.5);
76  trans = result.transformation_.Matmul(trans).Contiguous();
77  }
78 
79  for (auto _ : state) {
80  core::Tensor trans =
82 
83  for (int i = 0; i < 20; ++i) {
84  auto result =
86  src_vertex_map.AsTensor(),
87  dst_vertex_map.AsTensor(),
88  src_normal_map.AsTensor(), intrinsic_t, trans,
89  depth_diff, depth_diff * 0.5);
90  trans = result.transformation_.Matmul(trans).Contiguous();
91  }
93  }
94 }
95 
97  benchmark::State& state,
98  const core::Device& device,
99  const t::pipelines::odometry::Method& method) {
100  if (!t::geometry::Image::HAVE_IPP && device.IsCPU()) {
101  return;
102  }
103 
104  const float depth_scale = 1000.0;
105  const float depth_max = 3.0;
106  const float depth_diff = 0.07;
107 
108  data::SampleRedwoodRGBDImages redwood_data;
109  t::geometry::Image src_depth =
110  *t::io::CreateImageFromFile(redwood_data.GetDepthPaths()[0]);
111  t::geometry::Image src_color =
112  *t::io::CreateImageFromFile(redwood_data.GetColorPaths()[0]);
113 
114  t::geometry::Image dst_depth =
115  *t::io::CreateImageFromFile(redwood_data.GetDepthPaths()[2]);
116 
117  t::geometry::Image dst_color =
118  *t::io::CreateImageFromFile(redwood_data.GetColorPaths()[0]);
119 
120  t::geometry::RGBDImage source, target;
121  source.color_ = src_color.To(device);
122  source.depth_ = src_depth.To(device);
123  target.color_ = dst_color.To(device);
124  target.depth_ = dst_depth.To(device);
125 
126  core::Tensor intrinsic_t = CreateIntrisicTensor();
127 
128  // Very strict criteria to ensure running most the iterations
130  std::vector<t::pipelines::odometry::OdometryConvergenceCriteria> criteria{
132  1e-12),
134  1e-12),
136  1e-12)};
137 
138  // Warp up
140  source, target, intrinsic_t,
142  depth_scale, depth_max, criteria, method, loss);
143 
144  for (auto _ : state) {
146  source, target, intrinsic_t,
148  depth_scale, depth_max, criteria, method, loss);
149  core::cuda::Synchronize(device);
150  }
151 }
152 
154  ->Unit(benchmark::kMillisecond);
155 #ifdef BUILD_CUDA_MODULE
157  CUDA,
158  core::Device("CUDA:0"))
159  ->Unit(benchmark::kMillisecond);
160 #endif
161 
163  Hybrid_CPU,
164  core::Device("CPU:0"),
166  ->Unit(benchmark::kMillisecond);
168  Intensity_CPU,
169  core::Device("CPU:0"),
171  ->Unit(benchmark::kMillisecond);
173  PointToPlane_CPU,
174  core::Device("CPU:0"),
176  ->Unit(benchmark::kMillisecond);
177 
178 #ifdef BUILD_CUDA_MODULE
180  Hybrid_CUDA,
181  core::Device("CUDA:0"),
183  ->Unit(benchmark::kMillisecond);
185  Intensity_CUDA,
186  core::Device("CUDA:0"),
188  ->Unit(benchmark::kMillisecond);
190  PointToPlane_CUDA,
191  core::Device("CUDA:0"),
193  ->Unit(benchmark::kMillisecond);
194 #endif
195 } // namespace odometry
196 } // namespace pipelines
197 } // namespace t
198 } // namespace cloudViewer
Common CUDA utilities.
core::Tensor result
Definition: VtkUtils.cpp:76
Contains the pinhole camera intrinsic parameters.
std::pair< double, double > GetFocalLength() const
Returns the focal length in a tuple of X-axis and Y-axis focal lengths.
std::pair< double, double > GetPrincipalPoint() const
bool IsCPU() const
Returns true iff device type is CPU.
Definition: Device.h:46
static Tensor Eye(int64_t n, Dtype dtype, const Device &device)
Create an identity matrix of size n x n.
Definition: Tensor.cpp:418
Data class for SampleRedwoodRGBDImages contains a sample set of 5 color and depth images from Redwood...
Definition: Dataset.h:1047
std::vector< std::string > GetDepthPaths() const
Returns List of paths to depth image samples of size 5.
Definition: Dataset.h:1054
std::vector< std::string > GetColorPaths() const
Returns List of paths to color image samples of size 5.
Definition: Dataset.h:1052
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
static constexpr bool HAVE_IPP
Do we use IPP for accelerating image processing operations?
Definition: Image.h:339
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
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
core::Tensor AsTensor() const
Returns the underlying Tensor of the Image.
Definition: Image.h:124
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
@ PrimeSenseDefault
Default settings for PrimeSense camera sensor.
const Dtype Float64
Definition: Dtype.cpp:43
std::shared_ptr< geometry::Image > CreateImageFromFile(const std::string &filename)
Definition: ImageIO.cpp:48
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...
static core::Tensor CreateIntrisicTensor()
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....
BENCHMARK_CAPTURE(RGBDOdometryMultiScale, Hybrid_CPU, core::Device("CPU:0"), t::pipelines::odometry::Method::Hybrid) -> Unit(benchmark::kMillisecond)
Generic file read and write utility for python interface.