Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpPixelMeterConversion.cpp
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#include <visp3/core/vpCameraParameters.h>
39#include <visp3/core/vpException.h>
40#include <visp3/core/vpMath.h>
41#include <visp3/core/vpPixelMeterConversion.h>
42
43#if defined(HAVE_OPENCV_IMGPROC) && \
44 (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_CALIB3D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_CALIB) && defined(HAVE_OPENCV_3D)))
45
46#if (VISP_HAVE_OPENCV_VERSION < 0x050000)
47#include <opencv2/calib3d/calib3d.hpp>
48#endif
49
50#if (VISP_HAVE_OPENCV_VERSION >= 0x050000)
51#include <opencv2/calib.hpp>
52#include <opencv2/3d.hpp>
53#endif
54
55#include <opencv2/imgproc/imgproc.hpp>
56#endif
57
74 void vpPixelMeterConversion::convertEllipse(const vpCameraParameters &cam, const vpImagePoint &center_p, double n20_p,
75 double n11_p, double n02_p, double &xc_m, double &yc_m, double &n20_m,
76 double &n11_m, double &n02_m)
77{
78 vpPixelMeterConversion::convertPoint(cam, center_p, xc_m, yc_m);
79 double px = cam.get_px();
80 double py = cam.get_py();
81
82 n20_m = n20_p / (px * px);
83 n11_m = n11_p / (px * py);
84 n02_m = n02_p / (py * py);
85}
86
98void vpPixelMeterConversion::convertLine(const vpCameraParameters &cam, const double &rho_p, const double &theta_p,
99 double &rho_m, double &theta_m)
100{
101 double co = cos(theta_p);
102 double si = sin(theta_p);
103 double d = vpMath::sqr(cam.m_px * co) + vpMath::sqr(cam.m_py * si);
104
105 if (fabs(d) < 1e-6) {
106 throw(vpException(vpException::divideByZeroError, "division by zero"));
107 }
108 theta_m = atan2(si * cam.m_py, co * cam.m_px);
109 rho_m = (rho_p - (cam.m_u0 * co) - (cam.m_v0 * si)) / sqrt(d);
110}
111
150 const vpMatrix &moment_pixel, vpMatrix &moment_meter)
151{
152 vpMatrix m(order, order);
153 double yc = -cam.m_v0;
154 double xc = -cam.m_u0;
155
156 for (unsigned int k = 0; k < order; ++k) { // iteration corresponding to moment order
157 for (unsigned int p = 0; p < order; ++p) { // iteration en X
158 for (unsigned int q = 0; q < order; ++q) { // iteration en Y
159 if ((p + q) == k) { // on est bien dans la matrice triangulaire superieure
160 m[p][q] = 0; // initialisation e 0
161 for (unsigned int r = 0; r <= p; ++r) { // somme externe
162 for (unsigned int t = 0; t <= q; ++t) { // somme interne
163 m[p][q] += static_cast<double>(vpMath::comb(p, r)) * static_cast<double>(vpMath::comb(q, t)) *
164 pow(xc, static_cast<int>(p - r)) * pow(yc, static_cast<int>(q - t)) * moment_pixel[r][t];
165 }
166 }
167 }
168 }
169 }
170 }
171
172 for (unsigned int k = 0; k < order; ++k) { // iteration corresponding to moment order
173 for (unsigned int p = 0; p < order; ++p) {
174 for (unsigned int q = 0; q < order; ++q) {
175 if ((p + q) == k) {
176 m[p][q] *= pow(cam.m_inv_px, static_cast<int>(1 + p)) * pow(cam.m_inv_py, static_cast<int>(1 + q));
177 }
178 }
179 }
180 }
181
182 for (unsigned int k = 0; k < order; ++k) { // iteration corresponding to moment order
183 for (unsigned int p = 0; p < order; ++p) {
184 for (unsigned int q = 0; q < order; ++q) {
185 if ((p + q) == k) {
186 moment_meter[p][q] = m[p][q];
187 }
188 }
189 }
190 }
191}
192
193#if defined(HAVE_OPENCV_IMGPROC) && \
194 (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_CALIB3D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_CALIB) && defined(HAVE_OPENCV_3D)))
213void vpPixelMeterConversion::convertEllipse(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
214 const vpImagePoint &center_p, double n20_p, double n11_p, double n02_p,
215 double &xc_m, double &yc_m, double &n20_m, double &n11_m, double &n02_m)
216{
217 vpPixelMeterConversion::convertPoint(cameraMatrix, distCoeffs, center_p, xc_m, yc_m);
218 double px = cameraMatrix.at<double>(0, 0);
219 double py = cameraMatrix.at<double>(1, 1);
220
221 n20_m = n20_p / (px * px);
222 n11_m = n11_p / (px * py);
223 n02_m = n02_p / (py * py);
224}
225
237void vpPixelMeterConversion::convertLine(const cv::Mat &cameraMatrix, const double &rho_p, const double &theta_p,
238 double &rho_m, double &theta_m)
239{
240 double co = cos(theta_p);
241 double si = sin(theta_p);
242 double px = cameraMatrix.at<double>(0, 0);
243 double py = cameraMatrix.at<double>(1, 1);
244 double u0 = cameraMatrix.at<double>(0, 2);
245 double v0 = cameraMatrix.at<double>(1, 2);
246
247 double d = vpMath::sqr(px * co) + vpMath::sqr(py * si);
248
249 if (fabs(d) < 1e-6) {
250 throw(vpException(vpException::divideByZeroError, "division by zero"));
251 }
252 theta_m = atan2(si * py, co * px);
253 rho_m = (rho_p - u0 * co - v0 * si) / sqrt(d);
254}
255
266void vpPixelMeterConversion::convertMoment(const cv::Mat &cameraMatrix, unsigned int order,
267 const vpMatrix &moment_pixel, vpMatrix &moment_meter)
268{
269 double inv_px = 1. / cameraMatrix.at<double>(0, 0);
270 double inv_py = 1. / cameraMatrix.at<double>(1, 1);
271 double u0 = cameraMatrix.at<double>(0, 2);
272 double v0 = cameraMatrix.at<double>(1, 2);
273
274 vpMatrix m(order, order);
275 double yc = -v0;
276 double xc = -u0;
277
278 for (unsigned int k = 0; k < order; ++k) { // iteration corresponding to moment order
279 for (unsigned int p = 0; p < order; ++p) { // iteration en X
280 for (unsigned int q = 0; q < order; ++q) { // iteration en Y
281 if (p + q == k) { // on est bien dans la matrice triangulaire superieure
282 m[p][q] = 0; // initialisation e 0
283 for (unsigned int r = 0; r <= p; ++r) { // somme externe
284 for (unsigned int t = 0; t <= q; ++t) { // somme interne
285 m[p][q] += static_cast<double>(vpMath::comb(p, r)) * static_cast<double>(vpMath::comb(q, t)) *
286 pow(xc, static_cast<int>(p - r)) * pow(yc, static_cast<int>(q - t)) * moment_pixel[r][t];
287 }
288 }
289 }
290 }
291 }
292 }
293
294 for (unsigned int k = 0; k < order; ++k) { // iteration corresponding to moment order
295 for (unsigned int p = 0; p < order; ++p) {
296 for (unsigned int q = 0; q < order; ++q) {
297 if (p + q == k) {
298 m[p][q] *= pow(inv_px, static_cast<int>(1 + p)) * pow(inv_py, static_cast<int>(1 + q));
299 }
300 }
301 }
302 }
303
304 for (unsigned int k = 0; k < order; ++k) { // iteration corresponding to moment order
305 for (unsigned int p = 0; p < order; ++p) {
306 for (unsigned int q = 0; q < order; ++q) {
307 if (p + q == k) {
308 moment_meter[p][q] = m[p][q];
309 }
310 }
311 }
312 }
313}
314
329void vpPixelMeterConversion::convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs, const double &u,
330 const double &v, double &x, double &y)
331{
332 std::vector<cv::Point2d> imagePoints_vec;
333 imagePoints_vec.push_back(cv::Point2d(u, v));
334 std::vector<cv::Point2d> objectPoints_vec;
335 cv::undistortPoints(imagePoints_vec, objectPoints_vec, cameraMatrix, distCoeffs);
336 x = objectPoints_vec[0].x;
337 y = objectPoints_vec[0].y;
338}
339
353void vpPixelMeterConversion::convertPoint(const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs,
354 const vpImagePoint &iP, double &x, double &y)
355{
356 std::vector<cv::Point2d> imagePoints_vec;
357 imagePoints_vec.push_back(cv::Point2d(iP.get_u(), iP.get_v()));
358 std::vector<cv::Point2d> objectPoints_vec;
359 cv::undistortPoints(imagePoints_vec, objectPoints_vec, cameraMatrix, distCoeffs);
360 x = objectPoints_vec[0].x;
361 y = objectPoints_vec[0].y;
362}
363
364#endif
365END_VISP_NAMESPACE
Generic class defining intrinsic camera parameters.
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ divideByZeroError
Division by zero.
Definition vpException.h:70
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
static long double comb(unsigned int n, unsigned int p)
Definition vpMath.h:398
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
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)