Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
testMomentAlpha.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  * Test some vpMomentAlpha functionalities.
32  */
33 
40 #include <string>
41 #include <visp3/core/vpMomentAlpha.h>
42 #include <visp3/core/vpMomentBasic.h>
43 #include <visp3/core/vpMomentCentered.h>
44 #include <visp3/core/vpMomentDatabase.h>
45 #include <visp3/core/vpMomentGravityCenter.h>
46 #include <visp3/core/vpMomentObject.h>
47 #include <visp3/io/vpImageIo.h>
48 
49 #ifdef ENABLE_VISP_NAMESPACE
50 using namespace VISP_NAMESPACE_NAME;
51 #endif
52 
53 int test_moment_alpha(const std::string &name, bool symmetry, const std::vector<int> &vec_angle, double tolerance_deg,
54  double symmetry_threshold = 1e-6)
55 {
57 
58  std::cout << "** Test " << (symmetry == true ? "symmetric " : "non symmetric ") << name << " object" << std::endl;
59 
60  // ***************
61  std::cout << "*** Test symmetry detection from mu 3rd order moments" << std::endl;
62  // ***************
63  std::vector<double> mu_ref;
64  double alpha_ref = 0.;
65  for (unsigned int i = (unsigned int)vec_angle.size(); i >= 1; --i) {
66  // Compute reference alpha image <name>-<vec_angle>[i]deg.pgm
67  std::stringstream ss;
68  ss << name << "-" << vec_angle[i - 1] << "deg.pgm";
69  std::cout << "Process image " << ss.str() << std::endl;
70  vpImageIo::read(I, ss.str());
71 
72  // Consider the case of a reference alpha
73  {
74  vpMomentObject obj(3);
76  obj.fromImage(I, 127,
77  vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
78  vpMomentDatabase db; // Database
79  vpMomentGravityCenter mg; // Declaration of gravity center moment
80  vpMomentCentered mc; // Declaration of centered moments
81  vpMomentAlpha malpha_ref; // Declaration of alpha reference moments
82  mg.linkTo(db); // Add gravity center moment to database
83  mc.linkTo(db); // Add centered moments
84  malpha_ref.linkTo(db); // Add alpha moment
85  db.updateAll(obj); // All of the moments must be updated, not just alpha
86  mg.compute(); // Compute gravity center moment
87  mc.compute(); // Compute centered moments AFTER gravity center
88  malpha_ref.compute(); // Compute alpha gravity center
89 
90  mu_ref.clear();
91  mu_ref.push_back(mc.get(3, 0));
92  mu_ref.push_back(mc.get(2, 1));
93  mu_ref.push_back(mc.get(1, 2));
94  mu_ref.push_back(mc.get(0, 3));
95  alpha_ref = malpha_ref.get();
96  }
97  // Consider the case of a relative alpha
98  {
99  vpMomentObject obj(3);
101  obj.fromImage(I, 127,
102  vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
103  vpMomentDatabase db; // Database
104  vpMomentGravityCenter mg; // Declaration of gravity center moment
105  vpMomentCentered mc; // Declaration of centered moments
106  vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Declaration of alpha relative moments
107  mg.linkTo(db); // Add gravity center moment to database
108  mc.linkTo(db); // Add centered moments
109  malpha.linkTo(db); // Add alpha moment
110  db.updateAll(obj); // All of the moments must be updated, not just alpha
111  mg.compute(); // Compute gravity center moment
112  mc.compute(); // Compute centered moments AFTER gravity center
113  malpha.compute(); // Compute alpha gravity center
114 
115  if (malpha.is_symmetric() != symmetry) {
116  std::cout << "Error in symmety detection" << std::endl;
117  return EXIT_FAILURE;
118  }
119  }
120  }
121 
122  // ***************
123  std::cout << "*** Compute angle in relative mode using the last reference from the previous test" << std::endl;
124  // ***************
125  for (size_t i = 0; i < vec_angle.size(); i++) {
126  std::stringstream ss;
127  ss << name << "-" << vec_angle[i] << "deg.pgm";
128  std::cout << "Process image " << ss.str() << std::endl;
129  vpImageIo::read(I, ss.str());
130 
131  vpMomentObject obj(3);
133  obj.fromImage(I, 127, vpCameraParameters()); // Init the dense object with the image
134  vpMomentDatabase db; // Database
135  vpMomentGravityCenter g; // Declaration of gravity center
136  vpMomentCentered mc; // Centered moments
137  vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Alpha moment relative to the reference alpha
138  g.linkTo(db); // Add gravity center to database
139  mc.linkTo(db); // Add centered moments
140  malpha.linkTo(db); // Add alpha depending on centered moments
141  db.updateAll(obj); // All of the moments must be updated, not just alpha
142  g.compute(); // Compute the moment
143  mc.compute(); // Compute centered moments AFTER gravity center
144  malpha.compute(); // Compute alpha AFTER centered moments.
145 
146  if (!symmetry) {
147  // Tranform input angle from [0; 360] to [-180; +180] range
148  double angle = vec_angle[i];
149  if (angle > 180)
150  angle -= 360;
151  if (angle < -180)
152  angle += 360;
153 
154  std::cout << "alpha expected " << angle << " computed " << vpMath::deg(malpha.get()) << " deg" << std::endl;
155 
156  if (!vpMath::equal(angle, vpMath::deg(malpha.get()), tolerance_deg)) { // 0.5 deg of tolerance
157  std::cout << "Error: result is not in the tolerance: " << tolerance_deg << std::endl;
158  return EXIT_FAILURE;
159  }
160  }
161  else {
162  // Tranform input angle from [0; 360] to [0; 180] range
163  double angle_des1 = vec_angle[i];
164  double angle_des2 = vec_angle[i] - 180;
165 
166  // Tranform input angle from [0; 360] to [0; 180] range
167  double alpha = vpMath::deg(malpha.get());
168 
169  std::cout << "alpha expected " << angle_des1 << " or " << angle_des2 << " computed " << alpha << " deg"
170  << std::endl;
171 
172  if (!vpMath::equal(angle_des1, alpha, tolerance_deg) &&
173  !vpMath::equal(angle_des2, alpha, tolerance_deg)) { // 0.5 deg of tolerance
174  std::cout << "Error: result is not in the tolerance: " << tolerance_deg << std::endl;
175  return EXIT_FAILURE;
176  }
177  }
178  }
179  std::cout << "Test succeed" << std::endl;
180  return EXIT_SUCCESS;
181 }
182 
183 int main()
184 {
185  std::string name;
186  bool symmetry;
187  double tolerance_deg;
188  std::vector<int> vec_angle;
189  double symmetry_threshold;
190 
191  // *******************************
192  // Test arrow
193  // *******************************
194  name = "arrow";
195  symmetry = false;
196  tolerance_deg = 0.5;
197  vec_angle.clear();
198  vec_angle.push_back(0);
199  vec_angle.push_back(45);
200  vec_angle.push_back(90);
201  vec_angle.push_back(135);
202  vec_angle.push_back(180);
203  vec_angle.push_back(225);
204  vec_angle.push_back(270);
205  vec_angle.push_back(315);
206 
207  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
208  return EXIT_FAILURE;
209  }
210 
211  // *******************************
212  // Test ellipse created with gimp
213  // *******************************
214  name = "ellipse";
215  symmetry = true;
216  tolerance_deg = 0.5;
217  vec_angle.clear();
218  vec_angle.push_back(0);
219  vec_angle.push_back(45);
220  vec_angle.push_back(90);
221  vec_angle.push_back(135);
222 
223  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
224  return EXIT_FAILURE;
225  }
226 
227  // *******************************
228  // Test ellipse created with xfig
229  // *******************************
230  name = "ellipse-xfig";
231  symmetry = true;
232  tolerance_deg = 2.5;
233  symmetry_threshold = 1e-2; // Modify default value
234  vec_angle.clear();
235  vec_angle.push_back(0);
236  vec_angle.push_back(45);
237  vec_angle.push_back(90);
238  vec_angle.push_back(135);
239 
240  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg, symmetry_threshold) == EXIT_FAILURE) {
241  return EXIT_FAILURE;
242  }
243 
244  // *******************************
245  // Test baleine created with gimp
246  // *******************************
247  name = "baleine";
248  symmetry = false;
249  tolerance_deg = 5.;
250  vec_angle.clear();
251  vec_angle.push_back(0);
252  vec_angle.push_back(45);
253  vec_angle.push_back(90);
254  vec_angle.push_back(135);
255  vec_angle.push_back(180);
256  vec_angle.push_back(225);
257  vec_angle.push_back(270);
258  vec_angle.push_back(315);
259 
260  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
261  return EXIT_FAILURE;
262  }
263 
264  return EXIT_SUCCESS;
265 }
Generic class defining intrinsic camera parameters.
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:147
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:458
static double deg(double rad)
Definition: vpMath.h:119
This class defines the orientation of the object inside the plane parallel to the object.
double get() const
This class defines the double-indexed centered moment descriptor .
double get(unsigned int i, unsigned int j) const
This class allows to register all vpMoments so they can access each other according to their dependen...
virtual void updateAll(vpMomentObject &object)
Class describing 2D gravity center moment.
Class for generic objects.
void linkTo(vpMomentDatabase &moments)
Definition: vpMoment.cpp:114