CamEqui.h
Go to the documentation of this file.
1 /*
2  * OpenVINS: An Open Platform for Visual-Inertial Research
3  * Copyright (C) 2018-2023 Patrick Geneva
4  * Copyright (C) 2018-2023 Guoquan Huang
5  * Copyright (C) 2018-2023 OpenVINS Contributors
6  * Copyright (C) 2018-2019 Kevin Eckenhoff
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef OV_CORE_CAM_EQUI_H
23 #define OV_CORE_CAM_EQUI_H
24 
25 #include "CamBase.h"
26 
27 namespace ov_core {
28 
91 class CamEqui : public CamBase {
92 
93 public:
99  CamEqui(int width, int height) : CamBase(width, height) {}
100 
101  ~CamEqui() {}
102 
108  Eigen::Vector2f undistort_f(const Eigen::Vector2f &uv_dist) override {
109 
110  // Determine what camera parameters we should use
111  cv::Matx33d camK = camera_k_OPENCV;
112  cv::Vec4d camD = camera_d_OPENCV;
113 
114  // Convert point to opencv format
115  cv::Mat mat(1, 2, CV_32F);
116  mat.at<float>(0, 0) = uv_dist(0);
117  mat.at<float>(0, 1) = uv_dist(1);
118  mat = mat.reshape(2); // Nx1, 2-channel
119 
120  // Undistort it!
121  cv::fisheye::undistortPoints(mat, mat, camK, camD);
122 
123  // Construct our return vector
124  Eigen::Vector2f pt_out;
125  mat = mat.reshape(1); // Nx2, 1-channel
126  pt_out(0) = mat.at<float>(0, 0);
127  pt_out(1) = mat.at<float>(0, 1);
128  return pt_out;
129  }
130 
136  Eigen::Vector2f distort_f(const Eigen::Vector2f &uv_norm) override {
137 
138  // Get our camera parameters
139  Eigen::MatrixXd cam_d = camera_values;
140 
141  // Calculate distorted coordinates for fisheye
142  double r = std::sqrt(uv_norm(0) * uv_norm(0) + uv_norm(1) * uv_norm(1));
143  double theta = std::atan(r);
144  double theta_d = theta + cam_d(4) * std::pow(theta, 3) + cam_d(5) * std::pow(theta, 5) + cam_d(6) * std::pow(theta, 7) +
145  cam_d(7) * std::pow(theta, 9);
146 
147  // Handle when r is small (meaning our xy is near the camera center)
148  double inv_r = (r > 1e-8) ? 1.0 / r : 1.0;
149  double cdist = (r > 1e-8) ? theta_d * inv_r : 1.0;
150 
151  // Calculate distorted coordinates for fisheye
152  Eigen::Vector2f uv_dist;
153  double x1 = uv_norm(0) * cdist;
154  double y1 = uv_norm(1) * cdist;
155  uv_dist(0) = (float)(cam_d(0) * x1 + cam_d(2));
156  uv_dist(1) = (float)(cam_d(1) * y1 + cam_d(3));
157  return uv_dist;
158  }
159 
166  void compute_distort_jacobian(const Eigen::Vector2d &uv_norm, Eigen::MatrixXd &H_dz_dzn, Eigen::MatrixXd &H_dz_dzeta) override {
167 
168  // Get our camera parameters
169  Eigen::MatrixXd cam_d = camera_values;
170 
171  // Calculate distorted coordinates for fisheye
172  double r = std::sqrt(uv_norm(0) * uv_norm(0) + uv_norm(1) * uv_norm(1));
173  double theta = std::atan(r);
174  double theta_d = theta + cam_d(4) * std::pow(theta, 3) + cam_d(5) * std::pow(theta, 5) + cam_d(6) * std::pow(theta, 7) +
175  cam_d(7) * std::pow(theta, 9);
176 
177  // Handle when r is small (meaning our xy is near the camera center)
178  double inv_r = (r > 1e-8) ? 1.0 / r : 1.0;
179  double cdist = (r > 1e-8) ? theta_d * inv_r : 1.0;
180 
181  // Jacobian of distorted pixel to "normalized" pixel
182  Eigen::Matrix<double, 2, 2> duv_dxy = Eigen::Matrix<double, 2, 2>::Zero();
183  duv_dxy << cam_d(0), 0, 0, cam_d(1);
184 
185  // Jacobian of "normalized" pixel to normalized pixel
186  Eigen::Matrix<double, 2, 2> dxy_dxyn = Eigen::Matrix<double, 2, 2>::Zero();
187  dxy_dxyn << theta_d * inv_r, 0, 0, theta_d * inv_r;
188 
189  // Jacobian of "normalized" pixel to r
190  Eigen::Matrix<double, 2, 1> dxy_dr = Eigen::Matrix<double, 2, 1>::Zero();
191  dxy_dr << -uv_norm(0) * theta_d * inv_r * inv_r, -uv_norm(1) * theta_d * inv_r * inv_r;
192 
193  // Jacobian of r pixel to normalized xy
194  Eigen::Matrix<double, 1, 2> dr_dxyn = Eigen::Matrix<double, 1, 2>::Zero();
195  dr_dxyn << uv_norm(0) * inv_r, uv_norm(1) * inv_r;
196 
197  // Jacobian of "normalized" pixel to theta_d
198  Eigen::Matrix<double, 2, 1> dxy_dthd = Eigen::Matrix<double, 2, 1>::Zero();
199  dxy_dthd << uv_norm(0) * inv_r, uv_norm(1) * inv_r;
200 
201  // Jacobian of theta_d to theta
202  double dthd_dth = 1 + 3 * cam_d(4) * std::pow(theta, 2) + 5 * cam_d(5) * std::pow(theta, 4) + 7 * cam_d(6) * std::pow(theta, 6) +
203  9 * cam_d(7) * std::pow(theta, 8);
204 
205  // Jacobian of theta to r
206  double dth_dr = 1 / (r * r + 1);
207 
208  // Total Jacobian wrt normalized pixel coordinates
209  H_dz_dzn = Eigen::MatrixXd::Zero(2, 2);
210  H_dz_dzn = duv_dxy * (dxy_dxyn + (dxy_dr + dxy_dthd * dthd_dth * dth_dr) * dr_dxyn);
211 
212  // Calculate distorted coordinates for fisheye
213  double x1 = uv_norm(0) * cdist;
214  double y1 = uv_norm(1) * cdist;
215 
216  // Compute the Jacobian in respect to the intrinsics
217  H_dz_dzeta = Eigen::MatrixXd::Zero(2, 8);
218  H_dz_dzeta(0, 0) = x1;
219  H_dz_dzeta(0, 2) = 1;
220  H_dz_dzeta(0, 4) = cam_d(0) * uv_norm(0) * inv_r * std::pow(theta, 3);
221  H_dz_dzeta(0, 5) = cam_d(0) * uv_norm(0) * inv_r * std::pow(theta, 5);
222  H_dz_dzeta(0, 6) = cam_d(0) * uv_norm(0) * inv_r * std::pow(theta, 7);
223  H_dz_dzeta(0, 7) = cam_d(0) * uv_norm(0) * inv_r * std::pow(theta, 9);
224  H_dz_dzeta(1, 1) = y1;
225  H_dz_dzeta(1, 3) = 1;
226  H_dz_dzeta(1, 4) = cam_d(1) * uv_norm(1) * inv_r * std::pow(theta, 3);
227  H_dz_dzeta(1, 5) = cam_d(1) * uv_norm(1) * inv_r * std::pow(theta, 5);
228  H_dz_dzeta(1, 6) = cam_d(1) * uv_norm(1) * inv_r * std::pow(theta, 7);
229  H_dz_dzeta(1, 7) = cam_d(1) * uv_norm(1) * inv_r * std::pow(theta, 9);
230  }
231 };
232 
233 } // namespace ov_core
234 
235 #endif /* OV_CORE_CAM_EQUI_H */
ov_core::CamEqui::CamEqui
CamEqui(int width, int height)
Default constructor.
Definition: CamEqui.h:99
ov_core::CamEqui::compute_distort_jacobian
void compute_distort_jacobian(const Eigen::Vector2d &uv_norm, Eigen::MatrixXd &H_dz_dzn, Eigen::MatrixXd &H_dz_dzeta) override
Computes the derivative of raw distorted to normalized coordinate.
Definition: CamEqui.h:166
ov_core::CamEqui::~CamEqui
~CamEqui()
Definition: CamEqui.h:101
ov_core::CamEqui::distort_f
Eigen::Vector2f distort_f(const Eigen::Vector2f &uv_norm) override
Given a normalized uv coordinate this will distort it to the raw image plane.
Definition: CamEqui.h:136
ov_core::CamEqui
Fisheye / equadistant model pinhole camera model class.
Definition: CamEqui.h:91
ov_core::CamEqui::undistort_f
Eigen::Vector2f undistort_f(const Eigen::Vector2f &uv_dist) override
Given a raw uv point, this will undistort it based on the camera matrices into normalized camera coor...
Definition: CamEqui.h:108
ov_core::CamBase
Base pinhole camera model class.
Definition: CamBase.h:39
ov_core::CamBase::camera_d_OPENCV
cv::Vec4d camera_d_OPENCV
Camera distortion in OpenCV format.
Definition: CamBase.h:186
ov_core::CamBase::camera_k_OPENCV
cv::Matx33d camera_k_OPENCV
Camera intrinsics in OpenCV format.
Definition: CamBase.h:183
CamBase.h
ov_core::CamBase::camera_values
Eigen::MatrixXd camera_values
Raw set of camera intrinic values (f_x & f_y & c_x & c_y & k_1 & k_2 & k_3 & k_4)
Definition: CamBase.h:180
ov_core
Core algorithms for OpenVINS.
Definition: CamBase.h:30


ov_core
Author(s): Patrick Geneva , Kevin Eckenhoff , Guoquan Huang
autogenerated on Mon Jan 22 2024 03:08:17