Visual Servoing Platform  version 3.4.1 under development (2021-07-24)
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/vpMomentObject.h>
47 #include <visp3/core/vpMomentGravityCenter.h>
48 #include <visp3/core/vpMomentDatabase.h>
49 #include <visp3/core/vpMomentCentered.h>
50 #include <visp3/core/vpMomentAlpha.h>
51 #include <visp3/core/vpMomentBasic.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, 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, vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
77  vpMomentDatabase db; // Database
78  vpMomentGravityCenter mg; // Declaration of gravity center moment
79  vpMomentCentered mc; // Declaration of centered moments
80  vpMomentAlpha malpha_ref; // Declaration of alpha reference moments
81  mg.linkTo(db); // Add gravity center moment to database
82  mc.linkTo(db); // Add centered moments
83  malpha_ref.linkTo(db); // Add alpha moment
84  db.updateAll(obj); // All of the moments must be updated, not just alpha
85  mg.compute(); // Compute gravity center moment
86  mc.compute(); // Compute centered moments AFTER gravity center
87  malpha_ref.compute(); // Compute alpha gravity center
88 
89  mu_ref.clear();
90  mu_ref.push_back(mc.get(3,0));
91  mu_ref.push_back(mc.get(2,1));
92  mu_ref.push_back(mc.get(1,2));
93  mu_ref.push_back(mc.get(0,3));
94  alpha_ref = malpha_ref.get();
95  }
96  // Consider the case of a relative alpha
97  {
98  vpMomentObject obj(3);
100  obj.fromImage(I, 127, vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
101  vpMomentDatabase db; // Database
102  vpMomentGravityCenter mg; // Declaration of gravity center moment
103  vpMomentCentered mc; // Declaration of centered moments
104  vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Declaration of alpha relative moments
105  mg.linkTo(db); // Add gravity center moment to database
106  mc.linkTo(db); // Add centered moments
107  malpha.linkTo(db); // Add alpha moment
108  db.updateAll(obj); // All of the moments must be updated, not just alpha
109  mg.compute(); // Compute gravity center moment
110  mc.compute(); // Compute centered moments AFTER gravity center
111  malpha.compute(); // Compute alpha gravity center
112 
113  if (malpha.is_symmetric() != symmetry) {
114  std::cout << "Error in symmety detection" << std::endl;
115  return EXIT_FAILURE;
116  }
117  }
118  }
119 
120  // ***************
121  std::cout << "*** Compute angle in relative mode using the last reference from the previous test" << std::endl;
122  // ***************
123  for(size_t i = 0; i < vec_angle.size(); i++) {
124  std::stringstream ss;
125  ss << name << "-" << vec_angle[i] << "deg.pgm";
126  std::cout << "Process image " << ss.str() << std::endl;
127  vpImageIo::read(I, ss.str());
128 
129  vpMomentObject obj(3);
131  obj.fromImage(I, 127, vpCameraParameters()); // Init the dense object with the image
132  vpMomentDatabase db; // Database
133  vpMomentGravityCenter g; // Declaration of gravity center
134  vpMomentCentered mc; // Centered moments
135  vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Alpha moment relative to the reference alpha
136  g.linkTo(db); // Add gravity center to database
137  mc.linkTo(db); // Add centered moments
138  malpha.linkTo(db); // Add alpha depending on centered moments
139  db.updateAll(obj); // All of the moments must be updated, not just alpha
140  g.compute(); // Compute the moment
141  mc.compute(); // Compute centered moments AFTER gravity center
142  malpha.compute(); // Compute alpha AFTER centered moments.
143 
144  if (! symmetry) {
145  // Tranform input angle from [0; 360] to [-180; +180] range
146  double angle = vec_angle[i];
147  if (angle > 180)
148  angle -= 360;
149  if (angle < -180)
150  angle += 360;
151 
152  std::cout << "alpha expected " << angle << " computed " << vpMath::deg(malpha.get()) << " deg" << std::endl;
153 
154  if (! vpMath::equal(angle, vpMath::deg(malpha.get()), tolerance_deg)) { // 0.5 deg of tolerance
155  std::cout << "Error: result is not in the tolerance: " << tolerance_deg << std::endl;
156  return EXIT_FAILURE;
157  }
158  }
159  else {
160  // Tranform input angle from [0; 360] to [0; 180] range
161  double angle_des1 = vec_angle[i];
162  double angle_des2 = vec_angle[i] - 180;
163 
164  // Tranform input angle from [0; 360] to [0; 180] range
165  double alpha = vpMath::deg(malpha.get());
166 
167  std::cout << "alpha expected " << angle_des1 << " or " << angle_des2 << " computed " << alpha << " deg" << std::endl;
168 
169  if (! vpMath::equal(angle_des1, alpha, tolerance_deg) && ! vpMath::equal(angle_des2, alpha, tolerance_deg)) { // 0.5 deg of tolerance
170  std::cout << "Error: result is not in the tolerance: " << tolerance_deg << std::endl;
171  return EXIT_FAILURE;
172  }
173  }
174  }
175  std::cout << "Test succeed" << std::endl;
176  return EXIT_SUCCESS;
177 }
178 
179 int main()
180 {
181  std::string name;
182  bool symmetry;
183  double tolerance_deg;
184  std::vector<int> vec_angle;
185  double symmetry_threshold;
186 
187  // *******************************
188  // Test arrow
189  // *******************************
190  name = "arrow";
191  symmetry = false;
192  tolerance_deg = 0.5;
193  vec_angle.clear();
194  vec_angle.push_back(0);
195  vec_angle.push_back(45);
196  vec_angle.push_back(90);
197  vec_angle.push_back(135);
198  vec_angle.push_back(180);
199  vec_angle.push_back(225);
200  vec_angle.push_back(270);
201  vec_angle.push_back(315);
202 
203  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
204  return EXIT_FAILURE;
205  }
206 
207  // *******************************
208  // Test ellipse created with gimp
209  // *******************************
210  name = "ellipse";
211  symmetry = true;
212  tolerance_deg = 0.5;
213  vec_angle.clear();
214  vec_angle.push_back(0);
215  vec_angle.push_back(45);
216  vec_angle.push_back(90);
217  vec_angle.push_back(135);
218 
219  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
220  return EXIT_FAILURE;
221  }
222 
223  // *******************************
224  // Test ellipse created with xfig
225  // *******************************
226  name = "ellipse-xfig";
227  symmetry = true;
228  tolerance_deg = 2.5;
229  symmetry_threshold = 1e-2; // Modify default value
230  vec_angle.clear();
231  vec_angle.push_back(0);
232  vec_angle.push_back(45);
233  vec_angle.push_back(90);
234  vec_angle.push_back(135);
235 
236  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg, symmetry_threshold) == EXIT_FAILURE) {
237  return EXIT_FAILURE;
238  }
239 
240  // *******************************
241  // Test baleine created with gimp
242  // *******************************
243  name = "baleine";
244  symmetry = false;
245  tolerance_deg = 5.;
246  vec_angle.clear();
247  vec_angle.push_back(0);
248  vec_angle.push_back(45);
249  vec_angle.push_back(90);
250  vec_angle.push_back(135);
251  vec_angle.push_back(180);
252  vec_angle.push_back(225);
253  vec_angle.push_back(270);
254  vec_angle.push_back(315);
255 
256  if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
257  return EXIT_FAILURE;
258  }
259 
260  return EXIT_SUCCESS;
261 }
double get(unsigned int i, unsigned int j) const
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:293
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:103
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:244