Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpMeEllipse.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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 
333  int number_of_points = 2000 ;
334  double incr = 2 * M_PI / number_of_points ; // angle increment
335 
336  double dmin1 = 1e6 ;
337  double dmin2 = 1e6 ;
338 
339  double k = 0 ;
340  while(k < 2*M_PI) {
341 
342 // j1 = a *cos(k) ; // equation of an ellipse
343 // i1 = b *sin(k) ; // equation of an ellipse
344 
345  double j1 = a *sin(k) ; // equation of an ellipse
346  double i1 = b *cos(k) ; // equation of an ellipse
347 
348  // (i1,j1) are the coordinates on the origin centered ellipse ;
349  // a rotation by "e" and a translation by (xci,jc) are done
350  // to get the coordinates of the point on the shifted ellipse
351 // j11 = iPc.get_j() + ce *j1 - se *i1 ;
352 // i11 = iPc.get_i() -( se *j1 + ce *i1) ;
353 
354  double j11 = iPc.get_j() + ce *j1 + se *i1 ;
355  double i11 = iPc.get_i() - se *j1 + ce *i1 ;
356 
357  double d = vpMath::sqr(pt1.get_i()-i11) + vpMath::sqr(pt1.get_j()-j11) ;
358  if (d < dmin1)
359  {
360  dmin1 = d ;
361  alpha1 = k ;
362  }
363  d = vpMath::sqr(pt2.get_i()-i11) + vpMath::sqr(pt2.get_j()-j11) ;
364  if (d < dmin2)
365  {
366  dmin2 = d ;
367  alpha2 = k ;
368  }
369  k += incr ;
370  }
371 
372  if (alpha2 < alpha1)
373  alpha2 += 2 * M_PI;
374  //else if (alpha2 == alpha1)
375  else if (std::fabs(alpha2 - alpha1) < std::fabs(alpha1) * std::numeric_limits<double>::epsilon())
376  alpha2 += 2 * M_PI;
377 }
378 
379 
385 void
386 vpMeEllipse::updateTheta()
387 {
388  vpMeSite p_me;
389  double theta;
390  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
391  p_me = *it;
392  vpImagePoint iP;
393  iP.set_i(p_me.ifloat);
394  iP.set_j(p_me.jfloat);
395  computeTheta(theta, K, iP) ;
396  p_me.alpha = theta ;
397  *it = p_me;
398  }
399 }
400 
404 void
405 vpMeEllipse::suppressPoints()
406 {
407  // Loop through list of sites to track
408  std::list<vpMeSite>::iterator itList = list.begin();
409  for(std::list<double>::iterator it=angle.begin(); it!=angle.end(); ){
410  vpMeSite s = *itList;//current reference pixel
412  {
413  itList = list.erase(itList) ;
414  it = angle.erase(it);
415  }
416  else
417  {
418  ++itList;
419  ++it;
420  }
421  }
422 }
423 
424 
434 void
435 vpMeEllipse::seekExtremities(const vpImage<unsigned char> &I)
436 {
437  if (!me) {
439  "Moving edges on ellipse tracking not initialized")) ;
440  }
441 
442  int rows = (int)I.getHeight() ;
443  int cols = (int)I.getWidth() ;
444 
445  vpImagePoint ip;
446 
447  unsigned int memory_range = me->getRange() ;
448  me->setRange(2);
449 
450  double memory_mu1 = me->getMu1();
451  me->setMu1(0.5);
452 
453  double memory_mu2 = me->getMu2();
454  me->setMu2(0.5);
455 
456  double incr = vpMath::rad(2.0) ;
457 
458  if (alpha2-alpha1 < 2*M_PI-vpMath::rad(6.0))
459  {
460  vpMeSite P;
461  double k = alpha1;
462  double i1,j1;
463 
464  for (unsigned int i=0 ; i < 3 ; i++)
465  {
466  k -= incr;
467  //while ( k < -M_PI ) { k+=2*M_PI; }
468 
469  i1 = b *cos(k) ; // equation of an ellipse
470  j1 = a *sin(k) ; // equation of an ellipse
471  P.ifloat = iPc.get_i() - se *j1 + ce *i1 ; P.i = (int)P.ifloat ;
472  P.jfloat = iPc.get_j() + ce *j1 + se *i1 ; P.j = (int)P.jfloat ;
473 
474  if(!outOfImage(P.i, P.j, 5, rows, cols))
475  {
476  P.track(I,me,false) ;
477 
479  {
480  list.push_back(P);
481  angle.push_back(k);
482  if (vpDEBUG_ENABLE(3)) {
483  ip.set_i( P.i );
484  ip.set_j( P.j );
485 
487  }
488  }
489  else {
490  if (vpDEBUG_ENABLE(3)) {
491  ip.set_i( P.i );
492  ip.set_j( P.j );
494  }
495  }
496  }
497  }
498 
499  k = alpha2;
500 
501  for (unsigned int i=0 ; i < 3 ; i++)
502  {
503  k += incr;
504  //while ( k > M_PI ) { k-=2*M_PI; }
505 
506  i1 = b *cos(k) ; // equation of an ellipse
507  j1 = a *sin(k) ; // equation of an ellipse
508  P.ifloat = iPc.get_i() - se *j1 + ce *i1 ; P.i = (int)P.ifloat ;
509  P.jfloat = iPc.get_j() + ce *j1 + se *i1 ; P.j = (int)P.jfloat ;
510 
511  if(!outOfImage(P.i, P.j, 5, rows, cols))
512  {
513  P.track(I,me,false) ;
514 
516  {
517  list.push_back(P);
518  angle.push_back(k);
519  if (vpDEBUG_ENABLE(3)) {
520  ip.set_i( P.i );
521  ip.set_j( P.j );
522 
524  }
525  }
526  else {
527  if (vpDEBUG_ENABLE(3)) {
528  ip.set_i( P.i );
529  ip.set_j( P.j );
531  }
532  }
533  }
534  }
535  }
536 
537  suppressPoints() ;
538 
539  me->setRange(memory_range);
540  me->setMu1(memory_mu1);
541  me->setMu2(memory_mu2);
542 }
543 
544 
548 void
549 vpMeEllipse::setExtremities()
550 {
551  double alphamin = +1e6;
552  double alphamax = -1e6;
553  double imin = 0;
554  double jmin = 0;
555  double imax = 0;
556  double jmax = 0;
557 
558  // Loop through list of sites to track
559  std::list<double>::const_iterator itAngle = angle.begin();
560 
561  for(std::list<vpMeSite>::const_iterator itList=list.begin(); itList!=list.end(); ++itList){
562  vpMeSite s = *itList;//current reference pixel
563  double alpha = *itAngle;
564  if (alpha < alphamin)
565  {
566  alphamin = alpha;
567  imin = s.ifloat ;
568  jmin = s.jfloat ;
569  }
570 
571  if (alpha > alphamax)
572  {
573  alphamax = alpha;
574  imax = s.ifloat ;
575  jmax = s.jfloat ;
576  }
577  ++itAngle;
578  }
579 
580  alpha1 = alphamin;
581  alpha2 = alphamax;
582  iP1.set_ij(imin,jmin);
583  iP2.set_ij(imax,jmax);
584 }
585 
586 
592 void
593 vpMeEllipse::leastSquare()
594 {
595  // Construction du systeme Ax=b
596  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
597  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
598  unsigned int i ;
599 
600  vpMeSite p_me ;
601 
602  unsigned int iter =0 ;
604  vpRobust r(numberOfSignal()) ;
605  r.setThreshold(2);
606  r.setIteration(0) ;
608  D.eye() ;
609  vpMatrix DA, DAmemory ;
610  vpColVector DAx ;
612  w =1 ;
613  unsigned int nos_1 = numberOfSignal() ;
614 
615  if (list.size() < 3)
616  {
618  "Not enought moving edges to track the ellipse")) ;
619  }
620 
621  vpMatrix A(numberOfSignal(),5) ;
622  vpColVector x(5);
623 
624  unsigned int k =0 ;
625  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
626  p_me = *it;
627  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
628  {
629  A[k][0] = vpMath::sqr(p_me.jfloat) ;
630  A[k][1] = 2 * p_me.ifloat * p_me.jfloat ;
631  A[k][2] = 2 * p_me.ifloat ;
632  A[k][3] = 2 * p_me.jfloat ;
633  A[k][4] = 1 ;
634 
635  b_[k] = - vpMath::sqr(p_me.ifloat) ;
636  k++ ;
637  }
638  }
639 
640  while (iter < 4 )
641  {
642  DA = D*A ;
643  vpMatrix DAp ;
644 
645  x = DA.pseudoInverse(1e-26) *D*b_ ;
646 
647  vpColVector residu(nos_1);
648  residu = b_ - A*x;
649  r.setIteration(iter) ;
650  r.MEstimator(vpRobust::TUKEY,residu,w) ;
651 
652  k = 0;
653  for (i=0 ; i < nos_1 ; i++)
654  {
655  D[k][k] =w[k] ;
656  k++;
657  }
658  iter++;
659  }
660 
661  k =0 ;
662  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
663  p_me = *it;
664  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
665  {
666  if (w[k] < thresholdWeight)
667  {
669 
670  *it = p_me;
671  }
672  k++ ;
673  }
674  }
675  for(i = 0; i < 5; i ++)
676  K[i] = x[i];
677 
678  getParameters() ;
679 }
680 
681 
691 void
693 {
695 }
696 
697 
706 void
708 {
709  const unsigned int n=5 ;
710  vpImagePoint iP[n];
711 
712  for (unsigned int k =0 ; k < n ; k++)
713  {
714  std::cout << "Click points "<< k+1 <<"/" << n ;
715  std::cout << " on the ellipse in the trigonometric order" <<std::endl ;
716  vpDisplay::getClick(I, iP[k], true);
718  vpDisplay::flush(I);
719  std::cout << iP[k] << std::endl;
720  }
721 
722  iP1 = iP[0];
723  iP2 = iP[n-1];
724 
725  initTracking(I, n, iP) ;
726 }
727 
728 
740 void
741 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const unsigned int n,
742  vpImagePoint *iP)
743 {
744  vpMatrix A(n,5) ;
745  vpColVector b_(n) ;
746  vpColVector x(5) ;
747 
748  // Construction du systeme Ax=b
749  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
750  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
751 
752  for (unsigned int k =0 ; k < n ; k++)
753  {
754  A[k][0] = vpMath::sqr(iP[k].get_j()) ;
755  A[k][1] = 2* iP[k].get_i() * iP[k].get_j() ;
756  A[k][2] = 2* iP[k].get_i() ;
757  A[k][3] = 2* iP[k].get_j() ;
758  A[k][4] = 1 ;
759 
760  b_[k] = - vpMath::sqr(iP[k].get_i()) ;
761  }
762 
763  K = A.pseudoInverse(1e-26)*b_ ;
764 
765  iP1 = iP[0];
766  iP2 = iP[n-1];
767 
768  getParameters() ;
769 
770  computeAngle(iP1, iP2) ;
771 
773 
774  display(I, vpColor::green) ;
775  sample(I) ;
776 
778 
779  track(I) ;
780 
782  vpDisplay::flush(I) ;
783 }
784 
795 void
796 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const std::vector<vpImagePoint> &iP)
797 {
798  unsigned int n = (unsigned int)(iP.size());
799  vpMatrix A(n,5) ;
800  vpColVector b_(n) ;
801  vpColVector x(5) ;
802 
803  // Construction du systeme Ax=b
804  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
805  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
806 
807  for (unsigned int k =0 ; k < n ; k++)
808  {
809  A[k][0] = vpMath::sqr(iP[k].get_j()) ;
810  A[k][1] = 2* iP[k].get_i() * iP[k].get_j() ;
811  A[k][2] = 2* iP[k].get_i() ;
812  A[k][3] = 2* iP[k].get_j() ;
813  A[k][4] = 1 ;
814 
815  b_[k] = - vpMath::sqr(iP[k].get_i()) ;
816  }
817 
818  K = A.pseudoInverse(1e-26)*b_ ;
819 
820  iP1 = iP[0];
821  iP2 = iP[n-1];
822 
823  getParameters() ;
824 
825  computeAngle(iP1, iP2) ;
826 
828 
829  display(I, vpColor::green) ;
830  sample(I) ;
831 
833 
834  track(I) ;
835 
837  vpDisplay::flush(I) ;
838 }
839 
840 void
841 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const vpImagePoint &ic, double a_p, double b_p, double e_p,
842  double low_alpha, double high_alpha)
843 {
844  iPc = ic;
845  a = a_p;
846  b = b_p;
847  e = e_p;
848  alpha1 = low_alpha;
849  alpha2 = high_alpha;
850 
851  if (alpha2 <alpha1)
852  alpha2 += 2 * M_PI;
853 
854  ce = cos(e);
855  se = sin(e);
856 
857  display(I, vpColor::green) ;
858  sample(I) ;
859 
861 
862  track(I) ;
863 
865  vpDisplay::flush(I) ;
866 }
867 
873 void
875 {
876  vpMeTracker::track(I) ;
877 
878  // Estimation des parametres de la droite aux moindres carre
879  suppressPoints() ;
880  setExtremities() ;
881 
882  leastSquare() ;
883  seekExtremities(I) ;
884  setExtremities() ;
885  leastSquare() ;
886 
887  // suppression des points rejetes par la regression robuste
888  suppressPoints() ;
889  setExtremities() ;
890 
891  //reechantillonage si necessaire
892  reSample(I) ;
893 
894  // remet a jour l'angle delta pour chaque point de la liste
895 
896  updateTheta() ;
897 
898  computeMoments();
899 
900  // Remise a jour de delta dans la liste de site me
901  if (vpDEBUG_ENABLE(2))
902  {
903  display(I,vpColor::red) ;
905  vpDisplay::flush(I) ;
906  }
907 }
908 
914 void
915 vpMeEllipse::computeMoments()
916 {
917  double tane = tan(-1/e);
918  m00 = M_PI*a*b;
919  m10 = m00*iPc.get_i();
920  m01 = m00*iPc.get_j();
921  m20 = m00*(a*a+b*b*tane*tane)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_i();
922  m02 = m00*(a*a*tane*tane+b*b)/(4*(1+tane*tane))+m00*iPc.get_j()*iPc.get_j();
923  m11 = m00*tane*(a*a-b*b)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_j();
924  mu11 = m11 - iPc.get_j()*m10;
925  mu02 = m02 - iPc.get_j()*m01;
926  mu20 = m20 - iPc.get_i()*m10;
927 }
928 
929 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
930 
934 void
935 vpMeEllipse::computeAngle(int ip1, int jp1, double &_alpha1,
936  int ip2, int jp2, double &_alpha2)
937 {
938  getParameters() ;
939 
940  int number_of_points = 2000 ;
941  double incr = 2 * M_PI / number_of_points ; // angle increment
942 
943  double dmin1 = 1e6 ;
944  double dmin2 = 1e6 ;
945 
946  double k = -M_PI ;
947  while(k < M_PI) {
948 
949  double j1 = a *cos(k) ; // equation of an ellipse
950  double i1 = b *sin(k) ; // equation of an ellipse
951 
952  // (i1,j1) are the coordinates on the origin centered ellipse ;
953  // a rotation by "e" and a translation by (xci,jc) are done
954  // to get the coordinates of the point on the shifted ellipse
955  double j11 = iPc.get_j() + ce *j1 - se *i1 ;
956  double i11 = iPc.get_i() -( se *j1 + ce *i1) ;
957 
958  double d = vpMath::sqr(ip1-i11) + vpMath::sqr(jp1-j11) ;
959  if (d < dmin1)
960  {
961  dmin1 = d ;
962  alpha1 = k ;
963  _alpha1 = k ;
964  }
965  d = vpMath::sqr(ip2-i11) + vpMath::sqr(jp2-j11) ;
966  if (d < dmin2)
967  {
968  dmin2 = d ;
969  alpha2 = k ;
970  _alpha2 = k ;
971  }
972  k += incr ;
973  }
974 
975  if (alpha2 <alpha1) alpha2 += 2*M_PI ;
976 
977  vpCDEBUG(1) << "end vpMeEllipse::computeAngle(..)" << alpha1 << " " << alpha2 << std::endl ;
978 
979 }
980 
981 
985 void
986 vpMeEllipse::computeAngle(int ip1, int jp1, int ip2, int jp2)
987 {
988 
989  double a1, a2 ;
990  computeAngle(ip1,jp1,a1, ip2, jp2,a2) ;
991 }
992 
993 
994 void
995 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const unsigned int n,
996  unsigned *i, unsigned *j)
997 {
998  vpCDEBUG(1) <<" begin vpMeEllipse::initTracking()"<<std::endl ;
999 
1000  //if (circle==false)
1001  if (1)
1002  {
1003  vpMatrix A(n,5) ;
1004  vpColVector b_(n) ;
1005  vpColVector x(5) ;
1006 
1007  // Construction du systeme Ax=b
1009  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
1010 
1011  for (unsigned int k =0 ; k < n ; k++)
1012  {
1013  A[k][0] = vpMath::sqr(j[k]) ;
1014  A[k][1] = 2* i[k] * j[k] ;
1015  A[k][2] = 2* i[k] ;
1016  A[k][3] = 2* j[k] ;
1017  A[k][4] = 1 ;
1018 
1019  b_[k] = - vpMath::sqr(i[k]) ;
1020  }
1021 
1022  K = A.pseudoInverse(1e-26)*b_ ;
1023  std::cout << K << std::endl;
1024  }
1025  else
1026  {
1027  vpMatrix A(n,3) ;
1028  vpColVector b_(n) ;
1029  vpColVector x(3) ;
1030 
1031  vpColVector Kc(3) ;
1032  for (unsigned int k =0 ; k < n ; k++)
1033  {
1034  A[k][0] = 2* i[k] ;
1035  A[k][1] = 2* j[k] ;
1036 
1037  A[k][2] = 1 ;
1038  b_[k] = - vpMath::sqr(i[k]) - vpMath::sqr(j[k]) ;
1039  }
1040 
1041  Kc = A.pseudoInverse(1e-26)*b_ ;
1042  K[0] = 1 ;
1043  K[1] = 0 ;
1044  K[2] = Kc[0] ;
1045  K[3] = Kc[1] ;
1046  K[4] = Kc[2] ;
1047 
1048  std::cout << K << std::endl;
1049  }
1050  iP1.set_i( i[0] );
1051  iP1.set_j( j[0] );
1052  iP2.set_i( i[n-1] );
1053  iP2.set_j( j[n-1] );
1054 
1055  getParameters() ;
1056  computeAngle(iP1, iP2) ;
1057  display(I, vpColor::green) ;
1058 
1059  sample(I) ;
1060 
1061  // 2. On appelle ce qui n'est pas specifique
1062  {
1064  }
1065 
1066  try{
1067  track(I) ;
1068  }
1069  catch(...)
1070  {
1071  vpERROR_TRACE("Error caught") ;
1072  throw ;
1073  }
1075  vpDisplay::flush(I) ;
1076 
1077 }
1078 #endif // Deprecated
1079 
1103  const double &A, const double &B, const double &E,
1104  const double & smallalpha, const double &highalpha,
1105  const vpColor &color, unsigned int thickness)
1106 {
1107  double j1, i1;
1108  vpImagePoint iP11;
1109  double j2, i2;
1110  vpImagePoint iP22;
1111  j1 = j2 = i1 = i2 = 0 ;
1112 
1113  double incr = vpMath::rad(2) ; // angle increment
1114 
1115  vpDisplay::displayCross(I,center,20, vpColor::red, thickness) ;
1116 
1117  double k = smallalpha ;
1118  while (k+incr<highalpha)
1119  {
1120  j1 = A *cos(k) ; // equation of an ellipse
1121  i1 = B *sin(k) ; // equation of an ellipse
1122 
1123  j2 = A *cos(k+incr) ; // equation of an ellipse
1124  i2 = B *sin(k+incr) ; // equation of an ellipse
1125 
1126  // (i1,j1) are the coordinates on the origin centered ellipse ;
1127  // a rotation by "e" and a translation by (xci,jc) are done
1128  // to get the coordinates of the point on the shifted ellipse
1129  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1130  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1131  // to get the coordinates of the point on the shifted ellipse
1132  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1133  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1134 
1135  vpDisplay::displayLine(I, iP11, iP22, color, thickness) ;
1136 
1137  k += incr ;
1138  }
1139 
1140  j1 = A *cos(smallalpha) ; // equation of an ellipse
1141  i1 = B *sin(smallalpha) ; // equation of an ellipse
1142 
1143  j2 = A *cos(highalpha) ; // equation of an ellipse
1144  i2 = B *sin(highalpha) ; // equation of an ellipse
1145 
1146  // (i1,j1) are the coordinates on the origin centered ellipse ;
1147  // a rotation by "e" and a translation by (xci,jc) are done
1148  // to get the coordinates of the point on the shifted ellipse
1149  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1150  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1151  // to get the coordinates of the point on the shifted ellipse
1152  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1153  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1154 
1155  vpDisplay::displayLine(I, center, iP11, vpColor::red, thickness) ;
1156  vpDisplay::displayLine(I, center, iP22, vpColor::blue, thickness) ;
1157 }
1158 
1182  const double &A, const double &B, const double &E,
1183  const double & smallalpha, const double &highalpha,
1184  const vpColor &color, unsigned int thickness)
1185 {
1186  double j1, i1;
1187  vpImagePoint iP11;
1188  double j2, i2;
1189  vpImagePoint iP22;
1190  j1 = j2 = i1 = i2 = 0 ;
1191 
1192  double incr = vpMath::rad(2) ; // angle increment
1193 
1194  vpDisplay::displayCross(I,center,20, vpColor::red, thickness) ;
1195 
1196  double k = smallalpha ;
1197  while (k+incr<highalpha)
1198  {
1199  j1 = A *cos(k) ; // equation of an ellipse
1200  i1 = B *sin(k) ; // equation of an ellipse
1201 
1202  j2 = A *cos(k+incr) ; // equation of an ellipse
1203  i2 = B *sin(k+incr) ; // equation of an ellipse
1204 
1205  // (i1,j1) are the coordinates on the origin centered ellipse ;
1206  // a rotation by "e" and a translation by (xci,jc) are done
1207  // to get the coordinates of the point on the shifted ellipse
1208  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1209  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1210  // to get the coordinates of the point on the shifted ellipse
1211  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1212  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1213 
1214  vpDisplay::displayLine(I, iP11, iP22, color, thickness) ;
1215 
1216  k += incr ;
1217  }
1218 
1219  j1 = A *cos(smallalpha) ; // equation of an ellipse
1220  i1 = B *sin(smallalpha) ; // equation of an ellipse
1221 
1222  j2 = A *cos(highalpha) ; // equation of an ellipse
1223  i2 = B *sin(highalpha) ; // equation of an ellipse
1224 
1225  // (i1,j1) are the coordinates on the origin centered ellipse ;
1226  // a rotation by "e" and a translation by (xci,jc) are done
1227  // to get the coordinates of the point on the shifted ellipse
1228  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1229  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1230  // to get the coordinates of the point on the shifted ellipse
1231  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1232  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1233 
1234  vpDisplay::displayLine(I, center, iP11, vpColor::red, thickness) ;
1235  vpDisplay::displayLine(I, center, iP22, vpColor::blue, thickness) ;
1236 }
double a
is the semiminor axis of the ellipse.
Definition: vpMeEllipse.h:255
unsigned int getRange() const
Definition: vpMe.h:167
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:97
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
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
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:199
unsigned int getWidth() const
Definition: vpImage.h:226
double jfloat
Definition: vpMeSite.h:96
#define vpDEBUG_ENABLE(level)
Definition: vpDebug.h:526
unsigned int numberOfSignal()
double getMu1() const
Definition: vpMe.h:143
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)
static int round(const double x)
Definition: vpMath.h:249
double get_j() const
Definition: vpImagePoint.h:210
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:226
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:163
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()
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:174
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
void setMu2(const double &mu_2)
Definition: vpMe.h:233
double getMu2() const
Definition: vpMe.h:149
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:374
vpMe * me
Moving edges initialisation parameters.
Definition: vpMeTracker.h:75
Contains an M-Estimator and various influence function.
Definition: vpRobust.h:60
void initTracking(const vpImage< unsigned char > &I)
unsigned int getHeight() const
Definition: vpImage.h:175
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1741
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
double alpha2
The highest angle.
Definition: vpMeEllipse.h:269
void setRange(const unsigned int &r)
Definition: vpMe.h:256
double getSampleStep() const
Definition: vpMe.h:270
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:185
static const vpColor blue
Definition: vpColor.h:169