Visual Servoing Platform  version 3.5.1 under development (2022-08-17)
testMomentAlpha.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  * Test some vpMomentAlpha functionalities.
33  *
34  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
45 #include <string>
46 #include <visp3/core/vpMomentAlpha.h>
47 #include <visp3/core/vpMomentBasic.h>
48 #include <visp3/core/vpMomentCentered.h>
49 #include <visp3/core/vpMomentDatabase.h>
50 #include <visp3/core/vpMomentGravityCenter.h>
51 #include <visp3/core/vpMomentObject.h>
52 #include <visp3/io/vpImageIo.h>
53 
54 int test_moment_alpha(const std::string &name, bool symmetry, const std::vector<int> &vec_angle, double tolerance_deg,
55  double symmetry_threshold = 1e-6)
56 {
58 
59  std::cout << "** Test " << (symmetry == true ? "symmetric " : "non symmetric ") << name << " object" << std::endl;
60 
61  // ***************
62  std::cout << "*** Test symmetry detection from mu 3rd order moments" << std::endl;
63  // ***************
64  std::vector<double> mu_ref;
65  double alpha_ref = 0.;
66  for (unsigned int i = (unsigned int)vec_angle.size(); i >= 1; --i) {
67  // Compute reference alpha image <name>-<vec_angle>[i]deg.pgm
68  std::stringstream ss;
69  ss << name << "-" << vec_angle[i - 1] << "deg.pgm";
70  std::cout << "Process image " << ss.str() << std::endl;
71  vpImageIo::read(I, ss.str());
72 
73  // Consider the case of a reference alpha
74  {
75  vpMomentObject obj(3);
77  obj.fromImage(I, 127,
78  vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
79  vpMomentDatabase db; // Database
80  vpMomentGravityCenter mg; // Declaration of gravity center moment
81  vpMomentCentered mc; // Declaration of centered moments
82  vpMomentAlpha malpha_ref; // Declaration of alpha reference moments
83  mg.linkTo(db); // Add gravity center moment to database
84  mc.linkTo(db); // Add centered moments
85  malpha_ref.linkTo(db); // Add alpha moment
86  db.updateAll(obj); // All of the moments must be updated, not just alpha
87  mg.compute(); // Compute gravity center moment
88  mc.compute(); // Compute centered moments AFTER gravity center
89  malpha_ref.compute(); // Compute alpha gravity center
90 
91  mu_ref.clear();
92  mu_ref.push_back(mc.get(3, 0));
93  mu_ref.push_back(mc.get(2, 1));
94  mu_ref.push_back(mc.get(1, 2));
95  mu_ref.push_back(mc.get(0, 3));
96  alpha_ref = malpha_ref.get();
97  }
98  // Consider the case of a relative alpha
99  {
100  vpMomentObject obj(3);
102  obj.fromImage(I, 127,
103  vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
104  vpMomentDatabase db; // Database
105  vpMomentGravityCenter mg; // Declaration of gravity center moment
106  vpMomentCentered mc; // Declaration of centered moments
107  vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Declaration of alpha relative moments
108  mg.linkTo(db); // Add gravity center moment to database
109  mc.linkTo(db); // Add centered moments
110  malpha.linkTo(db); // Add alpha moment
111  db.updateAll(obj); // All of the moments must be updated, not just alpha
112  mg.compute(); // Compute gravity center moment
113  mc.compute(); // Compute centered moments AFTER gravity center
114  malpha.compute(); // Compute alpha gravity center
115 
116  if (malpha.is_symmetric() != symmetry) {
117  std::cout << "Error in symmety detection" << std::endl;
118  return EXIT_FAILURE;
119  }
120  }
121  }
122 
123  // ***************
124  std::cout << "*** Compute angle in relative mode using the last reference from the previous test" << std::endl;
125  // ***************
126  for (size_t i = 0; i < vec_angle.size(); i++) {
127  std::stringstream ss;
128  ss << name << "-" << vec_angle[i] << "deg.pgm";
129  std::cout << "Process image " << ss.str() << std::endl;
130  vpImageIo::read(I, ss.str());
131 
132  vpMomentObject obj(3);
134  obj.fromImage(I, 127, vpCameraParameters()); // Init the dense object with the image
135  vpMomentDatabase db; // Database
136  vpMomentGravityCenter g; // Declaration of gravity center
137  vpMomentCentered mc; // Centered moments
138  vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Alpha moment relative to the reference alpha
139  g.linkTo(db); // Add gravity center to database
140  mc.linkTo(db); // Add centered moments
141  malpha.linkTo(db); // Add alpha depending on centered moments
142  db.updateAll(obj); // All of the moments must be updated, not just alpha
143  g.compute(); // Compute the moment
144  mc.compute(); // Compute centered moments AFTER gravity center
145  malpha.compute(); // Compute alpha AFTER centered moments.
146 
147  if (!symmetry) {
148  // Tranform input angle from [0; 360] to [-180; +180] range
149  double angle = vec_angle[i];
150  if (angle > 180)
151  angle -= 360;
152  if (angle < -180)
153  angle += 360;
154 
155  std::cout << "alpha expected " << angle << " computed " << vpMath::deg(malpha.get()) << " deg" << std::endl;
156 
157  if (!vpMath::equal(angle, vpMath::deg(malpha.get()), tolerance_deg)) { // 0.5 deg of tolerance
158  std::cout << "Error: result is not in the tolerance: " << tolerance_deg << std::endl;
159  return EXIT_FAILURE;
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 }
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:148
double get(unsigned int i, unsigned int j) const
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:364
void linkTo(vpMomentDatabase &moments)
Definition: vpMoment.cpp:98
Class for generic objects.
This class allows to register all vpMoments so they can access each other according to their dependen...
double get() const
Generic class defining intrinsic camera parameters.
virtual void updateAll(vpMomentObject &object)
This class defines the double-indexed centered moment descriptor .
This class defines the orientation of the object inside the plane parallel to the object...
Class describing 2D gravity center moment.
static double deg(double rad)
Definition: vpMath.h:110