Visual Servoing Platform  version 3.6.1 under development (2025-01-30)
vpPixelMeterConversion.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Pixel to meter conversion.
32  */
33 
39 #ifndef VP_PIXEL_METER_CONVERSION_H
40 #define VP_PIXEL_METER_CONVERSION_H
41 
42 #include <visp3/core/vpCameraParameters.h>
43 #include <visp3/core/vpException.h>
44 #include <visp3/core/vpImagePoint.h>
45 #include <visp3/core/vpMath.h>
46 
47 #if defined(VISP_HAVE_OPENCV)
48 #include <opencv2/core/core.hpp>
49 #endif
50 
51 BEGIN_VISP_NAMESPACE
64 class VISP_EXPORT vpPixelMeterConversion
65 {
66 public:
69  static void convertEllipse(const vpCameraParameters &cam, const vpImagePoint &center_p, double n20_p, double n11_p,
70  double n02_p, double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m);
71  static void convertLine(const vpCameraParameters &cam, const double &rho_p, const double &theta_p, double &rho_m,
72  double &theta_m);
73 
74  static void convertMoment(const vpCameraParameters &cam, unsigned int order, const vpMatrix &moment_pixel,
75  vpMatrix &moment_meter);
101  inline static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
102  {
103  switch (cam.m_projModel) {
105  convertPointWithoutDistortion(cam, u, v, x, y);
106  break;
108  convertPointWithDistortion(cam, u, v, x, y);
109  break;
111  convertPointWithKannalaBrandtDistortion(cam, u, v, x, y);
112  break;
113  default:
114  std::cerr << "projection model not identified" << std::endl;
115  }
116  }
117 
145  inline static void convertPoint(const vpCameraParameters &cam, const vpImagePoint &iP, double &x, double &y)
146  {
147  switch (cam.m_projModel) {
149  convertPointWithoutDistortion(cam, iP, x, y);
150  break;
152  convertPointWithDistortion(cam, iP, x, y);
153  break;
155  convertPointWithKannalaBrandtDistortion(cam, iP, x, y);
156  break;
157  default:
158  std::cerr << "projection model not identified" << std::endl;
159  }
160  }
161 
162 #ifndef DOXYGEN_SHOULD_SKIP_THIS
175  inline static void convertPointWithoutDistortion(const vpCameraParameters &cam, const double &u, const double &v,
176  double &x, double &y)
177  {
178  x = (u - cam.m_u0) * cam.m_inv_px;
179  y = (v - cam.m_v0) * cam.m_inv_py;
180  }
181 
197  inline static void convertPointWithoutDistortion(const vpCameraParameters &cam, const vpImagePoint &iP, double &x,
198  double &y)
199  {
200  x = (iP.get_u() - cam.m_u0) * cam.m_inv_px;
201  y = (iP.get_v() - cam.m_v0) * cam.m_inv_py;
202  }
203 
218  inline static void convertPointWithDistortion(const vpCameraParameters &cam, const double &u, const double &v,
219  double &x, double &y)
220  {
221  double r2 = 1. + (cam.m_kdu * (vpMath::sqr((u - cam.m_u0) * cam.m_inv_px) + vpMath::sqr((v - cam.m_v0) * cam.m_inv_py)));
222  x = (u - cam.m_u0) * r2 * cam.m_inv_px;
223  y = (v - cam.m_v0) * r2 * cam.m_inv_py;
224  }
225 
242  inline static void convertPointWithDistortion(const vpCameraParameters &cam, const vpImagePoint &iP, double &x,
243  double &y)
244  {
245  double r2 = 1. + (cam.m_kdu * (vpMath::sqr((iP.get_u() - cam.m_u0) * cam.m_inv_px) +
246  vpMath::sqr((iP.get_v() - cam.m_v0) * cam.m_inv_py)));
247  x = (iP.get_u() - cam.m_u0) * r2 * cam.m_inv_px;
248  y = (iP.get_v() - cam.m_v0) * r2 * cam.m_inv_py;
249  }
250 
271  inline static void convertPointWithKannalaBrandtDistortion(const vpCameraParameters &cam, const double &u,
272  const double &v, double &x, double &y)
273  {
274  double x_d = (u - cam.m_u0) / cam.m_px, y_d = (v - cam.m_v0) / cam.m_py;
275  double scale = 1.0;
276  double r_d = sqrt(vpMath::sqr(x_d) + vpMath::sqr(y_d));
277  const unsigned int index_0 = 0;
278  const unsigned int index_1 = 1;
279  const unsigned int index_2 = 2;
280  const unsigned int index_3 = 3;
281  const unsigned int val_1 = 1;
282  const unsigned int val_3 = 3;
283  const unsigned int val_5 = 5;
284  const unsigned int val_7 = 7;
285  const unsigned int val_9 = 9;
286  const unsigned int val_10 = 10;
287 
288  r_d = std::min<double>(std::max<double>(-M_PI, r_d), M_PI); // FOV restricted to 180degrees.
289 
290  std::vector<double> k = cam.getKannalaBrandtDistortionCoefficients();
291 
292  const double EPS = 1e-8;
293  // Use Newton-Raphson method to solve for the angle theta
294  if (r_d > EPS) {
295  // compensate distortion iteratively
296  double theta = r_d;
297 
298  for (unsigned int j = 0; j < val_10; ++j) {
299  double theta2 = theta * theta;
300  double theta4 = theta2 * theta2;
301  double theta6 = theta4 * theta2;
302  double theta8 = theta6 * theta2;
303  double k0_theta2 = k[index_0] * theta2;
304  double k1_theta4 = k[index_1] * theta4;
305  double k2_theta6 = k[index_2] * theta6,
306  k3_theta8 = k[index_3] * theta8;
307  /*
308  // new_theta = theta - theta_fix, theta_fix = f0(theta) / f0'(theta)
309  */
310  double theta_fix = ((theta * (val_1 + k0_theta2 + k1_theta4 + k2_theta6 + k3_theta8)) - r_d)
311  / (val_1 + (val_3 * k0_theta2) + (val_5 * k1_theta4) + (val_7 * k2_theta6) + (val_9 * k3_theta8));
312  theta = theta - theta_fix;
313  if (fabs(theta_fix) < EPS) {
314  break;
315  }
316  }
317 
318  scale = std::tan(theta) / r_d; // Scale of norm of (x,y) and (x_d, y_d)
319  }
320 
321  x = x_d * scale;
322  y = y_d * scale;
323  }
324 
344  inline static void convertPointWithKannalaBrandtDistortion(const vpCameraParameters &cam, const vpImagePoint &iP,
345  double &x, double &y)
346  {
347  double x_d = (iP.get_u() - cam.m_u0) / cam.m_px, y_d = (iP.get_v() - cam.m_v0) / cam.m_py;
348  double scale = 1.0;
349  double r_d = sqrt(vpMath::sqr(x_d) + vpMath::sqr(y_d));
350  const unsigned int index_0 = 0;
351  const unsigned int index_1 = 1;
352  const unsigned int index_2 = 2;
353  const unsigned int index_3 = 3;
354  const unsigned int val_1 = 1;
355  const unsigned int val_3 = 3;
356  const unsigned int val_5 = 5;
357  const unsigned int val_7 = 7;
358  const unsigned int val_9 = 9;
359  const unsigned int val_10 = 10;
360 
361  r_d = std::min<double>(std::max<double>(-M_PI, r_d), M_PI); // FOV restricted to 180degrees.
362 
363  std::vector<double> k = cam.getKannalaBrandtDistortionCoefficients();
364 
365  const double EPS = 1e-8;
366  // Use Newton-Raphson method to solve for the angle theta
367  if (r_d > EPS) {
368  // compensate distortion iteratively
369  double theta = r_d;
370 
371  for (unsigned int j = 0; j < val_10; ++j) {
372  double theta2 = theta * theta;
373  double theta4 = theta2 * theta2;
374  double theta6 = theta4 * theta2;
375  double theta8 = theta6 * theta2;
376  double k0_theta2 = k[index_0] * theta2;
377  double k1_theta4 = k[index_1] * theta4;
378  double k2_theta6 = k[index_2] * theta6;
379  double k3_theta8 = k[index_3] * theta8;
380  /*
381  // new_theta = theta - theta_fix, theta_fix = f0(theta) / f0'(theta)
382  */
383  double theta_fix = ((theta * (val_1 + k0_theta2 + k1_theta4 + k2_theta6 + k3_theta8)) - r_d) /
384  (val_1 + (val_3 * k0_theta2) + (val_5 * k1_theta4) + (val_7 * k2_theta6) + (val_9 * k3_theta8));
385  theta = theta - theta_fix;
386  if (fabs(theta_fix) < EPS) {
387  break;
388  }
389  }
390 
391  scale = std::tan(theta) / r_d; // Scale of norm of (x,y) and (x_d, y_d)
392  }
393 
394  x = x_d * scale;
395  y = y_d * scale;
396  }
397 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
399 
400 #if defined(HAVE_OPENCV_IMGPROC) && \
401  (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_CALIB3D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_CALIB) && defined(HAVE_OPENCV_3D)))
402 
405  static void convertEllipse(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const vpImagePoint &center_p,
406  double n20_p, double n11_p, double n02_p, double &xc_m, double &yc_m, double &n20_m,
407  double &n11_m, double &n02_m);
408  static void convertLine(const cv::Mat &cameraMatrix, const double &rho_p, const double &theta_p, double &rho_m,
409  double &theta_m);
410  static void convertMoment(const cv::Mat &cameraMatrix, unsigned int order, const vpMatrix &moment_pixel,
411  vpMatrix &moment_meter);
412  static void convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const double &u, const double &v,
413  double &x, double &y);
414  static void convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const vpImagePoint &iP, double &x,
415  double &y);
417 #endif
418 };
419 END_VISP_NAMESPACE
420 #endif
Generic class defining intrinsic camera parameters.
std::vector< double > getKannalaBrandtDistortionCoefficients() const
@ perspectiveProjWithDistortion
Perspective projection with distortion model.
@ ProjWithKannalaBrandtDistortion
Projection with Kannala-Brandt distortion model.
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
double get_u() const
Definition: vpImagePoint.h:136
double get_v() const
Definition: vpImagePoint.h:147
static double sqr(double x)
Definition: vpMath.h:203
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
static void convertPoint(const vpCameraParameters &cam, const vpImagePoint &iP, double &x, double &y)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)