Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
testCameraParametersConversion.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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  * Performs various tests on the vpPixelMeterConversion and
32  * vpPixelMeterConversion class.
33  */
34 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <visp3/core/vpCameraParameters.h>
45 #include <visp3/core/vpDebug.h>
46 #include <visp3/core/vpMath.h>
47 #include <visp3/core/vpMeterPixelConversion.h>
48 #include <visp3/core/vpPixelMeterConversion.h>
49 
50 int main()
51 {
52 #ifdef ENABLE_VISP_NAMESPACE
53  using namespace VISP_NAMESPACE_NAME;
54 #endif
55  try {
56  {
57  std::cout << "* Test operator=()" << std::endl;
58  vpCameraParameters cam1, cam2;
59  cam1.initPersProjWithDistortion(700.0, 700.0, 320.0, 240.0, 0.1, 0.1);
60  cam2.initPersProjWithoutDistortion(700.0, 700.0, 320.0, 240.0);
61  if (cam1 == cam2) {
62  std::cerr << "Issue with vpCameraParameters comparison operator." << std::endl;
63  return EXIT_FAILURE;
64  }
65 
66  cam2 = cam1;
67  if (cam1 != cam2) {
68  std::cerr << "Issue with vpCameraParameters comparison operator." << std::endl;
69  return EXIT_FAILURE;
70  }
71 
72  std::cout << "* Test computeFov()" << std::endl;
73  cam2.computeFov(640u, 480u);
74  if (cam1 == cam2) {
75  std::cerr << "Issue with vpCameraParameters comparison operator." << std::endl;
76  return EXIT_FAILURE;
77  }
78  }
79 
81  double px, py, u0, v0;
82  px = 1657.429131;
83  py = 1658.818598;
84  u0 = 322.2437833;
85  v0 = 230.8012737;
86  vpCameraParameters camDist;
87  double px_dist, py_dist, u0_dist, v0_dist, kud_dist, kdu_dist;
88  px_dist = 1624.824731;
89  py_dist = 1625.263641;
90  u0_dist = 324.0923411;
91  v0_dist = 245.2421388;
92  kud_dist = -0.1741532338;
93  kdu_dist = 0.1771165148;
94 
95  cam.initPersProjWithoutDistortion(px, py, u0, v0);
96  camDist.initPersProjWithDistortion(px_dist, py_dist, u0_dist, v0_dist, kud_dist, kdu_dist);
97 
98  double u1 = 320;
99  double v1 = 240;
100  double x1 = 0, y1 = 0;
101  double u2 = 0, v2 = 0;
102  std::cout << "* Test point conversion without distortion" << std::endl;
103  vpPixelMeterConversion::convertPoint(cam, u1, v1, x1, y1);
104  vpMeterPixelConversion::convertPoint(cam, x1, y1, u2, v2);
105  if (!vpMath::equal(u1, u2) || !vpMath::equal(v1, v2)) {
106  std::cerr << "Error in point conversion without distortion:\n"
107  << "u1 = " << u1 << ", u2 = " << u2 << std::endl
108  << "v1 = " << v1 << ", v2 = " << v2 << std::endl;
109  return EXIT_FAILURE;
110  }
111 
112  std::cout << "* Test point conversion with distortion" << std::endl;
113  vpPixelMeterConversion::convertPoint(camDist, u1, v1, x1, y1);
114  vpMeterPixelConversion::convertPoint(camDist, x1, y1, u2, v2);
115  if (!vpMath::equal(u1, u2) || !vpMath::equal(v1, v2)) {
116  std::cerr << "Error in point conversion without distortion:\n"
117  << "u1 = " << u1 << ", u2 = " << u2 << std::endl
118  << "v1 = " << v1 << ", v2 = " << v2 << std::endl;
119  return EXIT_FAILURE;
120  }
121 
122 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_CALIB3D) && defined(HAVE_OPENCV_IMGPROC)
123  {
124  std::cout << "* Compare ViSP and OpenCV point pixel meter conversion without distortion" << std::endl;
125  cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << px, 0, u0, 0, py, v0, 0, 0, 1);
126  cv::Mat distCoeffs = cv::Mat::zeros(5, 1, CV_64FC1);
127  double x2, y2;
128 
129  vpPixelMeterConversion::convertPoint(cam, u1, v1, x1, y1);
130  vpPixelMeterConversion::convertPoint(cameraMatrix, distCoeffs, u1, v1, x2, y2);
131  if (!vpMath::equal(x1, x2, 1e-6) || !vpMath::equal(y1, y2, 1e-6)) {
132  std::cerr << "Error in point pixel meter conversion: visp result (" << x1 << ", " << y1 << ") "
133  << "differ from OpenCV result (" << x2 << ", " << y2 << ")" << std::endl;
134  return EXIT_FAILURE;
135  }
136 
137  vpImagePoint ip(v1, u1);
138  vpPixelMeterConversion::convertPoint(cam, ip, x1, y1);
139  vpPixelMeterConversion::convertPoint(cameraMatrix, distCoeffs, ip, x2, y2);
140  if (!vpMath::equal(x1, x2, 1e-6) || !vpMath::equal(y1, y2, 1e-6)) {
141  std::cerr << "Error in point pixel meter conversion: visp result (" << x1 << ", " << y1 << ") "
142  << "differ from OpenCV result (" << x2 << ", " << y2 << ")" << std::endl;
143  return EXIT_FAILURE;
144  }
145 
146  std::cout << "* Compare ViSP and OpenCV point meter pixel conversion without distortion" << std::endl;
147  vpMeterPixelConversion::convertPoint(cam, x1, y1, u1, v1);
148  vpMeterPixelConversion::convertPoint(cameraMatrix, distCoeffs, x1, y1, u2, v2);
149  if (!vpMath::equal(u1, u2, 1e-6) || !vpMath::equal(v1, v2, 1e-6)) {
150  std::cerr << "Error in point meter pixel conversion: visp result (" << u1 << ", " << v1 << ") "
151  << "differ from OpenCV result (" << u2 << ", " << v2 << ")" << std::endl;
152  return EXIT_FAILURE;
153  }
154 
155  vpImagePoint iP1, iP2;
156  vpMeterPixelConversion::convertPoint(cam, x1, y1, iP1);
157  vpMeterPixelConversion::convertPoint(cameraMatrix, distCoeffs, x1, y1, iP2);
158  if (vpImagePoint::distance(iP1, iP2) > 1e-6) {
159  std::cerr << "Error in point meter pixel conversion: visp result (" << u1 << ", " << v1 << ") "
160  << "differ from OpenCV result (" << u2 << ", " << v2 << ")" << std::endl;
161  return EXIT_FAILURE;
162  }
163  }
164 
165  {
166  std::cout << "* Compare ViSP and OpenCV point pixel meter conversion with distortion" << std::endl;
167  cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << px_dist, 0, u0_dist, 0, py_dist, v0_dist, 0, 0, 1);
168  cv::Mat distCoeffs = cv::Mat::zeros(5, 1, CV_64FC1);
169  distCoeffs.at<double>(0, 0) = kdu_dist;
170  double x2, y2;
171 
172  vpPixelMeterConversion::convertPoint(camDist, u1, v1, x1, y1);
173  vpPixelMeterConversion::convertPoint(cameraMatrix, distCoeffs, u1, v1, x2, y2);
174  if (!vpMath::equal(x1, x2, 1e-6) || !vpMath::equal(y1, y2, 1e-6)) {
175  std::cerr << "Error in point conversion: visp result (" << x1 << ", " << y1 << ") "
176  << "differ from OpenCV result (" << x2 << ", " << y2 << ")" << std::endl;
177  return EXIT_FAILURE;
178  }
179 
180  std::cout << "* Compare ViSP and OpenCV point meter pixel conversion with distortion" << std::endl;
181  distCoeffs.at<double>(0, 0) = kud_dist;
182  vpMeterPixelConversion::convertPoint(camDist, x1, y1, u1, v1);
183  vpMeterPixelConversion::convertPoint(cameraMatrix, distCoeffs, x1, y1, u2, v2);
184  if (!vpMath::equal(u1, u2, 1e-6) || !vpMath::equal(v1, v2, 1e-6)) {
185  std::cerr << "Error in point meter pixel conversion: visp result (" << u1 << ", " << v1 << ") "
186  << "differ from OpenCV result (" << u2 << ", " << v2 << ")" << std::endl;
187  return EXIT_FAILURE;
188  }
189  }
190 
191  {
192  std::cout << "* Compare ViSP and OpenCV line pixel meter conversion without distortion" << std::endl;
193  cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << px, 0, u0, 0, py, v0, 0, 0, 1);
194  double rho_p = 100, theta_p = vpMath::rad(45);
195  double rho_m1, theta_m1, rho_m2, theta_m2;
196 
197  vpPixelMeterConversion::convertLine(cam, rho_p, theta_p, rho_m1, theta_m1);
198  vpPixelMeterConversion::convertLine(cameraMatrix, rho_p, theta_p, rho_m2, theta_m2);
199  if (!vpMath::equal(rho_m1, rho_m2, 1e-6) || !vpMath::equal(theta_m1, theta_m2, 1e-6)) {
200  std::cerr << "Error in line pixel meter conversion: visp result (" << rho_m1 << ", " << theta_m1 << ") "
201  << "differ from OpenCV result (" << rho_m2 << ", " << theta_m1 << ")" << std::endl;
202  return EXIT_FAILURE;
203  }
204 
205  std::cout << "* Compare ViSP and OpenCV line meter pixel conversion without distortion" << std::endl;
206  double rho_p1, theta_p1, rho_p2, theta_p2;
207  vpMeterPixelConversion::convertLine(cam, rho_m1, theta_m1, rho_p1, theta_p1);
208  vpMeterPixelConversion::convertLine(cameraMatrix, rho_m1, theta_m1, rho_p2, theta_p2);
209  if (!vpMath::equal(rho_p1, rho_p2, 1e-6) || !vpMath::equal(theta_p1, theta_p2, 1e-6)) {
210  std::cerr << "Error in line meter pixel conversion: visp result (" << rho_p1 << ", " << theta_p1 << ") "
211  << "differ from OpenCV result (" << rho_p2 << ", " << theta_p1 << ")" << std::endl;
212  return EXIT_FAILURE;
213  }
214  }
215 
216  {
217  std::cout << "* Compare ViSP and OpenCV moments pixel meter conversion without distortion" << std::endl;
218  cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << px, 0, u0, 0, py, v0, 0, 0, 1);
219  unsigned int order = 3;
220  double m00 = 2442, m10 = 414992, m01 = 470311, m11 = 7.99558e+07, m02 = 9.09603e+07, m20 = 7.11158e+07;
221 
222  vpMatrix mp(order, order);
223  vpMatrix m1(order, order), m2(order, order);
224 
225  mp[0][0] = m00;
226  mp[1][0] = m10;
227  mp[0][1] = m01;
228  mp[2][0] = m20;
229  mp[1][1] = m11;
230  mp[0][2] = m02;
231 
232  vpPixelMeterConversion::convertMoment(cam, order, mp, m1);
233  vpPixelMeterConversion::convertMoment(cameraMatrix, order, mp, m2);
234  for (unsigned int i = 0; i < m1.getRows(); i++) {
235  for (unsigned int j = 0; j < m1.getCols(); j++) {
236  if (!vpMath::equal(m1[i][j], m1[i][j], 1e-6)) {
237  std::cerr << "Error in moments pixel meter conversion: visp result for [" << i << "][" << j << "] ("
238  << m1[i][j] << ") "
239  << "differ from OpenCV result (" << m2[i][j] << ")" << std::endl;
240  return EXIT_FAILURE;
241  }
242  }
243  }
244  }
245 
246  {
247  std::cout << "* Compare ViSP and OpenCV ellipse from circle meter pixel conversion without distortion"
248  << std::endl;
249  cv::Mat cameraMatrix = (cv::Mat_<double>(3, 3) << px, 0, u0, 0, py, v0, 0, 0, 1);
250  vpCircle circle;
251  circle.setWorldCoordinates(0, 0, 1, 0, 0, 0, 0.1); // plane:(Z=0),X0=0,Y0=0,Z=0,R=0.1
252  vpHomogeneousMatrix cMo(0.1, 0.2, 0.5, vpMath::rad(10), vpMath::rad(5), vpMath::rad(45));
253  circle.changeFrame(cMo);
254  circle.projection();
255  vpImagePoint center_p1, center_p2;
256  double n20_p1, n11_p1, n02_p1, n20_p2, n11_p2, n02_p2;
257 
258  vpMeterPixelConversion::convertEllipse(cam, circle, center_p1, n20_p1, n11_p1, n02_p1);
259  vpMeterPixelConversion::convertEllipse(cameraMatrix, circle, center_p2, n20_p2, n11_p2, n02_p2);
260 
261  if (!vpMath::equal(n20_p1, n20_p2, 1e-6) || !vpMath::equal(n11_p1, n11_p2, 1e-6) ||
262  !vpMath::equal(n02_p1, n02_p2, 1e-6)) {
263  std::cerr << "Error in ellipse from circle meter pixel conversion: visp result (" << n20_p1 << ", " << n11_p1
264  << ", " << n02_p1 << ") "
265  << "differ from OpenCV result (" << n20_p2 << ", " << n11_p2 << ", " << n02_p2 << ")" << std::endl;
266  return EXIT_FAILURE;
267  }
268  if (vpImagePoint::distance(center_p1, center_p2) > 1e-6) {
269  std::cerr << "Error in ellipse from circle meter pixel conversion: visp result (" << center_p1 << ") "
270  << "differ from OpenCV result (" << center_p2 << ")" << std::endl;
271  return EXIT_FAILURE;
272  }
273 
274  std::cout << "* Compare ViSP and OpenCV ellipse from sphere meter pixel conversion without distortion"
275  << std::endl;
276  vpSphere sphere;
277  sphere.setWorldCoordinates(0, 0, 0, 0.1); // X0=0,Y0=0,Z0=0,R=0.1
278  circle.changeFrame(cMo);
279  circle.projection();
280  vpMeterPixelConversion::convertEllipse(cam, sphere, center_p1, n20_p1, n11_p1, n02_p1);
281  vpMeterPixelConversion::convertEllipse(cameraMatrix, sphere, center_p2, n20_p2, n11_p2, n02_p2);
282 
283  if (!vpMath::equal(n20_p1, n20_p2, 1e-6) || !vpMath::equal(n11_p1, n11_p2, 1e-6) ||
284  !vpMath::equal(n02_p1, n02_p2, 1e-6)) {
285  std::cerr << "Error in ellipse from sphere meter pixel conversion: visp result (" << n20_p1 << ", " << n11_p1
286  << ", " << n02_p1 << ") "
287  << "differ from OpenCV result (" << n20_p2 << ", " << n11_p2 << ", " << n02_p2 << ")" << std::endl;
288  return EXIT_FAILURE;
289  }
290  if (vpImagePoint::distance(center_p1, center_p2) > 1e-6) {
291  std::cerr << "Error in ellipse from sphere meter pixel conversion: visp result (" << center_p1 << ") "
292  << "differ from OpenCV result (" << center_p2 << ")" << std::endl;
293  return EXIT_FAILURE;
294  }
295  }
296 #endif
297 
298  std::cout << "Test successful" << std::endl;
299  return EXIT_SUCCESS;
300  }
301  catch (const vpException &e) {
302  std::cout << "Catch an exception: " << e << std::endl;
303  return EXIT_FAILURE;
304  }
305 }
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
void initPersProjWithDistortion(double px, double py, double u0, double v0, double kud, double kdu)
void computeFov(const unsigned int &w, const unsigned int &h)
Class that defines a 3D circle in the object frame and allows forward projection of a 3D circle in th...
Definition: vpCircle.h:87
void changeFrame(const vpHomogeneousMatrix &noMo, vpColVector &noP) const VP_OVERRIDE
Definition: vpCircle.cpp:262
void projection() VP_OVERRIDE
Definition: vpCircle.cpp:144
void setWorldCoordinates(const vpColVector &oP) VP_OVERRIDE
Definition: vpCircle.cpp:57
error that can be emitted by ViSP classes.
Definition: vpException.h:60
Implementation of an homogeneous matrix and operations on such kind of matrices.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
static double rad(double deg)
Definition: vpMath.h:129
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:458
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
static void convertLine(const vpCameraParameters &cam, const double &rho_m, const double &theta_m, double &rho_p, double &theta_p)
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
static void convertEllipse(const vpCameraParameters &cam, const vpSphere &sphere, vpImagePoint &center_p, double &n20_p, double &n11_p, double &n02_p)
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)
Class that defines a 3D sphere in the object frame and allows forward projection of a 3D sphere in th...
Definition: vpSphere.h:80
void setWorldCoordinates(const vpColVector &oP) VP_OVERRIDE
Definition: vpSphere.cpp:59