Visual Servoing Platform  version 3.6.1 under development (2024-10-13)
testMomentAlpha.cpp

Test for vpMomentAlpha class.

/*
* ViSP, open source Visual Servoing Platform software.
* Copyright (C) 2005 - 2024 by Inria. All rights reserved.
*
* This software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* See the file LICENSE.txt at the root directory of this source
* distribution for additional information about the GNU GPL.
*
* For using ViSP with software that can not be combined with the GNU
* GPL, please contact Inria about acquiring a ViSP Professional
* Edition License.
*
* See https://visp.inria.fr for more information.
*
* This software was developed at:
* Inria Rennes - Bretagne Atlantique
* Campus Universitaire de Beaulieu
* 35042 Rennes Cedex
* France
*
* If you have questions regarding the use of this file, please contact
* Inria at visp@inria.fr
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Description:
* Test some vpMomentAlpha functionalities.
*/
#include <string>
#include <visp3/core/vpMomentAlpha.h>
#include <visp3/core/vpMomentBasic.h>
#include <visp3/core/vpMomentCentered.h>
#include <visp3/core/vpMomentDatabase.h>
#include <visp3/core/vpMomentGravityCenter.h>
#include <visp3/core/vpMomentObject.h>
#include <visp3/io/vpImageIo.h>
#ifdef ENABLE_VISP_NAMESPACE
using namespace VISP_NAMESPACE_NAME;
#endif
int test_moment_alpha(const std::string &name, bool symmetry, const std::vector<int> &vec_angle, double tolerance_deg,
double symmetry_threshold = 1e-6)
{
std::cout << "** Test " << (symmetry == true ? "symmetric " : "non symmetric ") << name << " object" << std::endl;
// ***************
std::cout << "*** Test symmetry detection from mu 3rd order moments" << std::endl;
// ***************
std::vector<double> mu_ref;
double alpha_ref = 0.;
for (unsigned int i = (unsigned int)vec_angle.size(); i >= 1; --i) {
// Compute reference alpha image <name>-<vec_angle>[i]deg.pgm
std::stringstream ss;
ss << name << "-" << vec_angle[i - 1] << "deg.pgm";
std::cout << "Process image " << ss.str() << std::endl;
vpImageIo::read(I, ss.str());
// Consider the case of a reference alpha
{
obj.fromImage(I, 127,
vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
vpMomentDatabase db; // Database
vpMomentGravityCenter mg; // Declaration of gravity center moment
vpMomentCentered mc; // Declaration of centered moments
vpMomentAlpha malpha_ref; // Declaration of alpha reference moments
mg.linkTo(db); // Add gravity center moment to database
mc.linkTo(db); // Add centered moments
malpha_ref.linkTo(db); // Add alpha moment
db.updateAll(obj); // All of the moments must be updated, not just alpha
mg.compute(); // Compute gravity center moment
mc.compute(); // Compute centered moments AFTER gravity center
malpha_ref.compute(); // Compute alpha gravity center
mu_ref.clear();
mu_ref.push_back(mc.get(3, 0));
mu_ref.push_back(mc.get(2, 1));
mu_ref.push_back(mc.get(1, 2));
mu_ref.push_back(mc.get(0, 3));
alpha_ref = malpha_ref.get();
}
// Consider the case of a relative alpha
{
obj.fromImage(I, 127,
vpCameraParameters()); // Init the dense object with the image and corresponding camera parameters
vpMomentDatabase db; // Database
vpMomentGravityCenter mg; // Declaration of gravity center moment
vpMomentCentered mc; // Declaration of centered moments
vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Declaration of alpha relative moments
mg.linkTo(db); // Add gravity center moment to database
mc.linkTo(db); // Add centered moments
malpha.linkTo(db); // Add alpha moment
db.updateAll(obj); // All of the moments must be updated, not just alpha
mg.compute(); // Compute gravity center moment
mc.compute(); // Compute centered moments AFTER gravity center
malpha.compute(); // Compute alpha gravity center
if (malpha.is_symmetric() != symmetry) {
std::cout << "Error in symmety detection" << std::endl;
return EXIT_FAILURE;
}
}
}
// ***************
std::cout << "*** Compute angle in relative mode using the last reference from the previous test" << std::endl;
// ***************
for (size_t i = 0; i < vec_angle.size(); i++) {
std::stringstream ss;
ss << name << "-" << vec_angle[i] << "deg.pgm";
std::cout << "Process image " << ss.str() << std::endl;
vpImageIo::read(I, ss.str());
obj.fromImage(I, 127, vpCameraParameters()); // Init the dense object with the image
vpMomentDatabase db; // Database
vpMomentGravityCenter g; // Declaration of gravity center
vpMomentCentered mc; // Centered moments
vpMomentAlpha malpha(mu_ref, alpha_ref, symmetry_threshold); // Alpha moment relative to the reference alpha
g.linkTo(db); // Add gravity center to database
mc.linkTo(db); // Add centered moments
malpha.linkTo(db); // Add alpha depending on centered moments
db.updateAll(obj); // All of the moments must be updated, not just alpha
g.compute(); // Compute the moment
mc.compute(); // Compute centered moments AFTER gravity center
malpha.compute(); // Compute alpha AFTER centered moments.
if (!symmetry) {
// Tranform input angle from [0; 360] to [-180; +180] range
double angle = vec_angle[i];
if (angle > 180)
angle -= 360;
if (angle < -180)
angle += 360;
std::cout << "alpha expected " << angle << " computed " << vpMath::deg(malpha.get()) << " deg" << std::endl;
if (!vpMath::equal(angle, vpMath::deg(malpha.get()), tolerance_deg)) { // 0.5 deg of tolerance
std::cout << "Error: result is not in the tolerance: " << tolerance_deg << std::endl;
return EXIT_FAILURE;
}
}
else {
// Tranform input angle from [0; 360] to [0; 180] range
double angle_des1 = vec_angle[i];
double angle_des2 = vec_angle[i] - 180;
// Tranform input angle from [0; 360] to [0; 180] range
double alpha = vpMath::deg(malpha.get());
std::cout << "alpha expected " << angle_des1 << " or " << angle_des2 << " computed " << alpha << " deg"
<< std::endl;
if (!vpMath::equal(angle_des1, alpha, tolerance_deg) &&
!vpMath::equal(angle_des2, alpha, tolerance_deg)) { // 0.5 deg of tolerance
std::cout << "Error: result is not in the tolerance: " << tolerance_deg << std::endl;
return EXIT_FAILURE;
}
}
}
std::cout << "Test succeed" << std::endl;
return EXIT_SUCCESS;
}
int main()
{
std::string name;
bool symmetry;
double tolerance_deg;
std::vector<int> vec_angle;
double symmetry_threshold;
// *******************************
// Test arrow
// *******************************
name = "arrow";
symmetry = false;
tolerance_deg = 0.5;
vec_angle.clear();
vec_angle.push_back(0);
vec_angle.push_back(45);
vec_angle.push_back(90);
vec_angle.push_back(135);
vec_angle.push_back(180);
vec_angle.push_back(225);
vec_angle.push_back(270);
vec_angle.push_back(315);
if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
// *******************************
// Test ellipse created with gimp
// *******************************
name = "ellipse";
symmetry = true;
tolerance_deg = 0.5;
vec_angle.clear();
vec_angle.push_back(0);
vec_angle.push_back(45);
vec_angle.push_back(90);
vec_angle.push_back(135);
if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
// *******************************
// Test ellipse created with xfig
// *******************************
name = "ellipse-xfig";
symmetry = true;
tolerance_deg = 2.5;
symmetry_threshold = 1e-2; // Modify default value
vec_angle.clear();
vec_angle.push_back(0);
vec_angle.push_back(45);
vec_angle.push_back(90);
vec_angle.push_back(135);
if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg, symmetry_threshold) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
// *******************************
// Test baleine created with gimp
// *******************************
name = "baleine";
symmetry = false;
tolerance_deg = 5.;
vec_angle.clear();
vec_angle.push_back(0);
vec_angle.push_back(45);
vec_angle.push_back(90);
vec_angle.push_back(135);
vec_angle.push_back(180);
vec_angle.push_back(225);
vec_angle.push_back(270);
vec_angle.push_back(315);
if (test_moment_alpha(name, symmetry, vec_angle, tolerance_deg) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
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:459
static double deg(double rad)
Definition: vpMath.h:119
This class defines the orientation of the object inside the plane parallel to the object.
bool is_symmetric() const
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 setType(vpObjectType input_type)
void fromImage(const vpImage< unsigned char > &image, unsigned char threshold, const vpCameraParameters &cam)
void linkTo(vpMomentDatabase &moments)
Definition: vpMoment.cpp:114