Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
vpPixelMeterConversion.cpp
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 
44 #include <visp3/core/vpCameraParameters.h>
45 #include <visp3/core/vpDebug.h>
46 #include <visp3/core/vpException.h>
47 #include <visp3/core/vpMath.h>
48 #include <visp3/core/vpPixelMeterConversion.h>
49 
61  const vpImagePoint &center_p, double n20_p, double n11_p, double n02_p,
62  double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m)
63 {
64  vpPixelMeterConversion::convertPoint(cam, center_p, xc_m, yc_m);
65  double px = cam.get_px();
66  double py = cam.get_py();
67 
68  n20_m = n20_p / (px * px);
69  n11_m = n11_p / (px * py);
70  n02_m = n02_p / (py * py);
71 }
72 
83  const double &rho_p, const double &theta_p,
84  double &rho_m, double &theta_m)
85 {
86  double co = cos(theta_p);
87  double si = sin(theta_p);
88  double d = vpMath::sqr(cam.px * co) + vpMath::sqr(cam.py * si);
89 
90  if (fabs(d) < 1e-6) {
91  vpERROR_TRACE("division by zero");
92  throw(vpException(vpException::divideByZeroError, "division by zero"));
93  }
94  theta_m = atan2(si * cam.py, co * cam.px);
95  rho_m = (rho_p - cam.u0 * co - cam.v0 * si) / sqrt(d);
96 }
97 
136  unsigned int order, const vpMatrix &moment_pixel,
137  vpMatrix &moment_meter)
138 {
139  vpMatrix m(order, order);
140  double yc = -cam.v0;
141  double xc = -cam.u0;
142 
143  for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
144  {
145  for (unsigned int p = 0; p < order; p++) // iteration en X
146  for (unsigned int q = 0; q < order; q++) // iteration en Y
147  if (p + q == k) // on est bien dans la matrice triangulaire superieure
148  {
149  m[p][q] = 0; // initialisation e 0
150  for (unsigned int r = 0; r <= p; r++) // somme externe
151  for (unsigned int t = 0; t <= q; t++) // somme interne
152  {
153  m[p][q] += static_cast<double>(vpMath::comb(p, r)) * static_cast<double>(vpMath::comb(q, t)) *
154  pow(xc, (int)(p - r)) * pow(yc, (int)(q - t)) * moment_pixel[r][t];
155  }
156  }
157  }
158 
159  for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
160  for (unsigned int p = 0; p < order; p++)
161  for (unsigned int q = 0; q < order; q++)
162  if (p + q == k) {
163  m[p][q] *= pow(cam.inv_px, (int)(1 + p)) * pow(cam.inv_py, (int)(1 + q));
164  }
165 
166  for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
167  for (unsigned int p = 0; p < order; p++)
168  for (unsigned int q = 0; q < order; q++)
169  if (p + q == k) {
170  moment_meter[p][q] = m[p][q];
171  }
172 }
173 
174 #if VISP_HAVE_OPENCV_VERSION >= 0x020300
175 
188 void vpPixelMeterConversion::convertEllipse(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
189  const vpImagePoint &center_p, double n20_p, double n11_p, double n02_p,
190  double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m)
191 {
192  vpPixelMeterConversion::convertPoint(cameraMatrix, distCoeffs, center_p, xc_m, yc_m);
193  double px = cameraMatrix.at<double>(0,0);
194  double py = cameraMatrix.at<double>(1,1);
195 
196  n20_m = n20_p / (px * px);
197  n11_m = n11_p / (px * py);
198  n02_m = n02_p / (py * py);
199 }
200 
210 void vpPixelMeterConversion::convertLine(const cv::Mat &cameraMatrix,
211  const double &rho_p, const double &theta_p,
212  double &rho_m, double &theta_m)
213 {
214  double co = cos(theta_p);
215  double si = sin(theta_p);
216  double px = cameraMatrix.at<double>(0,0);
217  double py = cameraMatrix.at<double>(1,1);
218  double u0 = cameraMatrix.at<double>(0,2);
219  double v0 = cameraMatrix.at<double>(1,2);
220 
221  double d = vpMath::sqr(px * co) + vpMath::sqr(py * si);
222 
223  if (fabs(d) < 1e-6) {
224  vpERROR_TRACE("division by zero");
225  throw(vpException(vpException::divideByZeroError, "division by zero"));
226  }
227  theta_m = atan2(si * py, co * px);
228  rho_m = (rho_p - u0 * co - v0 * si) / sqrt(d);
229 }
230 
241 void vpPixelMeterConversion::convertMoment(const cv::Mat &cameraMatrix,
242  unsigned int order, const vpMatrix &moment_pixel,
243  vpMatrix &moment_meter)
244 {
245  double inv_px = 1. / cameraMatrix.at<double>(0,0);
246  double inv_py = 1. / cameraMatrix.at<double>(1,1);
247  double u0 = cameraMatrix.at<double>(0,2);
248  double v0 = cameraMatrix.at<double>(1,2);
249 
250  vpMatrix m(order, order);
251  double yc = -v0;
252  double xc = -u0;
253 
254  for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
255  {
256  for (unsigned int p = 0; p < order; p++) // iteration en X
257  for (unsigned int q = 0; q < order; q++) // iteration en Y
258  if (p + q == k) // on est bien dans la matrice triangulaire superieure
259  {
260  m[p][q] = 0; // initialisation e 0
261  for (unsigned int r = 0; r <= p; r++) // somme externe
262  for (unsigned int t = 0; t <= q; t++) // somme interne
263  {
264  m[p][q] += static_cast<double>(vpMath::comb(p, r)) * static_cast<double>(vpMath::comb(q, t)) *
265  pow(xc, static_cast<int>(p - r)) * pow(yc, static_cast<int>(q - t)) * moment_pixel[r][t];
266  }
267  }
268  }
269 
270  for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
271  for (unsigned int p = 0; p < order; p++)
272  for (unsigned int q = 0; q < order; q++)
273  if (p + q == k) {
274  m[p][q] *= pow(inv_px, static_cast<int>(1 + p)) * pow(inv_py, static_cast<int>(1 + q));
275  }
276 
277  for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
278  for (unsigned int p = 0; p < order; p++)
279  for (unsigned int q = 0; q < order; q++)
280  if (p + q == k) {
281  moment_meter[p][q] = m[p][q];
282  }
283 }
284 
299 void vpPixelMeterConversion::convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
300  const double &u, const double &v, double &x, double &y)
301 {
302  std::vector<cv::Point2d> imagePoints_vec;
303  imagePoints_vec.push_back(cv::Point2d(u, v));
304  std::vector<cv::Point2d> objectPoints_vec;
305  cv::undistortPoints(imagePoints_vec, objectPoints_vec, cameraMatrix, distCoeffs);
306  x = objectPoints_vec[0].x;
307  y = objectPoints_vec[0].y;
308 }
309 
323 void vpPixelMeterConversion::convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
324  const vpImagePoint &iP, double &x, double &y)
325 {
326  std::vector<cv::Point2d> imagePoints_vec;
327  imagePoints_vec.push_back(cv::Point2d(iP.get_u(), iP.get_v()));
328  std::vector<cv::Point2d> objectPoints_vec;
329  cv::undistortPoints(imagePoints_vec, objectPoints_vec, cameraMatrix, distCoeffs);
330  x = objectPoints_vec[0].x;
331  y = objectPoints_vec[0].y;
332 }
333 
334 #endif
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:153
#define vpERROR_TRACE
Definition: vpDebug.h:393
error that can be emited by ViSP classes.
Definition: vpException.h:71
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
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)
double get_u() const
Definition: vpImagePoint.h:262
static double sqr(double x)
Definition: vpMath.h:116
Generic class defining intrinsic camera parameters.
static void convertMoment(const vpCameraParameters &cam, unsigned int order, const vpMatrix &moment_pixel, vpMatrix &moment_meter)
static long double comb(unsigned int n, unsigned int p)
Definition: vpMath.h:232
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
static void convertLine(const vpCameraParameters &cam, const double &rho_p, const double &theta_p, double &rho_m, double &theta_m)
double get_v() const
Definition: vpImagePoint.h:273