ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
RGBDOdometryJacobian.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 <Image.h>
11 #include <RGBDImage.h>
12 
14 
15 namespace cloudViewer {
16 
17 namespace {
18 
19 const double SOBEL_SCALE = 0.125;
20 const double LAMBDA_HYBRID_DEPTH = 0.968;
21 
22 } // unnamed namespace
23 
24 namespace pipelines {
25 namespace odometry {
26 using namespace cloudViewer;
27 
29  int row,
30  std::vector<Eigen::Vector6d, utility::Vector6d_allocator> &J_r,
31  std::vector<double> &r,
32  std::vector<double> &w,
33  const geometry::RGBDImage &source,
34  const geometry::RGBDImage &target,
35  const geometry::Image &source_xyz,
36  const geometry::RGBDImage &target_dx,
37  const geometry::RGBDImage &target_dy,
38  const Eigen::Matrix3d &intrinsic,
39  const Eigen::Matrix4d &extrinsic,
40  const CorrespondenceSetPixelWise &corresps) const {
41  Eigen::Matrix3d R = extrinsic.block<3, 3>(0, 0);
42  Eigen::Vector3d t = extrinsic.block<3, 1>(0, 3);
43 
44  int u_s = corresps[row](0);
45  int v_s = corresps[row](1);
46  int u_t = corresps[row](2);
47  int v_t = corresps[row](3);
48  double diff = *target.color_.PointerAt<float>(u_t, v_t) -
49  *source.color_.PointerAt<float>(u_s, v_s);
50  double dIdx = SOBEL_SCALE * (*target_dx.color_.PointerAt<float>(u_t, v_t));
51  double dIdy = SOBEL_SCALE * (*target_dy.color_.PointerAt<float>(u_t, v_t));
52  Eigen::Vector3d p3d_mat(*source_xyz.PointerAt<float>(u_s, v_s, 0),
53  *source_xyz.PointerAt<float>(u_s, v_s, 1),
54  *source_xyz.PointerAt<float>(u_s, v_s, 2));
55  Eigen::Vector3d p3d_trans = R * p3d_mat + t;
56  double invz = 1. / p3d_trans(2);
57  double c0 = dIdx * intrinsic(0, 0) * invz;
58  double c1 = dIdy * intrinsic(1, 1) * invz;
59  double c2 = -(c0 * p3d_trans(0) + c1 * p3d_trans(1)) * invz;
60 
61  J_r.resize(1);
62  J_r[0](0) = -p3d_trans(2) * c1 + p3d_trans(1) * c2;
63  J_r[0](1) = p3d_trans(2) * c0 - p3d_trans(0) * c2;
64  J_r[0](2) = -p3d_trans(1) * c0 + p3d_trans(0) * c1;
65  J_r[0](3) = c0;
66  J_r[0](4) = c1;
67  J_r[0](5) = c2;
68  r.resize(1);
69  r[0] = diff;
70  w.resize(1);
71  w[0] = 1.0;
72 }
73 
75  int row,
76  std::vector<Eigen::Vector6d, utility::Vector6d_allocator> &J_r,
77  std::vector<double> &r,
78  std::vector<double> &w,
79  const geometry::RGBDImage &source,
80  const geometry::RGBDImage &target,
81  const geometry::Image &source_xyz,
82  const geometry::RGBDImage &target_dx,
83  const geometry::RGBDImage &target_dy,
84  const Eigen::Matrix3d &intrinsic,
85  const Eigen::Matrix4d &extrinsic,
86  const CorrespondenceSetPixelWise &corresps) const {
87  double sqrt_lamba_dep, sqrt_lambda_img;
88  sqrt_lamba_dep = sqrt(LAMBDA_HYBRID_DEPTH);
89  sqrt_lambda_img = sqrt(1.0 - LAMBDA_HYBRID_DEPTH);
90 
91  const double fx = intrinsic(0, 0);
92  const double fy = intrinsic(1, 1);
93  Eigen::Matrix3d R = extrinsic.block<3, 3>(0, 0);
94  Eigen::Vector3d t = extrinsic.block<3, 1>(0, 3);
95 
96  int u_s = corresps[row](0);
97  int v_s = corresps[row](1);
98  int u_t = corresps[row](2);
99  int v_t = corresps[row](3);
100  double diff_photo = (*target.color_.PointerAt<float>(u_t, v_t) -
101  *source.color_.PointerAt<float>(u_s, v_s));
102  double dIdx = SOBEL_SCALE * (*target_dx.color_.PointerAt<float>(u_t, v_t));
103  double dIdy = SOBEL_SCALE * (*target_dy.color_.PointerAt<float>(u_t, v_t));
104  double dDdx = SOBEL_SCALE * (*target_dx.depth_.PointerAt<float>(u_t, v_t));
105  double dDdy = SOBEL_SCALE * (*target_dy.depth_.PointerAt<float>(u_t, v_t));
106  if (std::isnan(dDdx)) dDdx = 0;
107  if (std::isnan(dDdy)) dDdy = 0;
108  Eigen::Vector3d p3d_mat(*source_xyz.PointerAt<float>(u_s, v_s, 0),
109  *source_xyz.PointerAt<float>(u_s, v_s, 1),
110  *source_xyz.PointerAt<float>(u_s, v_s, 2));
111  Eigen::Vector3d p3d_trans = R * p3d_mat + t;
112 
113  double diff_geo = *target.depth_.PointerAt<float>(u_t, v_t) - p3d_trans(2);
114  double invz = 1. / p3d_trans(2);
115  double c0 = dIdx * fx * invz;
116  double c1 = dIdy * fy * invz;
117  double c2 = -(c0 * p3d_trans(0) + c1 * p3d_trans(1)) * invz;
118  double d0 = dDdx * fx * invz;
119  double d1 = dDdy * fy * invz;
120  double d2 = -(d0 * p3d_trans(0) + d1 * p3d_trans(1)) * invz;
121 
122  J_r.resize(2);
123  r.resize(2);
124  w.resize(2);
125  J_r[0](0) = sqrt_lambda_img * (-p3d_trans(2) * c1 + p3d_trans(1) * c2);
126  J_r[0](1) = sqrt_lambda_img * (p3d_trans(2) * c0 - p3d_trans(0) * c2);
127  J_r[0](2) = sqrt_lambda_img * (-p3d_trans(1) * c0 + p3d_trans(0) * c1);
128  J_r[0](3) = sqrt_lambda_img * (c0);
129  J_r[0](4) = sqrt_lambda_img * (c1);
130  J_r[0](5) = sqrt_lambda_img * (c2);
131  double r_photo = sqrt_lambda_img * diff_photo;
132  r[0] = r_photo;
133  w[0] = 1.0;
134 
135  J_r[1](0) = sqrt_lamba_dep *
136  ((-p3d_trans(2) * d1 + p3d_trans(1) * d2) - p3d_trans(1));
137  J_r[1](1) = sqrt_lamba_dep *
138  ((p3d_trans(2) * d0 - p3d_trans(0) * d2) + p3d_trans(0));
139  J_r[1](2) = sqrt_lamba_dep * ((-p3d_trans(1) * d0 + p3d_trans(0) * d1));
140  J_r[1](3) = sqrt_lamba_dep * (d0);
141  J_r[1](4) = sqrt_lamba_dep * (d1);
142  J_r[1](5) = sqrt_lamba_dep * (d2 - 1.0f);
143  double r_geo = sqrt_lamba_dep * diff_geo;
144  r[1] = r_geo;
145  w[1] = 1.0;
146 }
147 
148 } // namespace odometry
149 } // namespace pipelines
150 } // namespace cloudViewer
The Image class stores image with customizable width, height, num of channels and bytes per channel.
Definition: Image.h:33
T * PointerAt(int u, int v) const
Function to access the raw data of a single-channel Image.
RGBDImage is for a pair of registered color and depth images,.
Definition: RGBDImage.h:27
Image color_
The color image.
Definition: RGBDImage.h:135
Image depth_
The depth image.
Definition: RGBDImage.h:137
void ComputeJacobianAndResidual(int row, std::vector< Eigen::Vector6d, utility::Vector6d_allocator > &J_r, std::vector< double > &r, std::vector< double > &w, const geometry::RGBDImage &source, const geometry::RGBDImage &target, const geometry::Image &source_xyz, const geometry::RGBDImage &target_dx, const geometry::RGBDImage &target_dy, const Eigen::Matrix3d &intrinsic, const Eigen::Matrix4d &extrinsic, const CorrespondenceSetPixelWise &corresps) const override
Parameterized Constructor.
void ComputeJacobianAndResidual(int row, std::vector< Eigen::Vector6d, utility::Vector6d_allocator > &J_r, std::vector< double > &r, std::vector< double > &w, const geometry::RGBDImage &source, const geometry::RGBDImage &target, const geometry::Image &source_xyz, const geometry::RGBDImage &target_dx, const geometry::RGBDImage &target_dy, const Eigen::Matrix3d &intrinsic, const Eigen::Matrix4d &extrinsic, const CorrespondenceSetPixelWise &corresps) const override
Parameterized Constructor.
std::vector< Eigen::Vector4i, utility::Vector4i_allocator > CorrespondenceSetPixelWise
Generic file read and write utility for python interface.