ViSP  2.10.0
vpMomentCInvariant.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMomentCInvariant.cpp 5304 2015-02-10 17:03:04Z mbakthav $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Descriptor for various invariants used to drive space roations around X and Y axis.
36  *
37  * Authors:
38  * Filip Novotny
39  *
40  *****************************************************************************/
41 
42 #include <visp/vpMomentCInvariant.h>
43 #include <visp/vpMomentCentered.h>
44 #include <visp/vpMomentObject.h>
45 
50 vpMomentCInvariant::vpMomentCInvariant(bool flg_sxsynormalization)
51  : I(16),II(4),c(4),s(4), K(0.0), cn(4),sn(4), In1(0.0), flg_sxsynormalization_(flg_sxsynormalization)
52 {
53  values.resize(14);
54 }
55 
61 void vpMomentCInvariant::computeI(const vpMomentCentered& momentCentered, std::vector<double>& I_val){
62 
63  double mu30 = momentCentered.get(3,0);
64  double mu30_2 = mu30*mu30;
65  double mu30_3 = mu30_2*mu30;
66 
67  double mu03 = momentCentered.get(0,3);
68  double mu03_2 = mu03*mu03;
69  double mu03_3 = mu03*mu03_2;
70 
71  double mu20 = momentCentered.get(2,0);
72  double mu02 = momentCentered.get(0,2);
73  double mu50 = momentCentered.get(5,0);
74  double mu32 = momentCentered.get(3,2);
75  double mu14 = momentCentered.get(1,4);
76  double mu05 = momentCentered.get(0,5);
77  double mu23 = momentCentered.get(2,3);
78  double mu41 = momentCentered.get(4,1);
79  double mu40 = momentCentered.get(4,0);
80  double mu04 = momentCentered.get(0,4);
81  double mu31 = momentCentered.get(3,1);
82  double mu13 = momentCentered.get(1,3);
83  double mu22 = momentCentered.get(2,2);
84  double mu21 = momentCentered.get(2,1);
85  double mu12 = momentCentered.get(1,2);
86  double mu11 = momentCentered.get(1,1);
87 
88  double mu11_2 = mu11*mu11;
89  double mu12_2 = mu12*mu12;
90  double mu21_2 = mu21*mu21;
91  double mu22_2 = mu22*mu22;
92  double mu13_2 = mu13*mu13;
93  double mu31_2 = mu31*mu31;
94  double mu04_2 = mu04*mu04;
95  double mu40_2 = mu40*mu40;
96  double mu21_3 = mu21*mu21_2;
97  double mu12_3 = mu12_2*mu12;
98  double mu12_4 = mu12_3*mu12;
99  double mu21_4 = mu21_2*mu21_2;
100 
101  //double kappa = mu30_2+mu03_2-3*mu21_2+6*mu21*mu03; //Used in I8 calculation but simplified with MAPLE and found it to be wrong
102  double zeta = mu20-mu02;
103  double zeta_2 = zeta * zeta;
104  double omicron = (mu03_2+3*mu03*mu21+mu30*(mu30+3*mu12));
105  double omega = mu50+2*mu32+mu14;
106  double nu = mu05+2*mu23+mu41;
107  double ro = mu50-2*mu32-3*mu14;
108  double gamma = mu05-2*mu23-3*mu41;
109 
110  double delta = mu50-10*mu32+5*mu14;
111  double phi = mu05-10*mu23+5*mu41;
112  double omega_2 = omega*omega;
113  double nu_2 = nu*nu;
114  double ro_2 = ro*ro;
115  double gamma_2 = gamma*gamma;
116  double delta_2 = delta*delta;
117  double phi_2 = phi*phi;
118 
119  I_val[1]=-mu20*mu02+mu11_2;
120  I_val[2]=zeta_2+4*mu11_2;
121  I_val[3]=(mu30-3*mu12)*(mu30-3*mu12)+(mu03-3*mu21)*(mu03-3*mu21);
122  I_val[4]=(mu30+mu12)*(mu30+mu12)+(mu21+mu03)*(mu21+mu03);
123  I_val[5]=-mu30_2*mu03_2+(-4*mu12_3+6*mu21*mu12*mu03)*mu30-4*mu21_3*mu03+3*mu21_2*mu12_2;
124  I_val[6]=3*mu12_4+2*mu30*mu12_3+(3*mu30_2-6*mu03*mu21)*mu12_2-6*mu30*mu21*(mu21+mu03)*mu12+2*mu30_2*mu03_2+2*mu21_3*mu03+3*mu21_2*mu03_2+3*mu21_4;
125  I_val[7]=(3*mu21+2*mu03)*mu12_3+3*mu30*(mu03+2*mu21)*mu12_2-3*mu21*(mu30+mu03+mu21)*(-mu30+mu03+mu21)*mu12+mu30*(-mu30_2*mu03-2*mu21_3-3*mu03*mu21_2+mu03_3);
126  //I_val[8]=3*mu21_4-3*mu21_3*mu03+(3*mu03_2+kappa-6*mu12_2)*mu21_2-mu03*(-15*mu12_2+kappa)*mu21-(-3*mu12_2*mu30+(2*kappa-3*mu03_2)*mu12+kappa*mu30)*mu12;
127  I_val[8] = 3*mu03*mu21_3-2*mu03_2*mu21_2+mu21_2*mu30_2+3*mu12_2*mu03*mu21-mu03*mu21*mu30_2-mu03_3*mu21+3*mu12_3*mu30-2*mu12_2*mu30_2+mu12_2*mu03_2-mu12*mu30_3-mu12*mu30*mu03_2+3*mu12*mu30*mu21_2-6*mu12*mu30*mu03*mu21;
128  I_val[9]=omicron*omicron;
129 
130  I_val[10]=mu40*mu04-4*mu31*mu13+3*mu22_2;
131  I_val[11]=3*mu13_2+2*mu31*mu13+(-3*mu40-3*mu04)*mu22-2*mu40*mu04+3*mu31_2;
132  I_val[12]=3*mu04_2+(2*mu40+12*mu22)*mu04+3*mu40_2+12*mu40*mu22+16*mu31*mu13;
133  I_val[13]=omega_2+nu_2;
134  I_val[14]=ro_2+gamma_2;
135  I_val[15]=delta_2+phi_2;
136 
137  double a;
139  a = momentCentered.get(2,0)+momentCentered.get(0,2);
140  else
141  a = getObject().get(0,0);
142 
143  c[1]=momentCentered.get(2,0)-momentCentered.get(0,2);
144  s[1]=2*momentCentered.get(1,1);
145  c[2]=momentCentered.get(0,3)-3*momentCentered.get(2,1);
146  s[2]=momentCentered.get(3,0)-3*momentCentered.get(1,2);
147  c[3]=c[1]*c[1]-s[1]*s[1];
148  s[3]=2*s[1]*c[1];
149 
150  II[1]=c[1]*c[1]+s[1]*s[1];
151  II[2]=c[2]*c[2]+s[2]*s[2];
152  II[3]=momentCentered.get(2,0)+momentCentered.get(0,2);
153 
154  K=(II[1]*(II[3]*sqrt(std::abs(II[3]))))/sqrt(std::abs(a));
155 
156  /*
157  * Intermediate quantities required for calculation of normalized version of Sx and Sy
158  * The pij doubles below are the respective centered moment values mu_ij scaled by mu20 + mu02
159  */
160  double p20 = momentCentered.get(2,0)/II[3]; // II[3] is the normalization factor for the 2nd order moments
161  double p11 = momentCentered.get(1,1)/II[3];
162  double p02 = momentCentered.get(0,2)/II[3];
163 
164  double d = sqrt(std::abs(a))/(II[3]*sqrt(std::abs(II[3]))); // d is the normalization factor for 3rd order moments
165  double p30 = momentCentered.get(3,0)*d;
166  double p21 = momentCentered.get(2,1)*d;
167  double p12 = momentCentered.get(1,2)*d;
168  double p03 = momentCentered.get(0,3)*d;
169 
170  cn[1] = p20 - p02;
171  sn[1] = 2.0*p11;
172  sn[2] = p30 - 3.0*p12;
173  cn[2] = p03 - 3.0*p21;
174 
175  cn[3] = cn[1]*cn[1]-sn[1]*sn[1];
176  sn[3] = 2.0*sn[1]*cn[1];
177 
178  In1 = cn[1]*cn[1]+sn[1]*sn[1];
179 }
180 
187  if(getObject().getOrder()<5) throw vpException(vpException::notInitialized,"Order is not high enough for vpMomentCInvariant. Specify at least order 5.");
188  bool found_moment_centered;
189  const vpMomentCentered& momentCentered = (static_cast<const vpMomentCentered&>(getMoments().get("vpMomentCentered",found_moment_centered)));
190 
191  if(!found_moment_centered) throw vpException(vpException::notInitialized,"vpMomentCentered not found");
192 
193  computeI(momentCentered,I);
194  double II3_2 = II[3]*II[3];
195  double II3_3 = II3_2*II[3];
196 
197  double a;
198  if(getObject().getType()==vpMomentObject::DISCRETE)
199  a = momentCentered.get(2,0)+momentCentered.get(0,2);
200  else
201  a = getObject().get(0,0);
202 
203  values[0] = I[1]/I[2];
204  values[1] = I[3]/I[4];
205 
206  values[2] = I[5]/I[6];
207 
208  values[3] = I[7]/I[6];
209 
210  values[4] = I[8]/I[6];
211 
212  values[5] = I[9]/I[6];
213 
214  values[6] = I[11]/I[10];
215 
216  values[7] = I[12]/I[10];
217 
218  values[8] = I[13]/I[15];
219 
220  values[9] = I[14]/I[15];
221 
222  if (flg_sxsynormalization_)
223  calcSxSyNormalized(values[10], values[11]);
224  else
225  calcSxSy(values[10], values[11]);
226 
227  values[12] = II[1]/(II3_2); // Px
228  values[13] = a*II[2]/(II3_3); // Py
229 }
230 
234 void vpMomentCInvariant::calcSxSy(double& sx, double& sy) const{
235  sx = (c[2]*c[3]+s[2]*s[3])/K;
236  sy = (s[2]*c[3]-c[2]*s[3])/K;
237 }
238 
243 void vpMomentCInvariant::calcSxSyNormalized(double& sx, double& sy) const{
244  sx = (cn[2]*cn[3] + sn[2]*sn[3]) / In1;
245  sy = (sn[2]*cn[3] - cn[2]*sn[3]) / In1;
246 }
247 
252 void vpMomentCInvariant::printI(unsigned int index){
253  std::cout << "I("<< index << ")=" << I[index] << std::endl;
254 }
255 
261 void vpMomentCInvariant::printInvariants(std::ostream& os) const{
262  for (unsigned int i = 1; i < I.size(); ++i){ // i = 1 since vector I has been indexed from 1 in vpMomentCinvariant
263  os << "I[" << i << "]=" << I[i] << std::endl;
264  }
265  os << std::endl;
266 
267 }
268 
272 VISP_EXPORT std::ostream& operator<<(std::ostream & os, const vpMomentCInvariant& c){
273  for(unsigned int i = 0;i<c.values.size();i++){
274  os << c.values[i] << "," << std::endl;
275  }
276  return os;
277 }
278 
void printInvariants(std::ostream &os) const
error that can be emited by ViSP classes.
Definition: vpException.h:76
const std::vector< double > & get() const
const vpMoment & get(const char *type, bool &found) const
vpMomentCInvariant(bool flg_sxsynormalization=false)
This class defines the double-indexed centered moment descriptor .
double get(unsigned int i, unsigned int j) const
friend VISP_EXPORT std::ostream & operator<<(std::ostream &os, const vpMomentCInvariant &v)
vpObjectType getType() const
vpMomentDatabase & getMoments() const
Definition: vpMoment.h:119
const vpMomentObject & getObject() const
Definition: vpMoment.h:121
std::vector< double > values
Definition: vpMoment.h:114
void printI(unsigned int index)