MomentAlpha¶
- class MomentAlpha(*args, **kwargs)¶
Bases:
Moment
This class defines the orientation of the object inside the plane parallel to the object.
In general the value of the moment is computed in \([-\pi/2 ; \pi/2]\) interval by the formula \(\alpha = \frac{1}{2} \mathrm{atan2}(2\mu_{11}, \mu_{20}-\mu_{02})\) .
To obtain a \([-\pi ; \pi]\) precision for non symmetric object, you have to specify a reference information. This reference information is an alpha computed using the previous formula in \([-\pi/2 ; \pi/2]\) . Obtaining this precision comes from third-order centered moments and this reference information.
Therefore there are two modes for vpMomentAlpha and one constructor per mode:
Reference mode using the empty constructor vpMomentAlpha() : The vpMomentAlpha doesn’t need any additional information, it will compute its values from available moments in \([-\pi/2 ; \pi/2]\) .
Relative mode using non-empty constructor vpMomentAlpha(std::vector<double>&, double) : The vpMomentAlpha is computed in \([-\pi ; \pi]\) from the available moments and the reference information. By knowing the reference, it may distinguish in-plane rotations of \(\alpha\) from rotations of \(\alpha + \pi\) .
The following code demonstrates a calculation of a reference alpha and then uses this alpha to estimate the orientation of the same object after performing a 180 degrees rotation. Therefore the first and second alpha should have opposite values.
#include <visp3/core/vpMomentAlpha.h> #include <visp3/core/vpMomentCentered.h> #include <visp3/core/vpMomentDatabase.h> #include <visp3/core/vpMomentGravityCenter.h> #include <visp3/core/vpMomentObject.h> #include <visp3/core/vpPoint.h> //generic function for printing void print (double i) { std::cout << i << "\t";} #ifdef ENABLE_VISP_NAMESPACE using namespace VISP_NAMESPACE_NAME; #endif int main() { vpPoint p; std::vector<vpPoint> vec_p; // Vector that contains the vertices of the contour polygon p.set_x(1); p.set_y(1); // Coordinates in meters in the image plane (vertex 1) vec_p.push_back(p); p.set_x(2); p.set_y(2); // Coordinates in meters in the image plane (vertex 2) vec_p.push_back(p); p.set_x(-3); p.set_y(0); // Coordinates in meters in the image plane (vertex 3) vec_p.push_back(p); p.set_x(-3); p.set_y(-1); // Coordinates in meters in the image plane (vertex 4) vec_p.push_back(p); //////////////////////////////REFERENCE VALUES//////////////////////////////// vpMomentObject objRef(3); // Reference object. Must be of order 3 because we will // need the 3rd order centered moments objRef.setType(vpMomentObject::DENSE_POLYGON); // Object is the inner part of a polygon objRef.fromVector(vec_p); // Init the dense object with the polygon vpMomentDatabase dbRef; // Reference database vpMomentGravityCenter gRef; // Declaration of gravity center vpMomentCentered mcRef; // Centered moments vpMomentAlpha alphaRef; // Declare alpha as reference gRef.linkTo(dbRef); // Add gravity center to database mcRef.linkTo(dbRef); // Add centered moments alphaRef.linkTo(dbRef); // Add alpha depending on centered moments dbRef.updateAll(objRef); // All of the moments must be updated, not just alpha gRef.compute(); // Compute the moment mcRef.compute(); // Compute centered moments AFTER gravity center alphaRef.compute(); // Compute alpha AFTER centered moments. // The order of values in the vector must be as follows: mu30 mu21 mu12 mu03 std::vector<double> mu3ref = {mcRef.get(3,0), mcRef.get(2,1), mcRef.get(1,2), mcRef.get(0,3)}; std::cout << "--- Reference object ---" << std::endl; std::cout << "alphaRef=" << vpMath::deg(alphaRef.get()) << " deg" << std::endl << "mu3="; // print reference alpha std::for_each (mu3ref.begin(), mu3ref.end(), print); std::cout << std::endl; ////////////CURRENT VALUES (same object rotated 180deg - must be ////////////entered in reverse order)//////////////// vec_p.clear(); p.set_x(-3); p.set_y(1); // Coordinates in meters in the image plane (vertex 4) vec_p.push_back(p); p.set_x(-3); p.set_y(0); // Coordinates in meters in the image plane (vertex 3) vec_p.push_back(p); p.set_x(2); p.set_y(-2); // Coordinates in meters in the image plane (vertex 2) vec_p.push_back(p); p.set_x(1); p.set_y(-1); // Coordinates in meters in the image plane (vertex 1) vec_p.push_back(p); vpMomentObject obj(3); // Second object. Order 3 is also required because of the Alpha // will compare third-order centered moments to given reference. obj.setType(vpMomentObject::DENSE_POLYGON); // Object is the inner part of a polygon obj.fromVector(vec_p); // Init the dense object with the polygon vpMomentDatabase db; // Database vpMomentGravityCenter g; // Declaration of gravity center vpMomentCentered mc; // mc contains centered moments vpMomentAlpha alpha(mu3ref, alphaRef.get()); // Declare alpha as relative to a reference g.linkTo(db); // Add gravity center to database mc.linkTo(db); // Add centered moments alpha.linkTo(db); // Add alpha depending on centered moments db.updateAll(obj); // All of the moments must be updated g.compute(); // Compute the moment mc.compute(); // Compute centered moments AFTER gravity center alpha.compute(); // Compute alpha AFTER centered moments. std::cout << "--- current object ---" << std::endl; std::cout << "alpha=" << vpMath::deg(alpha.get()) << " deg" << std::endl; return 0; }
This program outputs:
--- Reference object --- alphaRef=25.3019 deg mu3=1.80552 0.921882 0.385828 0.122449 --- current object --- alpha=-25.3019 deg
There is also testMomentAlpha.cpp example that shows how to compute alpha in the range \([-\pi ; \pi]\) using arrow images as input. The code is given below:
/* * 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) { vpImage<unsigned char> I; 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 { vpMomentObject obj(3); obj.setType( vpMomentObject::DENSE_FULL_OBJECT ); 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 { vpMomentObject obj(3); obj.setType( vpMomentObject::DENSE_FULL_OBJECT ); 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()); vpMomentObject obj(3); obj.setType( vpMomentObject::DENSE_FULL_OBJECT ); 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; }
From the first image we compute the 3rd order centered moments and the value of the reference alpha that is than used to compute the alpha moment in the range \([-\pi ; \pi]\) . Running this example you will get:
alpha expected 0 computed -0.128108 deg alpha expected 45 computed 44.8881 deg alpha expected 90 computed 89.8719 deg alpha expected 135 computed 134.888 deg alpha expected 180 computed 179.872 deg alpha expected -135 computed -135.112 deg alpha expected -90 computed -90.1281 deg alpha expected -45 computed -45.1119 deg
Shortcuts for quickly getting those references exist in vpMomentCommon .
This moment depends on vpMomentCentered .
Overloaded function.
__init__(self: visp._visp.core.MomentAlpha) -> None
Empty constructor. Initializes alpha moment as a reference alpha with a value in \([-\pi/2 ; \pi/2]\) . A default-constructed alpha moment may be used as a reference information for other alphas. A reference alpha is a class harbouring an alpha value computed for a \([-\pi/2 ; \pi/2]\) portion of the circle.
__init__(self: visp._visp.core.MomentAlpha, mu3_ref: list[float], alpha_ref: float, threshold: float = 1e-6) -> None
Common constructor. Initializes alpha moment as a non-reference alpha with a value computed in \([-\pi ; \pi]\) when the object is non symmetric.
- Parameters:
- mu3_ref
Vector of 3rd order centered moments corresponding to the reference alpha in the following order: \(\mu_{30},\mu_{21},\mu_{12},\mu_{03}\) .
- alpha_ref
Value of the reference alpha that has mu3_ref 3rd order moments.
- threshold
Threshold used to determine object symmetry along its 2 axis. The object is declared symmetric if all the four 3rd order centered moments mu3_ref have values lower than this threshold. If the object is symmetric, the alpha angle is commuted in [ \([-\pi/2 ; \pi/2]\) ]. If the object is non symmetric, the alpha angle is commuted in [ \([-\pi ; \pi]\) ]
Methods
Overloaded function.
Compute the value of the alpha-moment.
Overloaded function.
Returns true if the alpha moment was constructed as a reference with values in \([-\pi/2 ; \pi/2]\) , false otherwise.
Returns true if the alpha moment is computed on a symmetric object along its two axis.
Moment name.
Overloaded function.
Inherited Methods
Updates the moment with the current object.
Links the moment to a database of moment primitives.
Operators
__doc__
Overloaded function.
__module__
__repr__
Attributes
__annotations__
- __init__(*args, **kwargs)¶
Overloaded function.
__init__(self: visp._visp.core.MomentAlpha) -> None
Empty constructor. Initializes alpha moment as a reference alpha with a value in \([-\pi/2 ; \pi/2]\) . A default-constructed alpha moment may be used as a reference information for other alphas. A reference alpha is a class harbouring an alpha value computed for a \([-\pi/2 ; \pi/2]\) portion of the circle.
__init__(self: visp._visp.core.MomentAlpha, mu3_ref: list[float], alpha_ref: float, threshold: float = 1e-6) -> None
Common constructor. Initializes alpha moment as a non-reference alpha with a value computed in \([-\pi ; \pi]\) when the object is non symmetric.
- Parameters:
- mu3_ref
Vector of 3rd order centered moments corresponding to the reference alpha in the following order: \(\mu_{30},\mu_{21},\mu_{12},\mu_{03}\) .
- alpha_ref
Value of the reference alpha that has mu3_ref 3rd order moments.
- threshold
Threshold used to determine object symmetry along its 2 axis. The object is declared symmetric if all the four 3rd order centered moments mu3_ref have values lower than this threshold. If the object is symmetric, the alpha angle is commuted in [ \([-\pi/2 ; \pi/2]\) ]. If the object is non symmetric, the alpha angle is commuted in [ \([-\pi ; \pi]\) ]
- get(*args, **kwargs)¶
Overloaded function.
get(self: visp._visp.core.MomentAlpha) -> float
Retrieve the orientation of the object as a single double value.
get(self: visp._visp.core.Moment) -> list[float]
- Returns:
vector of values
- getObject(self) visp._visp.core.MomentObject ¶
- is_ref(self) bool ¶
Returns true if the alpha moment was constructed as a reference with values in \([-\pi/2 ; \pi/2]\) , false otherwise.
- is_symmetric(self) bool ¶
Returns true if the alpha moment is computed on a symmetric object along its two axis. Symmetry is computed using 3rd order centered moments \(\mu_{30},\mu_{21},\mu_{12},\mu_{03}\) .
- linkTo(self, moments: visp._visp.core.MomentDatabase) None ¶
Links the moment to a database of moment primitives. If the moment depends on other moments, these moments must be linked to the same database.
Warning
Two moments of the same class cannot be stored in the same database
#include <visp3/core/vpMomentCentered.h> #include <visp3/core/vpMomentDatabase.h> #include <visp3/core/vpMomentGravityCenter.h> #include <visp3/core/vpMomentObject.h> #include <visp3/core/vpPoint.h> #ifdef ENABLE_VISP_NAMESPACE using namespace VISP_NAMESPACE_NAME; #endif int main() { vpPoint p; std::vector<vpPoint> vec_p; p.set_x(1); p.set_y(1); // coordinates in meters in the image plane (vertex 1) vec_p.push_back(p); p.set_x(2); p.set_y(2); // coordinates in meters in the image plane (vertex 2) vec_p.push_back(p); vpMomentObject obj(2); obj.setType(vpMomentObject::DISCRETE); // Discrete mode. obj.fromVector(vec_p); // Init the dense object with the polygon vpMomentDatabase db; vpMomentGravityCenter G; // declaration of gravity center vpMomentCentered mc; // mc contains centered moments G.linkTo(db); // add gravity center to database mc.linkTo(db); // centered moments depend on gravity, add them to the // database to grant access G.update(obj); // specify the object for gravity center mc.update(obj); // and for centered moments G.compute(); // compute the moment mc.compute(); // compute centered moments AFTER gravity center return 0; }
- printDependencies(*args, **kwargs)¶
Overloaded function.
printDependencies(self: visp._visp.core.MomentAlpha, os: std::ostream) -> None
Prints the dependencies of alpha, namely centered moments mu11, mu20 ad mu02
printDependencies(self: visp._visp.core.Moment, os: std::ostream) -> None
Prints values of all dependent moments required to calculate a specific vpMoment . Not made pure to maintain compatibility Recommended : Types inheriting from vpMoment should implement this function
- update(self, object: visp._visp.core.MomentObject) None ¶
Updates the moment with the current object. This does not compute any values.