Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpPixelMeterConversion.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 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 https://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*****************************************************************************/
35
40#include <visp3/core/vpCameraParameters.h>
41#include <visp3/core/vpDebug.h>
42#include <visp3/core/vpException.h>
43#include <visp3/core/vpMath.h>
44#include <visp3/core/vpPixelMeterConversion.h>
45
56void vpPixelMeterConversion::convertEllipse(const vpCameraParameters &cam, const vpImagePoint &center_p, double n20_p,
57 double n11_p, double n02_p, double &xc_m, double &yc_m, double &n20_m,
58 double &n11_m, double &n02_m)
59{
60 vpPixelMeterConversion::convertPoint(cam, center_p, xc_m, yc_m);
61 double px = cam.get_px();
62 double py = cam.get_py();
63
64 n20_m = n20_p / (px * px);
65 n11_m = n11_p / (px * py);
66 n02_m = n02_p / (py * py);
67}
68
78void vpPixelMeterConversion::convertLine(const vpCameraParameters &cam, const double &rho_p, const double &theta_p,
79 double &rho_m, double &theta_m)
80{
81 double co = cos(theta_p);
82 double si = sin(theta_p);
83 double d = vpMath::sqr(cam.px * co) + vpMath::sqr(cam.py * si);
84
85 if (fabs(d) < 1e-6) {
86 vpERROR_TRACE("division by zero");
87 throw(vpException(vpException::divideByZeroError, "division by zero"));
88 }
89 theta_m = atan2(si * cam.py, co * cam.px);
90 rho_m = (rho_p - cam.u0 * co - cam.v0 * si) / sqrt(d);
91}
92
131 const vpMatrix &moment_pixel, vpMatrix &moment_meter)
132{
133 vpMatrix m(order, order);
134 double yc = -cam.v0;
135 double xc = -cam.u0;
136
137 for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
138 {
139 for (unsigned int p = 0; p < order; p++) // iteration en X
140 for (unsigned int q = 0; q < order; q++) // iteration en Y
141 if (p + q == k) // on est bien dans la matrice triangulaire superieure
142 {
143 m[p][q] = 0; // initialisation e 0
144 for (unsigned int r = 0; r <= p; r++) // somme externe
145 for (unsigned int t = 0; t <= q; t++) // somme interne
146 {
147 m[p][q] += static_cast<double>(vpMath::comb(p, r)) * static_cast<double>(vpMath::comb(q, t)) *
148 pow(xc, (int)(p - r)) * pow(yc, (int)(q - t)) * moment_pixel[r][t];
149 }
150 }
151 }
152
153 for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
154 for (unsigned int p = 0; p < order; p++)
155 for (unsigned int q = 0; q < order; q++)
156 if (p + q == k) {
157 m[p][q] *= pow(cam.inv_px, (int)(1 + p)) * pow(cam.inv_py, (int)(1 + q));
158 }
159
160 for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
161 for (unsigned int p = 0; p < order; p++)
162 for (unsigned int q = 0; q < order; q++)
163 if (p + q == k) {
164 moment_meter[p][q] = m[p][q];
165 }
166}
167
168#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_CALIB3D) && defined(HAVE_OPENCV_IMGPROC)
182void vpPixelMeterConversion::convertEllipse(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
183 const vpImagePoint &center_p, double n20_p, double n11_p, double n02_p,
184 double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m)
185{
186 vpPixelMeterConversion::convertPoint(cameraMatrix, distCoeffs, center_p, xc_m, yc_m);
187 double px = cameraMatrix.at<double>(0, 0);
188 double py = cameraMatrix.at<double>(1, 1);
189
190 n20_m = n20_p / (px * px);
191 n11_m = n11_p / (px * py);
192 n02_m = n02_p / (py * py);
193}
194
204void vpPixelMeterConversion::convertLine(const cv::Mat &cameraMatrix, const double &rho_p, const double &theta_p,
205 double &rho_m, double &theta_m)
206{
207 double co = cos(theta_p);
208 double si = sin(theta_p);
209 double px = cameraMatrix.at<double>(0, 0);
210 double py = cameraMatrix.at<double>(1, 1);
211 double u0 = cameraMatrix.at<double>(0, 2);
212 double v0 = cameraMatrix.at<double>(1, 2);
213
214 double d = vpMath::sqr(px * co) + vpMath::sqr(py * si);
215
216 if (fabs(d) < 1e-6) {
217 vpERROR_TRACE("division by zero");
218 throw(vpException(vpException::divideByZeroError, "division by zero"));
219 }
220 theta_m = atan2(si * py, co * px);
221 rho_m = (rho_p - u0 * co - v0 * si) / sqrt(d);
222}
223
234void vpPixelMeterConversion::convertMoment(const cv::Mat &cameraMatrix, unsigned int order,
235 const vpMatrix &moment_pixel, vpMatrix &moment_meter)
236{
237 double inv_px = 1. / cameraMatrix.at<double>(0, 0);
238 double inv_py = 1. / cameraMatrix.at<double>(1, 1);
239 double u0 = cameraMatrix.at<double>(0, 2);
240 double v0 = cameraMatrix.at<double>(1, 2);
241
242 vpMatrix m(order, order);
243 double yc = -v0;
244 double xc = -u0;
245
246 for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
247 {
248 for (unsigned int p = 0; p < order; p++) // iteration en X
249 for (unsigned int q = 0; q < order; q++) // iteration en Y
250 if (p + q == k) // on est bien dans la matrice triangulaire superieure
251 {
252 m[p][q] = 0; // initialisation e 0
253 for (unsigned int r = 0; r <= p; r++) // somme externe
254 for (unsigned int t = 0; t <= q; t++) // somme interne
255 {
256 m[p][q] += static_cast<double>(vpMath::comb(p, r)) * static_cast<double>(vpMath::comb(q, t)) *
257 pow(xc, static_cast<int>(p - r)) * pow(yc, static_cast<int>(q - t)) * moment_pixel[r][t];
258 }
259 }
260 }
261
262 for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
263 for (unsigned int p = 0; p < order; p++)
264 for (unsigned int q = 0; q < order; q++)
265 if (p + q == k) {
266 m[p][q] *= pow(inv_px, static_cast<int>(1 + p)) * pow(inv_py, static_cast<int>(1 + q));
267 }
268
269 for (unsigned int k = 0; k < order; k++) // iteration correspondant e l'ordre du moment
270 for (unsigned int p = 0; p < order; p++)
271 for (unsigned int q = 0; q < order; q++)
272 if (p + q == k) {
273 moment_meter[p][q] = m[p][q];
274 }
275}
276
291void vpPixelMeterConversion::convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const double &u,
292 const double &v, double &x, double &y)
293{
294 std::vector<cv::Point2d> imagePoints_vec;
295 imagePoints_vec.push_back(cv::Point2d(u, v));
296 std::vector<cv::Point2d> objectPoints_vec;
297 cv::undistortPoints(imagePoints_vec, objectPoints_vec, cameraMatrix, distCoeffs);
298 x = objectPoints_vec[0].x;
299 y = objectPoints_vec[0].y;
300}
301
315void vpPixelMeterConversion::convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
316 const vpImagePoint &iP, double &x, double &y)
317{
318 std::vector<cv::Point2d> imagePoints_vec;
319 imagePoints_vec.push_back(cv::Point2d(iP.get_u(), iP.get_v()));
320 std::vector<cv::Point2d> objectPoints_vec;
321 cv::undistortPoints(imagePoints_vec, objectPoints_vec, cameraMatrix, distCoeffs);
322 x = objectPoints_vec[0].x;
323 y = objectPoints_vec[0].y;
324}
325
326#endif
Generic class defining intrinsic camera parameters.
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ divideByZeroError
Division by zero.
Definition vpException.h:82
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:124
static long double comb(unsigned int n, unsigned int p)
Definition vpMath.h:309
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:152
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 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 convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
#define vpERROR_TRACE
Definition vpDebug.h:388