Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpPixelMeterConversion.h
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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
38
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
71class VISP_EXPORT vpPixelMeterConversion
72{
73public:
76 static void convertEllipse(const vpCameraParameters &cam, const vpImagePoint &center_p, double n20_p, double n11_p,
77 double n02_p, double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m);
78 static void convertLine(const vpCameraParameters &cam, const double &rho_p, const double &theta_p, double &rho_m,
79 double &theta_m);
80
81 static void convertMoment(const vpCameraParameters &cam, unsigned int order, const vpMatrix &moment_pixel,
82 vpMatrix &moment_meter);
108 inline static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
109 {
110 switch (cam.m_projModel) {
112 convertPointWithoutDistortion(cam, u, v, x, y);
113 break;
115 convertPointWithDistortion(cam, u, v, x, y);
116 break;
118 convertPointWithKannalaBrandtDistortion(cam, u, v, x, y);
119 break;
120 default: {
121 throw(vpException(vpException::fatalError, "Unsupported camera projection model in vpPixelMerterConversion::convertPoint()"));
122 }
123 }
124 }
125
153 inline static void convertPoint(const vpCameraParameters &cam, const vpImagePoint &iP, double &x, double &y)
154 {
155 switch (cam.m_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 default: {
166 throw(vpException(vpException::fatalError, "Unsupported camera projection model in vpPixelMerterConversion::convertPoint()"));
167 }
168 }
169 }
170
171#ifndef DOXYGEN_SHOULD_SKIP_THIS
184 inline static void convertPointWithoutDistortion(const vpCameraParameters &cam, const double &u, const double &v,
185 double &x, double &y)
186 {
187 x = (u - cam.m_u0) * cam.m_inv_px;
188 y = (v - cam.m_v0) * cam.m_inv_py;
189 }
190
206 inline static void convertPointWithoutDistortion(const vpCameraParameters &cam, const vpImagePoint &iP, double &x,
207 double &y)
208 {
209 x = (iP.get_u() - cam.m_u0) * cam.m_inv_px;
210 y = (iP.get_v() - cam.m_v0) * cam.m_inv_py;
211 }
212
227 inline static void convertPointWithDistortion(const vpCameraParameters &cam, const double &u, const double &v,
228 double &x, double &y)
229 {
230 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)));
231 x = (u - cam.m_u0) * r2 * cam.m_inv_px;
232 y = (v - cam.m_v0) * r2 * cam.m_inv_py;
233 }
234
251 inline static void convertPointWithDistortion(const vpCameraParameters &cam, const vpImagePoint &iP, double &x,
252 double &y)
253 {
254 double r2 = 1. + (cam.m_kdu * (vpMath::sqr((iP.get_u() - cam.m_u0) * cam.m_inv_px) +
255 vpMath::sqr((iP.get_v() - cam.m_v0) * cam.m_inv_py)));
256 x = (iP.get_u() - cam.m_u0) * r2 * cam.m_inv_px;
257 y = (iP.get_v() - cam.m_v0) * r2 * cam.m_inv_py;
258 }
259
280 inline static void convertPointWithKannalaBrandtDistortion(const vpCameraParameters &cam, const double &u,
281 const double &v, double &x, double &y)
282 {
283 double x_d = (u - cam.m_u0) / cam.m_px, y_d = (v - cam.m_v0) / cam.m_py;
284 double scale = 1.0;
285 double r_d = sqrt(vpMath::sqr(x_d) + vpMath::sqr(y_d));
286 const unsigned int index_0 = 0;
287 const unsigned int index_1 = 1;
288 const unsigned int index_2 = 2;
289 const unsigned int index_3 = 3;
290 const unsigned int val_1 = 1;
291 const unsigned int val_3 = 3;
292 const unsigned int val_5 = 5;
293 const unsigned int val_7 = 7;
294 const unsigned int val_9 = 9;
295 const unsigned int val_10 = 10;
296
297 r_d = std::min<double>(std::max<double>(-M_PI, r_d), M_PI); // FOV restricted to 180degrees.
298
299 std::vector<double> k = cam.getKannalaBrandtDistortionCoefficients();
300
301 const double EPS = 1e-8;
302 // Use Newton-Raphson method to solve for the angle theta
303 if (r_d > EPS) {
304 // compensate distortion iteratively
305 double theta = r_d;
306
307 for (unsigned int j = 0; j < val_10; ++j) {
308 double theta2 = theta * theta;
309 double theta4 = theta2 * theta2;
310 double theta6 = theta4 * theta2;
311 double theta8 = theta6 * theta2;
312 double k0_theta2 = k[index_0] * theta2;
313 double k1_theta4 = k[index_1] * theta4;
314 double k2_theta6 = k[index_2] * theta6,
315 k3_theta8 = k[index_3] * theta8;
316 /*
317 // new_theta = theta - theta_fix, theta_fix = f0(theta) / f0'(theta)
318 */
319 double theta_fix = ((theta * (val_1 + k0_theta2 + k1_theta4 + k2_theta6 + k3_theta8)) - r_d)
320 / (val_1 + (val_3 * k0_theta2) + (val_5 * k1_theta4) + (val_7 * k2_theta6) + (val_9 * k3_theta8));
321 theta = theta - theta_fix;
322 if (fabs(theta_fix) < EPS) {
323 break;
324 }
325 }
326
327 scale = std::tan(theta) / r_d; // Scale of norm of (x,y) and (x_d, y_d)
328 }
329
330 x = x_d * scale;
331 y = y_d * scale;
332 }
333
353 inline static void convertPointWithKannalaBrandtDistortion(const vpCameraParameters &cam, const vpImagePoint &iP,
354 double &x, double &y)
355 {
356 double x_d = (iP.get_u() - cam.m_u0) / cam.m_px, y_d = (iP.get_v() - cam.m_v0) / cam.m_py;
357 double scale = 1.0;
358 double r_d = sqrt(vpMath::sqr(x_d) + vpMath::sqr(y_d));
359 const unsigned int index_0 = 0;
360 const unsigned int index_1 = 1;
361 const unsigned int index_2 = 2;
362 const unsigned int index_3 = 3;
363 const unsigned int val_1 = 1;
364 const unsigned int val_3 = 3;
365 const unsigned int val_5 = 5;
366 const unsigned int val_7 = 7;
367 const unsigned int val_9 = 9;
368 const unsigned int val_10 = 10;
369
370 r_d = std::min<double>(std::max<double>(-M_PI, r_d), M_PI); // FOV restricted to 180degrees.
371
372 std::vector<double> k = cam.getKannalaBrandtDistortionCoefficients();
373
374 const double EPS = 1e-8;
375 // Use Newton-Raphson method to solve for the angle theta
376 if (r_d > EPS) {
377 // compensate distortion iteratively
378 double theta = r_d;
379
380 for (unsigned int j = 0; j < val_10; ++j) {
381 double theta2 = theta * theta;
382 double theta4 = theta2 * theta2;
383 double theta6 = theta4 * theta2;
384 double theta8 = theta6 * theta2;
385 double k0_theta2 = k[index_0] * theta2;
386 double k1_theta4 = k[index_1] * theta4;
387 double k2_theta6 = k[index_2] * theta6;
388 double k3_theta8 = k[index_3] * theta8;
389 /*
390 // new_theta = theta - theta_fix, theta_fix = f0(theta) / f0'(theta)
391 */
392 double theta_fix = ((theta * (val_1 + k0_theta2 + k1_theta4 + k2_theta6 + k3_theta8)) - r_d) /
393 (val_1 + (val_3 * k0_theta2) + (val_5 * k1_theta4) + (val_7 * k2_theta6) + (val_9 * k3_theta8));
394 theta = theta - theta_fix;
395 if (fabs(theta_fix) < EPS) {
396 break;
397 }
398 }
399
400 scale = std::tan(theta) / r_d; // Scale of norm of (x,y) and (x_d, y_d)
401 }
402
403 x = x_d * scale;
404 y = y_d * scale;
405 }
406#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
408
409#if defined(HAVE_OPENCV_IMGPROC) && \
410 (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_CALIB3D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_CALIB) && defined(HAVE_OPENCV_3D)))
411
414 static void convertEllipse(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const vpImagePoint &center_p,
415 double n20_p, double n11_p, double n02_p, double &xc_m, double &yc_m, double &n20_m,
416 double &n11_m, double &n02_m);
417 static void convertLine(const cv::Mat &cameraMatrix, const double &rho_p, const double &theta_p, double &rho_m,
418 double &theta_m);
419 static void convertMoment(const cv::Mat &cameraMatrix, unsigned int order, const vpMatrix &moment_pixel,
420 vpMatrix &moment_meter);
421 static void convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const double &u, const double &v,
422 double &x, double &y);
423 static void convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const vpImagePoint &iP, double &x,
424 double &y);
426#endif
427};
428END_VISP_NAMESPACE
429#endif
Generic class defining intrinsic camera parameters.
@ perspectiveProjWithDistortion
Perspective projection with distortion model.
@ ProjWithKannalaBrandtDistortion
Projection with Kannala-Brandt distortion model.
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ fatalError
Fatal error.
Definition vpException.h:72
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
double get_u() const
double get_v() const
static double sqr(double x)
Definition vpMath.h:203
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
static void convertPoint(const vpCameraParameters &cam, const vpImagePoint &iP, double &x, double &y)
static void convertMoment(const vpCameraParameters &cam, unsigned int order, const vpMatrix &moment_pixel, vpMatrix &moment_meter)
static void convertLine(const vpCameraParameters &cam, const double &rho_p, const double &theta_p, double &rho_m, double &theta_m)
static void convertEllipse(const vpCameraParameters &cam, const vpImagePoint &center_p, double n20_p, double n11_p, double n02_p, double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)