Visual Servoing Platform  version 3.0.0
vpMeEllipse.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Moving edges.
32  *
33  * Authors:
34  * Eric Marchand
35  *
36  *****************************************************************************/
37 
38 
39 
40 #include <visp3/me/vpMeEllipse.h>
41 
42 #include <visp3/me/vpMe.h>
43 #include <visp3/core/vpRobust.h>
44 #include <visp3/core/vpException.h>
45 #include <visp3/core/vpImagePoint.h>
46 #include <visp3/core/vpDebug.h>
47 
48 #include <cmath> // std::fabs
49 #include <limits> // numeric_limits
50 #include <vector>
51 
52 void computeTheta(double &theta, vpColVector &K, vpImagePoint iP);
53 
61 void
62 computeTheta(double &theta, vpColVector &K, vpImagePoint iP)
63 {
64  double i = iP.get_i();
65  double j = iP.get_j();
66 
67  double A = 2*i+2*K[1]*j + 2*K[2] ;
68  double B = 2*K[0]*j + 2*K[1]*i + 2*K[3];
69 
70  theta = atan2(A,B) ; //Angle between the tangente and the i axis.
71 
72  while (theta > M_PI) { theta -= M_PI ; }
73  while (theta < 0) { theta += M_PI ; }
74 }
75 
76 
81  : K(), iPc(), a(0.), b(0.), e(0.), iP1(), iP2(), alpha1(0), alpha2(2*M_PI),
82  ce(0.), se(0.), angle(), m00(0.), mu11(0.), mu20(0.), mu02(0.),
83  m10(0.), m01(0.), m11(0.), m02(0.), m20(0.),
84  thresholdWeight(0.2), expecteddensity(0.)
85 {
86  // redimensionnement du vecteur de parametre
87  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
88 
89  K.resize(5) ;
90 
91  //j1 = j2 = i1 = i2 = 0 ;
92  iP1.set_i(0);
93  iP1.set_j(0);
94  iP2.set_i(0);
95  iP2.set_j(0);
96 }
97 
102  : vpMeTracker(meellipse), K(), iPc(), a(0.), b(0.), e(0.), iP1(), iP2(), alpha1(0), alpha2(2*M_PI),
103  ce(0.), se(0.), angle(), m00(0.), mu11(0.), mu20(0.), mu02(0.),
104  m10(0.), m01(0.), m11(0.), m02(0.), m20(0.),
105  thresholdWeight(0.2), expecteddensity(0.)
106 {
107  K = meellipse.K;
108  iPc = meellipse.iPc;
109  a = meellipse.a;
110  b = meellipse.b;
111  e = meellipse.e;
112 
113  iP1 = meellipse.iP1;
114  iP2 = meellipse.iP2;
115  alpha1 = meellipse.alpha1;
116  alpha2 = meellipse.alpha2;
117  ce = meellipse.ce;
118  se = meellipse.se;
119 
120  angle = meellipse.angle;
121 
122  m00 = meellipse.m00;
123  mu11 = meellipse.mu11;
124  mu20 = meellipse.mu20;
125  mu02 = meellipse.mu02;
126  m10 = meellipse.m10;
127  m01 = meellipse.m01;
128  m11 = meellipse.m11;
129  m02 = meellipse.m02;
130  m20 = meellipse.m20;
131  thresholdWeight = meellipse.thresholdWeight;
132 
133  expecteddensity = meellipse.expecteddensity;
134 }
135 
140 {
141  list.clear();
142  angle.clear();
143 }
144 
145 
156 void
157 vpMeEllipse::sample(const vpImage<unsigned char> & I)
158 {
159  if (!me) {
161  "Moving edges on ellipse tracking not initialized")) ;
162  }
163 
164  int height = (int)I.getHeight() ;
165  int width = (int)I.getWidth() ;
166 
167  //if (me->getSampleStep()==0)
168  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
169  {
170  std::cout << "In vpMeEllipse::sample: " ;
171  std::cout << "function called with sample step = 0" ;
172  //return fatalError ;
173  }
174 
175  double j, i;//, j11, i11;
176  vpImagePoint iP11;
177  j = i = 0.0 ;
178 
179  double incr = vpMath::rad(me->getSampleStep()) ; // angle increment en degree
180  vpColor col = vpColor::red ;
181  getParameters() ;
182 
183  // Delete old list
184  list.clear();
185 
186  angle.clear();
187 
188  // sample positions
189  double k = alpha1 ;
190  while (k<alpha2)
191  {
192 // j = a *cos(k) ; // equation of an ellipse
193 // i = b *sin(k) ; // equation of an ellipse
194 
195  j = a *sin(k) ; // equation of an ellipse
196  i = b *cos(k) ; // equation of an ellipse
197 
198  // (i,j) are the coordinates on the origin centered ellipse ;
199  // a rotation by "e" and a translation by (xci,jc) are done
200  // to get the coordinates of the point on the shifted ellipse
201 // iP11.set_j( iPc.get_j() + ce *j - se *i );
202 // iP11.set_i( iPc.get_i() -( se *j + ce *i) );
203 
204  iP11.set_j( iPc.get_j() + ce *j + se *i );
205  iP11.set_i( iPc.get_i() - se *j + ce *i );
206 
207  vpDisplay::displayCross(I, iP11, 5, col) ;
208 
209  double theta ;
210  computeTheta(theta, K, iP11) ;
211 
212  // If point is in the image, add to the sample list
213  if(!outOfImage(vpMath::round(iP11.get_i()), vpMath::round(iP11.get_j()), 0, height, width))
214  {
215  vpMeSite pix ;
216  pix.init((int)iP11.get_i(), (int)iP11.get_j(), theta) ;
219 
220  if(vpDEBUG_ENABLE(3))
221  {
223  }
224  list.push_back(pix);
225  angle.push_back(k);
226  }
227  k += incr ;
228 
229  }
231 }
232 
233 
248 void
249 vpMeEllipse::reSample(const vpImage<unsigned char> &I)
250 {
251  if (!me) {
253  "Moving edges on ellipse tracking not initialized")) ;
254  }
255 
256  unsigned int n = numberOfSignal() ;
258  if ((double)n<0.9*expecteddensity){
259  sample(I) ;
260  }
261 }
262 
263 
270 void
271 vpMeEllipse::getParameters()
272 {
273  double k[6] ;
274  for (unsigned int i=0 ; i < 5 ; i++)
275  k[i+1] = K[i] ;
276  k[0] = 1 ;
277 
278  double d = k[2]*k[2] - k[0]*k[1];
279 
280  iPc.set_i( (k[1] * k[3] - k[2] * k[4]) / d );
281  iPc.set_j( (k[0] * k[4] - k[2] * k[3]) / d );
282 
283  double sq = sqrt(vpMath::sqr(k[1]-k[0]) + 4.0*vpMath::sqr(k[2])) ;
284 
285  if (std::fabs(k[2]) <= std::numeric_limits<double>::epsilon()) {
286  e = 0;
287  }
288  else {
289  e = (k[1] - k[0] + sq) / (2.0*k[2]);
290  e = (-1/e) ;
291  }
292 
293  e = atan(e) ;
294 
295  if(e < 0.0) e += M_PI ;
296 
297  ce = cos(e) ;
298  se = sin(e) ;
299 
300  double num = 2.0*(k[0]*iPc.get_i()*iPc.get_i() + 2.0*k[2]*iPc.get_j()*iPc.get_i() + k[1]*iPc.get_j()*iPc.get_j() - k[5]) ;
301  double a2 = num / (k[0] + k[1] + sq ) ;
302  double b2 = num / (k[0] + k[1] - sq ) ;
303 
304  a = sqrt( a2 ) ;
305  b = sqrt( b2 ) ;
306 }
307 
311 void
313 {
314  std::cout << "K" << std::endl ;
315  std::cout << K.t() ;
316  std::cout << iPc << std::endl ;
317 }
318 
328 void
329 vpMeEllipse::computeAngle(vpImagePoint pt1, vpImagePoint pt2)
330 {
331  getParameters() ;
332  double j1, i1, j11, i11;
333  j1 = i1 = 0.0 ;
334 
335  int number_of_points = 2000 ;
336  double incr = 2 * M_PI / number_of_points ; // angle increment
337 
338  double dmin1 = 1e6 ;
339  double dmin2 = 1e6 ;
340 
341  double k = 0 ;
342  while(k < 2*M_PI) {
343 
344 // j1 = a *cos(k) ; // equation of an ellipse
345 // i1 = b *sin(k) ; // equation of an ellipse
346 
347  j1 = a *sin(k) ; // equation of an ellipse
348  i1 = b *cos(k) ; // equation of an ellipse
349 
350  // (i1,j1) are the coordinates on the origin centered ellipse ;
351  // a rotation by "e" and a translation by (xci,jc) are done
352  // to get the coordinates of the point on the shifted ellipse
353 // j11 = iPc.get_j() + ce *j1 - se *i1 ;
354 // i11 = iPc.get_i() -( se *j1 + ce *i1) ;
355 
356  j11 = iPc.get_j() + ce *j1 + se *i1 ;
357  i11 = iPc.get_i() - se *j1 + ce *i1 ;
358 
359  double d = vpMath::sqr(pt1.get_i()-i11) + vpMath::sqr(pt1.get_j()-j11) ;
360  if (d < dmin1)
361  {
362  dmin1 = d ;
363  alpha1 = k ;
364  }
365  d = vpMath::sqr(pt2.get_i()-i11) + vpMath::sqr(pt2.get_j()-j11) ;
366  if (d < dmin2)
367  {
368  dmin2 = d ;
369  alpha2 = k ;
370  }
371  k += incr ;
372  }
373 
374  if (alpha2 < alpha1)
375  alpha2 += 2 * M_PI;
376  //else if (alpha2 == alpha1)
377  else if (std::fabs(alpha2 - alpha1) < std::fabs(alpha1) * std::numeric_limits<double>::epsilon())
378  alpha2 += 2 * M_PI;
379 }
380 
381 
387 void
388 vpMeEllipse::updateTheta()
389 {
390  vpMeSite p_me;
391  double theta;
392  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
393  p_me = *it;
394  vpImagePoint iP;
395  iP.set_i(p_me.ifloat);
396  iP.set_j(p_me.jfloat);
397  computeTheta(theta, K, iP) ;
398  p_me.alpha = theta ;
399  *it = p_me;
400  }
401 }
402 
406 void
407 vpMeEllipse::suppressPoints()
408 {
409  // Loop through list of sites to track
410  std::list<vpMeSite>::iterator itList = list.begin();
411  for(std::list<double>::iterator it=angle.begin(); it!=angle.end(); ){
412  vpMeSite s = *itList;//current reference pixel
414  {
415  itList = list.erase(itList) ;
416  it = angle.erase(it);
417  }
418  else
419  {
420  ++itList;
421  ++it;
422  }
423  }
424 }
425 
426 
436 void
437 vpMeEllipse::seekExtremities(const vpImage<unsigned char> &I)
438 {
439  if (!me) {
441  "Moving edges on ellipse tracking not initialized")) ;
442  }
443 
444  int rows = (int)I.getHeight() ;
445  int cols = (int)I.getWidth() ;
446 
447  vpImagePoint ip;
448 
449  unsigned int memory_range = me->getRange() ;
450  me->setRange(2);
451 
452  double memory_mu1 = me->getMu1();
453  me->setMu1(0.5);
454 
455  double memory_mu2 = me->getMu2();
456  me->setMu2(0.5);
457 
458  double incr = vpMath::rad(2.0) ;
459 
460  if (alpha2-alpha1 < 2*M_PI-vpMath::rad(6.0))
461  {
462  vpMeSite P;
463  double k = alpha1;
464  double i1,j1;
465 
466  for (unsigned int i=0 ; i < 3 ; i++)
467  {
468  k -= incr;
469  //while ( k < -M_PI ) { k+=2*M_PI; }
470 
471  i1 = b *cos(k) ; // equation of an ellipse
472  j1 = a *sin(k) ; // equation of an ellipse
473  P.ifloat = iPc.get_i() - se *j1 + ce *i1 ; P.i = (int)P.ifloat ;
474  P.jfloat = iPc.get_j() + ce *j1 + se *i1 ; P.j = (int)P.jfloat ;
475 
476  if(!outOfImage(P.i, P.j, 5, rows, cols))
477  {
478  P.track(I,me,false) ;
479 
481  {
482  list.push_back(P);
483  angle.push_back(k);
484  if (vpDEBUG_ENABLE(3)) {
485  ip.set_i( P.i );
486  ip.set_j( P.j );
487 
489  }
490  }
491  else {
492  if (vpDEBUG_ENABLE(3)) {
493  ip.set_i( P.i );
494  ip.set_j( P.j );
496  }
497  }
498  }
499  }
500 
501  k = alpha2;
502 
503  for (unsigned int i=0 ; i < 3 ; i++)
504  {
505  k += incr;
506  //while ( k > M_PI ) { k-=2*M_PI; }
507 
508  i1 = b *cos(k) ; // equation of an ellipse
509  j1 = a *sin(k) ; // equation of an ellipse
510  P.ifloat = iPc.get_i() - se *j1 + ce *i1 ; P.i = (int)P.ifloat ;
511  P.jfloat = iPc.get_j() + ce *j1 + se *i1 ; P.j = (int)P.jfloat ;
512 
513  if(!outOfImage(P.i, P.j, 5, rows, cols))
514  {
515  P.track(I,me,false) ;
516 
518  {
519  list.push_back(P);
520  angle.push_back(k);
521  if (vpDEBUG_ENABLE(3)) {
522  ip.set_i( P.i );
523  ip.set_j( P.j );
524 
526  }
527  }
528  else {
529  if (vpDEBUG_ENABLE(3)) {
530  ip.set_i( P.i );
531  ip.set_j( P.j );
533  }
534  }
535  }
536  }
537  }
538 
539  suppressPoints() ;
540 
541  me->setRange(memory_range);
542  me->setMu1(memory_mu1);
543  me->setMu2(memory_mu2);
544 }
545 
546 
550 void
551 vpMeEllipse::setExtremities()
552 {
553  double alphamin = +1e6;
554  double alphamax = -1e6;
555  double imin = 0;
556  double jmin = 0;
557  double imax = 0;
558  double jmax = 0;
559 
560  // Loop through list of sites to track
561  std::list<double>::const_iterator itAngle = angle.begin();
562 
563  for(std::list<vpMeSite>::const_iterator itList=list.begin(); itList!=list.end(); ++itList){
564  vpMeSite s = *itList;//current reference pixel
565  double alpha = *itAngle;
566  if (alpha < alphamin)
567  {
568  alphamin = alpha;
569  imin = s.ifloat ;
570  jmin = s.jfloat ;
571  }
572 
573  if (alpha > alphamax)
574  {
575  alphamax = alpha;
576  imax = s.ifloat ;
577  jmax = s.jfloat ;
578  }
579  ++itAngle;
580  }
581 
582  alpha1 = alphamin;
583  alpha2 = alphamax;
584  iP1.set_ij(imin,jmin);
585  iP2.set_ij(imax,jmax);
586 }
587 
588 
594 void
595 vpMeEllipse::leastSquare()
596 {
597  // Construction du systeme Ax=b
598  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
599  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
600  unsigned int i ;
601 
602  vpMeSite p_me ;
603 
604  unsigned int iter =0 ;
606  vpRobust r(numberOfSignal()) ;
607  r.setThreshold(2);
608  r.setIteration(0) ;
610  D.eye() ;
611  vpMatrix DA, DAmemory ;
612  vpColVector DAx ;
614  w =1 ;
615  unsigned int nos_1 = numberOfSignal() ;
616 
617  if (list.size() < 3)
618  {
620  "Not enought moving edges to track the ellipse")) ;
621  }
622 
623  vpMatrix A(numberOfSignal(),5) ;
624  vpColVector x(5);
625 
626  unsigned int k =0 ;
627  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
628  p_me = *it;
629  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
630  {
631  A[k][0] = vpMath::sqr(p_me.jfloat) ;
632  A[k][1] = 2 * p_me.ifloat * p_me.jfloat ;
633  A[k][2] = 2 * p_me.ifloat ;
634  A[k][3] = 2 * p_me.jfloat ;
635  A[k][4] = 1 ;
636 
637  b_[k] = - vpMath::sqr(p_me.ifloat) ;
638  k++ ;
639  }
640  }
641 
642  while (iter < 4 )
643  {
644  DA = D*A ;
645  vpMatrix DAp ;
646 
647  x = DA.pseudoInverse(1e-26) *D*b_ ;
648 
649  vpColVector residu(nos_1);
650  residu = b_ - A*x;
651  r.setIteration(iter) ;
652  r.MEstimator(vpRobust::TUKEY,residu,w) ;
653 
654  k = 0;
655  for (i=0 ; i < nos_1 ; i++)
656  {
657  D[k][k] =w[k] ;
658  k++;
659  }
660  iter++;
661  }
662 
663  k =0 ;
664  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
665  p_me = *it;
666  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
667  {
668  if (w[k] < thresholdWeight)
669  {
671 
672  *it = p_me;
673  }
674  k++ ;
675  }
676  }
677  for(i = 0; i < 5; i ++)
678  K[i] = x[i];
679 
680  getParameters() ;
681 }
682 
683 
693 void
695 {
697 }
698 
699 
708 void
710 {
711  const unsigned int n=5 ;
712  vpImagePoint iP[n];
713 
714  for (unsigned int k =0 ; k < n ; k++)
715  {
716  std::cout << "Click points "<< k+1 <<"/" << n ;
717  std::cout << " on the ellipse in the trigonometric order" <<std::endl ;
718  vpDisplay::getClick(I, iP[k], true);
720  vpDisplay::flush(I);
721  std::cout << iP[k] << std::endl;
722  }
723 
724  iP1 = iP[0];
725  iP2 = iP[n-1];
726 
727  initTracking(I, n, iP) ;
728 }
729 
730 
742 void
743 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const unsigned int n,
744  vpImagePoint *iP)
745 {
746  vpMatrix A(n,5) ;
747  vpColVector b_(n) ;
748  vpColVector x(5) ;
749 
750  // Construction du systeme Ax=b
751  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
752  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
753 
754  for (unsigned int k =0 ; k < n ; k++)
755  {
756  A[k][0] = vpMath::sqr(iP[k].get_j()) ;
757  A[k][1] = 2* iP[k].get_i() * iP[k].get_j() ;
758  A[k][2] = 2* iP[k].get_i() ;
759  A[k][3] = 2* iP[k].get_j() ;
760  A[k][4] = 1 ;
761 
762  b_[k] = - vpMath::sqr(iP[k].get_i()) ;
763  }
764 
765  K = A.pseudoInverse(1e-26)*b_ ;
766 
767  iP1 = iP[0];
768  iP2 = iP[n-1];
769 
770  getParameters() ;
771 
772  computeAngle(iP1, iP2) ;
773 
775 
776  display(I, vpColor::green) ;
777  sample(I) ;
778 
780 
781  track(I) ;
782 
784  vpDisplay::flush(I) ;
785 }
786 
797 void
798 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const std::vector<vpImagePoint> &iP)
799 {
800  unsigned int n = (unsigned int)(iP.size());
801  vpMatrix A(n,5) ;
802  vpColVector b_(n) ;
803  vpColVector x(5) ;
804 
805  // Construction du systeme Ax=b
806  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
807  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
808 
809  for (unsigned int k =0 ; k < n ; k++)
810  {
811  A[k][0] = vpMath::sqr(iP[k].get_j()) ;
812  A[k][1] = 2* iP[k].get_i() * iP[k].get_j() ;
813  A[k][2] = 2* iP[k].get_i() ;
814  A[k][3] = 2* iP[k].get_j() ;
815  A[k][4] = 1 ;
816 
817  b_[k] = - vpMath::sqr(iP[k].get_i()) ;
818  }
819 
820  K = A.pseudoInverse(1e-26)*b_ ;
821 
822  iP1 = iP[0];
823  iP2 = iP[n-1];
824 
825  getParameters() ;
826 
827  computeAngle(iP1, iP2) ;
828 
830 
831  display(I, vpColor::green) ;
832  sample(I) ;
833 
835 
836  track(I) ;
837 
839  vpDisplay::flush(I) ;
840 }
841 
842 void
843 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const vpImagePoint &ic, double a_p, double b_p, double e_p,
844  double low_alpha, double high_alpha)
845 {
846  iPc = ic;
847  a = a_p;
848  b = b_p;
849  e = e_p;
850  alpha1 = low_alpha;
851  alpha2 = high_alpha;
852 
853  if (alpha2 <alpha1)
854  alpha2 += 2 * M_PI;
855 
856  ce = cos(e);
857  se = sin(e);
858 
859  display(I, vpColor::green) ;
860  sample(I) ;
861 
863 
864  track(I) ;
865 
867  vpDisplay::flush(I) ;
868 }
869 
875 void
877 {
878  vpMeTracker::track(I) ;
879 
880  // Estimation des parametres de la droite aux moindres carre
881  suppressPoints() ;
882  setExtremities() ;
883 
884  leastSquare() ;
885  seekExtremities(I) ;
886  setExtremities() ;
887  leastSquare() ;
888 
889  // suppression des points rejetes par la regression robuste
890  suppressPoints() ;
891  setExtremities() ;
892 
893  //reechantillonage si necessaire
894  reSample(I) ;
895 
896  // remet a jour l'angle delta pour chaque point de la liste
897 
898  updateTheta() ;
899 
900  computeMoments();
901 
902  // Remise a jour de delta dans la liste de site me
903  if (vpDEBUG_ENABLE(2))
904  {
905  display(I,vpColor::red) ;
907  vpDisplay::flush(I) ;
908  }
909 }
910 
916 void
917 vpMeEllipse::computeMoments()
918 {
919  double tane = tan(-1/e);
920  m00 = M_PI*a*b;
921  m10 = m00*iPc.get_i();
922  m01 = m00*iPc.get_j();
923  m20 = m00*(a*a+b*b*tane*tane)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_i();
924  m02 = m00*(a*a*tane*tane+b*b)/(4*(1+tane*tane))+m00*iPc.get_j()*iPc.get_j();
925  m11 = m00*tane*(a*a-b*b)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_j();
926  mu11 = m11 - iPc.get_j()*m10;
927  mu02 = m02 - iPc.get_j()*m01;
928  mu20 = m20 - iPc.get_i()*m10;
929 }
930 
931 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
932 
936 void
937 vpMeEllipse::computeAngle(int ip1, int jp1, double &_alpha1,
938  int ip2, int jp2, double &_alpha2)
939 {
940  getParameters() ;
941  double j1, i1, j11, i11;
942  j1 = i1 = 0.0 ;
943 
944  int number_of_points = 2000 ;
945  double incr = 2 * M_PI / number_of_points ; // angle increment
946 
947  double dmin1 = 1e6 ;
948  double dmin2 = 1e6 ;
949 
950  double k = -M_PI ;
951  while(k < M_PI) {
952 
953  j1 = a *cos(k) ; // equation of an ellipse
954  i1 = b *sin(k) ; // equation of an ellipse
955 
956  // (i1,j1) are the coordinates on the origin centered ellipse ;
957  // a rotation by "e" and a translation by (xci,jc) are done
958  // to get the coordinates of the point on the shifted ellipse
959  j11 = iPc.get_j() + ce *j1 - se *i1 ;
960  i11 = iPc.get_i() -( se *j1 + ce *i1) ;
961 
962  double d = vpMath::sqr(ip1-i11) + vpMath::sqr(jp1-j11) ;
963  if (d < dmin1)
964  {
965  dmin1 = d ;
966  alpha1 = k ;
967  _alpha1 = k ;
968  }
969  d = vpMath::sqr(ip2-i11) + vpMath::sqr(jp2-j11) ;
970  if (d < dmin2)
971  {
972  dmin2 = d ;
973  alpha2 = k ;
974  _alpha2 = k ;
975  }
976  k += incr ;
977  }
978 
979  if (alpha2 <alpha1) alpha2 += 2*M_PI ;
980 
981  vpCDEBUG(1) << "end vpMeEllipse::computeAngle(..)" << alpha1 << " " << alpha2 << std::endl ;
982 
983 }
984 
985 
989 void
990 vpMeEllipse::computeAngle(int ip1, int jp1, int ip2, int jp2)
991 {
992 
993  double a1, a2 ;
994  computeAngle(ip1,jp1,a1, ip2, jp2,a2) ;
995 }
996 
997 
998 void
999 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const unsigned int n,
1000  unsigned *i, unsigned *j)
1001 {
1002  vpCDEBUG(1) <<" begin vpMeEllipse::initTracking()"<<std::endl ;
1003 
1004  //if (circle==false)
1005  if (1)
1006  {
1007  vpMatrix A(n,5) ;
1008  vpColVector b_(n) ;
1009  vpColVector x(5) ;
1010 
1011  // Construction du systeme Ax=b
1013  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
1014 
1015  for (unsigned int k =0 ; k < n ; k++)
1016  {
1017  A[k][0] = vpMath::sqr(j[k]) ;
1018  A[k][1] = 2* i[k] * j[k] ;
1019  A[k][2] = 2* i[k] ;
1020  A[k][3] = 2* j[k] ;
1021  A[k][4] = 1 ;
1022 
1023  b_[k] = - vpMath::sqr(i[k]) ;
1024  }
1025 
1026  K = A.pseudoInverse(1e-26)*b_ ;
1027  std::cout << K << std::endl;
1028  }
1029  else
1030  {
1031  vpMatrix A(n,3) ;
1032  vpColVector b_(n) ;
1033  vpColVector x(3) ;
1034 
1035  vpColVector Kc(3) ;
1036  for (unsigned int k =0 ; k < n ; k++)
1037  {
1038  A[k][0] = 2* i[k] ;
1039  A[k][1] = 2* j[k] ;
1040 
1041  A[k][2] = 1 ;
1042  b_[k] = - vpMath::sqr(i[k]) - vpMath::sqr(j[k]) ;
1043  }
1044 
1045  Kc = A.pseudoInverse(1e-26)*b_ ;
1046  K[0] = 1 ;
1047  K[1] = 0 ;
1048  K[2] = Kc[0] ;
1049  K[3] = Kc[1] ;
1050  K[4] = Kc[2] ;
1051 
1052  std::cout << K << std::endl;
1053  }
1054  iP1.set_i( i[0] );
1055  iP1.set_j( j[0] );
1056  iP2.set_i( i[n-1] );
1057  iP2.set_j( j[n-1] );
1058 
1059  getParameters() ;
1060  computeAngle(iP1, iP2) ;
1061  display(I, vpColor::green) ;
1062 
1063  sample(I) ;
1064 
1065  // 2. On appelle ce qui n'est pas specifique
1066  {
1068  }
1069 
1070  try{
1071  track(I) ;
1072  }
1073  catch(...)
1074  {
1075  vpERROR_TRACE("Error caught") ;
1076  throw ;
1077  }
1079  vpDisplay::flush(I) ;
1080 
1081 }
1082 #endif // Deprecated
1083 
1107  const double &A, const double &B, const double &E,
1108  const double & smallalpha, const double &highalpha,
1109  const vpColor &color, unsigned int thickness)
1110 {
1111  double j1, i1;
1112  vpImagePoint iP11;
1113  double j2, i2;
1114  vpImagePoint iP22;
1115  j1 = j2 = i1 = i2 = 0 ;
1116 
1117  double incr = vpMath::rad(2) ; // angle increment
1118 
1119  vpDisplay::displayCross(I,center,20, vpColor::red, thickness) ;
1120 
1121  double k = smallalpha ;
1122  while (k+incr<highalpha)
1123  {
1124  j1 = A *cos(k) ; // equation of an ellipse
1125  i1 = B *sin(k) ; // equation of an ellipse
1126 
1127  j2 = A *cos(k+incr) ; // equation of an ellipse
1128  i2 = B *sin(k+incr) ; // equation of an ellipse
1129 
1130  // (i1,j1) are the coordinates on the origin centered ellipse ;
1131  // a rotation by "e" and a translation by (xci,jc) are done
1132  // to get the coordinates of the point on the shifted ellipse
1133  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1134  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1135  // to get the coordinates of the point on the shifted ellipse
1136  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1137  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1138 
1139  vpDisplay::displayLine(I, iP11, iP22, color, thickness) ;
1140 
1141  k += incr ;
1142  }
1143 
1144  j1 = A *cos(smallalpha) ; // equation of an ellipse
1145  i1 = B *sin(smallalpha) ; // equation of an ellipse
1146 
1147  j2 = A *cos(highalpha) ; // equation of an ellipse
1148  i2 = B *sin(highalpha) ; // equation of an ellipse
1149 
1150  // (i1,j1) are the coordinates on the origin centered ellipse ;
1151  // a rotation by "e" and a translation by (xci,jc) are done
1152  // to get the coordinates of the point on the shifted ellipse
1153  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1154  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1155  // to get the coordinates of the point on the shifted ellipse
1156  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1157  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1158 
1159  vpDisplay::displayLine(I, center, iP11, vpColor::red, thickness) ;
1160  vpDisplay::displayLine(I, center, iP22, vpColor::blue, thickness) ;
1161 }
1162 
1186  const double &A, const double &B, const double &E,
1187  const double & smallalpha, const double &highalpha,
1188  const vpColor &color, unsigned int thickness)
1189 {
1190  double j1, i1;
1191  vpImagePoint iP11;
1192  double j2, i2;
1193  vpImagePoint iP22;
1194  j1 = j2 = i1 = i2 = 0 ;
1195 
1196  double incr = vpMath::rad(2) ; // angle increment
1197 
1198  vpDisplay::displayCross(I,center,20, vpColor::red, thickness) ;
1199 
1200  double k = smallalpha ;
1201  while (k+incr<highalpha)
1202  {
1203  j1 = A *cos(k) ; // equation of an ellipse
1204  i1 = B *sin(k) ; // equation of an ellipse
1205 
1206  j2 = A *cos(k+incr) ; // equation of an ellipse
1207  i2 = B *sin(k+incr) ; // equation of an ellipse
1208 
1209  // (i1,j1) are the coordinates on the origin centered ellipse ;
1210  // a rotation by "e" and a translation by (xci,jc) are done
1211  // to get the coordinates of the point on the shifted ellipse
1212  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1213  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1214  // to get the coordinates of the point on the shifted ellipse
1215  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1216  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1217 
1218  vpDisplay::displayLine(I, iP11, iP22, color, thickness) ;
1219 
1220  k += incr ;
1221  }
1222 
1223  j1 = A *cos(smallalpha) ; // equation of an ellipse
1224  i1 = B *sin(smallalpha) ; // equation of an ellipse
1225 
1226  j2 = A *cos(highalpha) ; // equation of an ellipse
1227  i2 = B *sin(highalpha) ; // equation of an ellipse
1228 
1229  // (i1,j1) are the coordinates on the origin centered ellipse ;
1230  // a rotation by "e" and a translation by (xci,jc) are done
1231  // to get the coordinates of the point on the shifted ellipse
1232  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1233  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1234  // to get the coordinates of the point on the shifted ellipse
1235  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1236  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1237 
1238  vpDisplay::displayLine(I, center, iP11, vpColor::red, thickness) ;
1239  vpDisplay::displayLine(I, center, iP22, vpColor::blue, thickness) ;
1240 }
double a
is the semiminor axis of the ellipse.
Definition: vpMeEllipse.h:255
unsigned int getRange() const
Definition: vpMe.h:225
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:92
double m01
Definition: vpMeEllipse.h:281
double expecteddensity
Expected number of me to track along the ellipse.
Definition: vpMeEllipse.h:287
double e
is the angle made by the major axis and the i axis of the image frame .
Definition: vpMeEllipse.h:259
void initTracking(const vpImage< unsigned char > &I)
double mu02
Definition: vpMeEllipse.h:279
void init()
Definition: vpMeSite.cpp:69
double get_i() const
Definition: vpImagePoint.h:190
unsigned int getWidth() const
Definition: vpImage.h:161
double jfloat
Definition: vpMeSite.h:96
#define vpDEBUG_ENABLE(level)
Definition: vpDebug.h:526
unsigned int numberOfSignal()
double getMu1() const
Definition: vpMe.h:167
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:72
double thresholdWeight
Threshold for the robust least square.
Definition: vpMeEllipse.h:285
#define vpERROR_TRACE
Definition: vpDebug.h:391
Class to define colors available for display functionnalities.
Definition: vpColor.h:121
int outOfImage(int i, int j, int half, int rows, int cols)
vpImagePoint iP1
The coordinates of the point corresponding to the smallest angle. More things about the are given a...
Definition: vpMeEllipse.h:263
double alpha
Definition: vpMeSite.h:100
int i
Definition: vpMeSite.h:94
error that can be emited by ViSP classes.
Definition: vpException.h:73
Class that tracks an ellipse moving edges.
Definition: vpMeEllipse.h:95
double mu20
Definition: vpMeEllipse.h:279
static const vpColor green
Definition: vpColor.h:166
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2233
static int round(const double x)
Definition: vpMath.h:248
double get_j() const
Definition: vpImagePoint.h:201
double b
is the semimajor axis of the ellipse.
Definition: vpMeEllipse.h:257
double se
Value of sin(e).
Definition: vpMeEllipse.h:273
void setMu1(const double &mu_1)
Definition: vpMe.h:160
static const vpColor red
Definition: vpColor.h:163
vpMeSiteState getState() const
Definition: vpMeSite.h:198
double ifloat
Definition: vpMeSite.h:96
virtual ~vpMeEllipse()
double m20
Definition: vpMeEllipse.h:283
void set_i(const double ii)
Definition: vpImagePoint.h:154
void track(const vpImage< unsigned char > &Im)
std::list< vpMeSite > list
Definition: vpMeTracker.h:73
vpImagePoint iP2
The coordinates of the point corresponding to the highest angle. More things about the are given at...
Definition: vpMeEllipse.h:265
vpImagePoint iPc
The coordinates of the ellipse center.
Definition: vpMeEllipse.h:253
double m11
Second order raw moments.
Definition: vpMeEllipse.h:283
double alpha1
The smallest angle.
Definition: vpMeEllipse.h:267
static double sqr(double x)
Definition: vpMath.h:110
void printParameters()
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void setDisplay(vpMeSiteDisplayType select)
Definition: vpMeSite.h:148
void display(const vpImage< unsigned char > &I, vpColor col)
#define vpCDEBUG(level)
Definition: vpDebug.h:502
void track(const vpImage< unsigned char > &I)
Track sampled pixels.
double mu11
Second order central moments.
Definition: vpMeEllipse.h:279
double m10
First order raw moments.
Definition: vpMeEllipse.h:281
Contains abstract elements for a Distance to Feature type feature.
Definition: vpMeTracker.h:64
vpColVector K
Definition: vpMeEllipse.h:251
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:185
double m00
Surface.
Definition: vpMeEllipse.h:277
static double rad(double deg)
Definition: vpMath.h:104
std::list< double > angle
Stores the value of the angle for each vpMeSite.
Definition: vpMeEllipse.h:275
void set_j(const double jj)
Definition: vpImagePoint.h:165
void setMu2(const double &mu_2)
Definition: vpMe.h:174
double getMu2() const
Definition: vpMe.h:181
int j
Definition: vpMeSite.h:94
double m02
Definition: vpMeEllipse.h:283
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
void track(const vpImage< unsigned char > &im, const vpMe *me, const bool test_contraste=true)
Definition: vpMeSite.cpp:377
vpMe * me
Moving edges initialisation parameters.
Definition: vpMeTracker.h:75
Contains an M-Estimator and various influence function.
Definition: vpRobust.h:59
void initTracking(const vpImage< unsigned char > &I)
unsigned int getHeight() const
Definition: vpImage.h:152
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1756
virtual bool getClick(bool blocking=true)=0
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
virtual void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)=0
double alpha2
The highest angle.
Definition: vpMeEllipse.h:269
void setRange(const unsigned int &r)
Definition: vpMe.h:218
double getSampleStep() const
Definition: vpMe.h:267
vpMeSite::vpMeSiteDisplayType selectDisplay
Definition: vpMeTracker.h:80
virtual void display(const vpImage< unsigned char > &I, vpColor col)=0
double ce
Value of cos(e).
Definition: vpMeEllipse.h:271
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:176
static const vpColor blue
Definition: vpColor.h:169