Visual Servoing Platform version 3.5.0
vpPixelMeterConversion.h
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See http://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Pixel to meter conversion.
33 *
34 * Authors:
35 * Eric Marchand
36 * Anthony Saunier
37 *
38 *****************************************************************************/
39
40#ifndef vpPixelMeterConversion_H
41#define vpPixelMeterConversion_H
42
48#include <visp3/core/vpCameraParameters.h>
49#include <visp3/core/vpDebug.h>
50#include <visp3/core/vpException.h>
51#include <visp3/core/vpImagePoint.h>
52#include <visp3/core/vpMath.h>
53
54#if VISP_HAVE_OPENCV_VERSION >= 0x020300
55# include <opencv2/imgproc/imgproc.hpp>
56# include <opencv2/calib3d/calib3d.hpp>
57#endif
58
71class VISP_EXPORT vpPixelMeterConversion
72{
73public:
76 static void convertEllipse(const vpCameraParameters &cam,
77 const vpImagePoint &center_p, double n20_p, double n11_p, double n02_p,
78 double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m);
79 static void convertLine(const vpCameraParameters &cam, const double &rho_p, const double &theta_p, double &rho_m,
80 double &theta_m);
81
82 static void convertMoment(const vpCameraParameters &cam, unsigned int order, const vpMatrix &moment_pixel,
83 vpMatrix &moment_meter);
109 inline static void convertPoint(const vpCameraParameters &cam,
110 const double &u, const double &v, double &x, double &y)
111 {
112 switch (cam.projModel) {
114 convertPointWithoutDistortion(cam, u, v, x, y);
115 break;
117 convertPointWithDistortion(cam, u, v, x, y);
118 break;
120 convertPointWithKannalaBrandtDistortion(cam, u, v, x, y);
121 break;
122 }
123 }
124
152 inline static void convertPoint(const vpCameraParameters &cam,
153 const vpImagePoint &iP, double &x, double &y)
154 {
155 switch (cam.projModel) {
157 convertPointWithoutDistortion(cam, iP, x, y);
158 break;
160 convertPointWithDistortion(cam, iP, x, y);
161 break;
163 convertPointWithKannalaBrandtDistortion(cam, iP, x, y);
164 break;
165 }
166 }
167
168#ifndef DOXYGEN_SHOULD_SKIP_THIS
181 inline static void convertPointWithoutDistortion(const vpCameraParameters &cam,
182 const double &u, const double &v, double &x, double &y)
183 {
184 x = (u - cam.u0) * cam.inv_px;
185 y = (v - cam.v0) * cam.inv_py;
186 }
187
203 inline static void convertPointWithoutDistortion(const vpCameraParameters &cam,
204 const vpImagePoint &iP, double &x, double &y)
205 {
206 x = (iP.get_u() - cam.u0) * cam.inv_px;
207 y = (iP.get_v() - cam.v0) * cam.inv_py;
208 }
209
224 inline static void convertPointWithDistortion(const vpCameraParameters &cam,
225 const double &u, const double &v, double &x, double &y)
226 {
227 double r2 = 1. + cam.kdu * (vpMath::sqr((u - cam.u0) * cam.inv_px) + vpMath::sqr((v - cam.v0) * cam.inv_py));
228 x = (u - cam.u0) * r2 * cam.inv_px;
229 y = (v - cam.v0) * r2 * cam.inv_py;
230 }
231
248 inline static void convertPointWithDistortion(const vpCameraParameters &cam,
249 const vpImagePoint &iP, double &x, double &y)
250 {
251 double r2 = 1. + cam.kdu * (vpMath::sqr((iP.get_u() - cam.u0) * cam.inv_px) +
252 vpMath::sqr((iP.get_v() - cam.v0) * cam.inv_py));
253 x = (iP.get_u() - cam.u0) * r2 * cam.inv_px;
254 y = (iP.get_v() - cam.v0) * r2 * cam.inv_py;
255 }
256
277 inline static void convertPointWithKannalaBrandtDistortion(const vpCameraParameters &cam, const double &u,
278 const double &v, double &x, double &y)
279 {
280 double x_d = (u - cam.u0) / cam.px, y_d = (v - cam.v0) / cam.py;
281 double scale = 1.0;
282 double r_d = sqrt(vpMath::sqr(x_d) + vpMath::sqr(y_d));
283
284 r_d = std::min(std::max(-M_PI, r_d), M_PI); // FOV restricted to 180degrees.
285
286 std::vector<double> k = cam.getKannalaBrandtDistortionCoefficients();
287
288 const double EPS = 1e-8;
289 // Use Newton-Raphson method to solve for the angle theta
290 if (r_d > EPS)
291 {
292 // compensate distortion iteratively
293 double theta = r_d;
294
295 for (int j = 0; j < 10; j++)
296 {
297 double theta2 = theta*theta, theta4 = theta2*theta2, theta6 = theta4*theta2, theta8 = theta6*theta2;
298 double k0_theta2 = k[0] * theta2, k1_theta4 = k[1] * theta4, k2_theta6 = k[2] * theta6, k3_theta8 = k[3] * theta8;
299 /* new_theta = theta - theta_fix, theta_fix = f0(theta) / f0'(theta) */
300 double theta_fix = (theta * (1 + k0_theta2 + k1_theta4 + k2_theta6 + k3_theta8) - r_d) /
301 (1 + 3*k0_theta2 + 5*k1_theta4 + 7*k2_theta6 + 9*k3_theta8);
302 theta = theta - theta_fix;
303 if (fabs(theta_fix) < EPS)
304 break;
305 }
306
307 scale = std::tan(theta) / r_d; // Scale of norm of (x,y) and (x_d, y_d)
308 }
309
310 x = x_d * scale;
311 y = y_d * scale;
312 }
313
333 inline static void convertPointWithKannalaBrandtDistortion(const vpCameraParameters &cam, const vpImagePoint &iP,
334 double &x, double &y)
335 {
336 double x_d = (iP.get_u() - cam.u0) / cam.px, y_d = (iP.get_v() - cam.v0) / cam.py;
337 double scale = 1.0;
338 double r_d = sqrt(vpMath::sqr(x_d) + vpMath::sqr(y_d));
339
340 r_d = std::min(std::max(-M_PI, r_d), M_PI); // FOV restricted to 180degrees.
341
342 std::vector<double> k = cam.getKannalaBrandtDistortionCoefficients();
343
344 const double EPS = 1e-8;
345 // Use Newton-Raphson method to solve for the angle theta
346 if (r_d > EPS)
347 {
348 // compensate distortion iteratively
349 double theta = r_d;
350
351 for (int j = 0; j < 10; j++)
352 {
353 double theta2 = theta*theta, theta4 = theta2*theta2, theta6 = theta4*theta2, theta8 = theta6*theta2;
354 double k0_theta2 = k[0] * theta2, k1_theta4 = k[1] * theta4, k2_theta6 = k[2] * theta6, k3_theta8 = k[3] * theta8;
355 /* new_theta = theta - theta_fix, theta_fix = f0(theta) / f0'(theta) */
356 double theta_fix = (theta * (1 + k0_theta2 + k1_theta4 + k2_theta6 + k3_theta8) - r_d) /
357 (1 + 3*k0_theta2 + 5*k1_theta4 + 7*k2_theta6 + 9*k3_theta8);
358 theta = theta - theta_fix;
359 if (fabs(theta_fix) < EPS)
360 break;
361 }
362
363 scale = std::tan(theta) / r_d; // Scale of norm of (x,y) and (x_d, y_d)
364 }
365
366 x = x_d * scale;
367 y = y_d * scale;
368 }
369#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
371
372#if VISP_HAVE_OPENCV_VERSION >= 0x020300
375 static void convertEllipse(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
376 const vpImagePoint &center_p, double n20_p, double n11_p, double n02_p,
377 double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m);
378 static void convertLine(const cv::Mat &cameraMatrix,
379 const double &rho_p, const double &theta_p,
380 double &rho_m, double &theta_m);
381 static void convertMoment(const cv::Mat &cameraMatrix,
382 unsigned int order, const vpMatrix &moment_pixel,
383 vpMatrix &moment_meter);
384 static void convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
385 const double &u, const double &v, double &x, double &y);
386 static void convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
387 const vpImagePoint &iP, double &x, double &y);
389#endif
390};
391
392#endif
Generic class defining intrinsic camera parameters.
std::vector< double > getKannalaBrandtDistortionCoefficients() const
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
double get_u() const
Definition: vpImagePoint.h:262
double get_v() const
Definition: vpImagePoint.h:273
static double sqr(double x)
Definition: vpMath.h:116
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:154
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)