ViSP  2.9.0
vpMeEllipse.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMeEllipse.cpp 4649 2014-02-07 14:57:11Z fspindle $
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  * Moving edges.
36  *
37  * Authors:
38  * Eric Marchand
39  *
40  *****************************************************************************/
41 
42 
43 
44 #include <visp/vpMeEllipse.h>
45 
46 #include <visp/vpMe.h>
47 #include <visp/vpRobust.h>
48 #include <visp/vpTrackingException.h>
49 #include <visp/vpDebug.h>
50 #include <visp/vpImagePoint.h>
51 
52 #include <cmath> // std::fabs
53 #include <limits> // numeric_limits
54 
55 void computeTheta(double &theta, vpColVector &K, vpImagePoint iP);
63 void
64 computeTheta(double &theta, vpColVector &K, vpImagePoint iP)
65 {
66 
67  double i = iP.get_i();
68  double j = iP.get_j();
69 
70  double A = 2*i+2*K[1]*j + 2*K[2] ;
71  double B = 2*K[0]*j + 2*K[1]*i + 2*K[3];
72 
73  theta = atan2(A,B) ; //Angle between the tangente and the i axis.
74 
75  while (theta > M_PI) { theta -= M_PI ; }
76  while (theta < 0) { theta += M_PI ; }
77 }
78 
79 
84  : K(), iPc(), a(0.), b(0.), e(0.), iP1(), iP2(), alpha1(0), alpha2(2*M_PI),
85  ce(0.), se(0.), angle(), m00(0.), mu11(0.), mu20(0.), mu02(0.),
86  m10(0.), m01(0.), m11(0.), m02(0.), m20(0.), thresholdWeight(0.2), circle(false)
87 {
88  vpCDEBUG(1) << "begin vpMeEllipse::vpMeEllipse() " << std::endl ;
89 
90  // redimensionnement du vecteur de parametre
91  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
92 
93  K.resize(5) ;
94 
95  //j1 = j2 = i1 = i2 = 0 ;
96  iP1.set_i(0);
97  iP1.set_j(0);
98  iP2.set_i(0);
99  iP2.set_j(0);
100 
101  vpCDEBUG(1) << "end vpMeEllipse::vpMeEllipse() " << std::endl ;
102 }
103 
108  : vpMeTracker(meellipse), K(), iPc(), a(0.), b(0.), e(0.), iP1(), iP2(), alpha1(0), alpha2(2*M_PI),
109  ce(0.), se(0.), angle(), m00(0.), mu11(0.), mu20(0.), mu02(0.),
110  m10(0.), m01(0.), m11(0.), m02(0.), m20(0.), thresholdWeight(0.2), circle(false)
111 {
112  K = meellipse.K;
113  iPc = meellipse.iPc;
114  a = meellipse.a;
115  b = meellipse.b;
116  e = meellipse.e;
117 
118  iP1 = meellipse.iP1;
119  iP2 = meellipse.iP2;
120  alpha1 = meellipse.alpha1;
121  alpha2 = meellipse.alpha2;
122  ce = meellipse.ce;
123  se = meellipse.se;
124 
125  angle = meellipse.angle;
126 
127  m00 = meellipse.m00;
128  mu11 = meellipse.mu11;
129  mu20 = meellipse.mu20;
130  mu02 = meellipse.mu02;
131  m10 = meellipse.m10;
132  m01 = meellipse.m01;
133  m11 = meellipse.m11;
134  m02 = meellipse.m02;
135  m20 = meellipse.m20;
136  thresholdWeight = meellipse.thresholdWeight;
137 
138  circle = meellipse.circle;
139 }
140 
145 {
146  vpCDEBUG(1) << "begin vpMeEllipse::~vpMeEllipse() " << std::endl ;
147 
148  list.clear();
149  angle.clear();
150 
151  vpCDEBUG(1) << "end vpMeEllipse::~vpMeEllipse() " << std::endl ;
152 }
153 
154 
165 void
166 vpMeEllipse::sample(const vpImage<unsigned char> & I)
167 {
168  vpCDEBUG(1) <<"begin vpMeEllipse::sample() : "<<std::endl ;
169 
170  if (!me) {
171  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
173  "Moving edges not initialized")) ;
174  }
175 
176  int height = (int)I.getHeight() ;
177  int width = (int)I.getWidth() ;
178 
179  double n_sample;
180 
181  //if (me->getSampleStep()==0)
182  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
183  {
184  std::cout << "In vpMeEllipse::sample: " ;
185  std::cout << "function called with sample step = 0" ;
186  //return fatalError ;
187  }
188 
189  double j, i;//, j11, i11;
190  vpImagePoint iP11;
191  j = i = 0.0 ;
192 
193  double incr = vpMath::rad(me->getSampleStep()) ; // angle increment en degree
194  vpColor col = vpColor::red ;
195  getParameters() ;
196 
197  // Delete old list
198  list.clear();
199 
200  angle.clear();
201 
202  // sample positions
203  double k = alpha1 ;
204  while (k<alpha2)
205  {
206 // j = a *cos(k) ; // equation of an ellipse
207 // i = b *sin(k) ; // equation of an ellipse
208 
209  j = a *sin(k) ; // equation of an ellipse
210  i = b *cos(k) ; // equation of an ellipse
211 
212  // (i,j) are the coordinates on the origin centered ellipse ;
213  // a rotation by "e" and a translation by (xci,jc) are done
214  // to get the coordinates of the point on the shifted ellipse
215 // iP11.set_j( iPc.get_j() + ce *j - se *i );
216 // iP11.set_i( iPc.get_i() -( se *j + ce *i) );
217 
218  iP11.set_j( iPc.get_j() + ce *j + se *i );
219  iP11.set_i( iPc.get_i() - se *j + ce *i );
220 
221  vpDisplay::displayCross(I, iP11, 5, col) ;
222 
223  double theta ;
224  computeTheta(theta, K, iP11) ;
225 
226  // If point is in the image, add to the sample list
227  if(!outOfImage(vpMath::round(iP11.get_i()), vpMath::round(iP11.get_j()), 0, height, width))
228  {
229  vpMeSite pix ;
230  pix.init((int)iP11.get_i(), (int)iP11.get_j(), theta) ;
233 
234  if(vpDEBUG_ENABLE(3))
235  {
237  }
238  list.push_back(pix);
239  angle.push_back(k);
240  }
241  k += incr ;
242 
243  }
245 
246  n_sample = (unsigned int)list.size() ;
247 
248  vpCDEBUG(1) << "end vpMeEllipse::sample() : " ;
249  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
250 }
251 
252 
267 void
268 vpMeEllipse::reSample(const vpImage<unsigned char> &I)
269 {
270  if (!me) {
271  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
273  "Moving edges not initialized")) ;
274  }
275 
276  unsigned int n = numberOfSignal() ;
277  double expecteddensity = (alpha2-alpha1) / vpMath::rad((double)me->getSampleStep());
278  if ((double)n<0.9*expecteddensity){
279  sample(I) ;
280  }
281 }
282 
283 
290 void
291 vpMeEllipse::getParameters()
292 {
293 
294  double k[6] ;
295  for (unsigned int i=0 ; i < 5 ; i++)
296  k[i+1] = K[i] ;
297  k[0] = 1 ;
298 
299  double d = k[2]*k[2] - k[0]*k[1];
300 
301 
302  iPc.set_i( (k[1] * k[3] - k[2] * k[4]) / d );
303  iPc.set_j( (k[0] * k[4] - k[2] * k[3]) / d );
304 
305  double sq = sqrt(vpMath::sqr(k[1]-k[0]) + 4.0*vpMath::sqr(k[2])) ;
306  if (circle ==true)
307  {
308  e = 0 ;
309  }
310  else
311  {
312  e = (k[1] - k[0] + sq) / (2.0*k[2]);
313  e = (-1/e) ;
314 
315  e = atan(e) ;
316  }
317 
318  if(e < 0.0) e += M_PI ;
319 
320  ce = cos(e) ;
321  se = sin(e) ;
322 
323  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]) ;
324  double a2 = num / (k[0] + k[1] + sq ) ;
325  double b2 = num / (k[0] + k[1] - sq ) ;
326 
327  a = sqrt( a2 ) ;
328  b = sqrt( b2 ) ;
329 
330 }
331 
335 void
337 {
338  std::cout << "K" << std::endl ;
339  std::cout << K.t() ;
340  std::cout << iPc << std::endl ;
341 }
342 
351 void
352 vpMeEllipse::computeAngle(vpImagePoint pt1, vpImagePoint pt2)
353 {
354 
355  getParameters() ;
356  double j1, i1, j11, i11;
357  j1 = i1 = 0.0 ;
358 
359  int number_of_points = 2000 ;
360  double incr = 2 * M_PI / number_of_points ; // angle increment
361 
362  double dmin1 = 1e6 ;
363  double dmin2 = 1e6 ;
364 
365  double k = 0 ;
366  while(k < 2*M_PI) {
367 
368 // j1 = a *cos(k) ; // equation of an ellipse
369 // i1 = b *sin(k) ; // equation of an ellipse
370 
371  j1 = a *sin(k) ; // equation of an ellipse
372  i1 = b *cos(k) ; // equation of an ellipse
373 
374  // (i1,j1) are the coordinates on the origin centered ellipse ;
375  // a rotation by "e" and a translation by (xci,jc) are done
376  // to get the coordinates of the point on the shifted ellipse
377 // j11 = iPc.get_j() + ce *j1 - se *i1 ;
378 // i11 = iPc.get_i() -( se *j1 + ce *i1) ;
379 
380  j11 = iPc.get_j() + ce *j1 + se *i1 ;
381  i11 = iPc.get_i() - se *j1 + ce *i1 ;
382 
383  double d = vpMath::sqr(pt1.get_i()-i11) + vpMath::sqr(pt1.get_j()-j11) ;
384  if (d < dmin1)
385  {
386  dmin1 = d ;
387  alpha1 = k ;
388  }
389  d = vpMath::sqr(pt2.get_i()-i11) + vpMath::sqr(pt2.get_j()-j11) ;
390  if (d < dmin2)
391  {
392  dmin2 = d ;
393  alpha2 = k ;
394  }
395  k += incr ;
396  }
397  //std::cout << "end vpMeEllipse::computeAngle(..)" << alpha1 << " " << alpha2 << std::endl ;
398 
399  if (alpha2 <alpha1)
400  {
401 // double alphatmp = alpha2;
402 // alpha2 = alpha1;
403 // alpha1 = alphatmp;
404  alpha2 += 2 * M_PI;
405  }
406 
407  //std::cout << "end vpMeEllipse::computeAngle(..)" << alpha1 << " " << alpha2 << std::endl ;
408 
409 
410 }
411 
412 
418 void
419 vpMeEllipse::updateTheta()
420 {
421  vpMeSite p_me;
422  double theta;
423  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
424  p_me = *it;
425  vpImagePoint iP;
426  iP.set_i(p_me.ifloat);
427  iP.set_j(p_me.jfloat);
428  computeTheta(theta, K, iP) ;
429  p_me.alpha = theta ;
430  *it = p_me;
431  }
432 }
433 
437 void
438 vpMeEllipse::suppressPoints()
439 {
440  // Loop through list of sites to track
441  std::list<vpMeSite>::iterator itList = list.begin();
442  for(std::list<double>::iterator it=angle.begin(); it!=angle.end(); ){
443  vpMeSite s = *itList;//current reference pixel
445  {
446  itList = list.erase(itList) ;
447  it = angle.erase(it);
448  }
449  else
450  {
451  ++itList;
452  ++it;
453  }
454  }
455 }
456 
457 
467 void
468 vpMeEllipse::seekExtremities(const vpImage<unsigned char> &I)
469 {
470  if (!me) {
471  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
473  "Moving edges not initialized")) ;
474  }
475 
476  int rows = (int)I.getHeight() ;
477  int cols = (int)I.getWidth() ;
478 
479  vpImagePoint ip;
480 
481  unsigned int memory_range = me->getRange() ;
482  me->setRange(2);
483 
484  double memory_mu1 = me->getMu1();
485  me->setMu1(0.5);
486 
487  double memory_mu2 = me->getMu2();
488  me->setMu2(0.5);
489 
490  double incr = vpMath::rad(2.0) ;
491 
492  if (alpha2-alpha1 < 2*M_PI-vpMath::rad(6.0))
493  {
494  vpMeSite P;
495  double k = alpha1;
496  double i1,j1;
497 
498  for (unsigned int i=0 ; i < 3 ; i++)
499  {
500  k -= incr;
501  //while ( k < -M_PI ) { k+=2*M_PI; }
502 
503  i1 = b *cos(k) ; // equation of an ellipse
504  j1 = a *sin(k) ; // equation of an ellipse
505  P.ifloat = iPc.get_i() - se *j1 + ce *i1 ; P.i = (int)P.ifloat ;
506  P.jfloat = iPc.get_j() + ce *j1 + se *i1 ; P.j = (int)P.jfloat ;
507 
508  if(!outOfImage(P.i, P.j, 5, rows, cols))
509  {
510  P.track(I,me,false) ;
511 
513  {
514  list.push_back(P);
515  angle.push_back(k);
516  if (vpDEBUG_ENABLE(3)) {
517  ip.set_i( P.i );
518  ip.set_j( P.j );
519 
521  }
522  }
523  else {
524  if (vpDEBUG_ENABLE(3)) {
525  ip.set_i( P.i );
526  ip.set_j( P.j );
528  }
529  }
530  }
531  }
532 
533  k = alpha2;
534 
535  for (unsigned int i=0 ; i < 3 ; i++)
536  {
537  k += incr;
538  //while ( k > M_PI ) { k-=2*M_PI; }
539 
540  i1 = b *cos(k) ; // equation of an ellipse
541  j1 = a *sin(k) ; // equation of an ellipse
542  P.ifloat = iPc.get_i() - se *j1 + ce *i1 ; P.i = (int)P.ifloat ;
543  P.jfloat = iPc.get_j() + ce *j1 + se *i1 ; P.j = (int)P.jfloat ;
544 
545  if(!outOfImage(P.i, P.j, 5, rows, cols))
546  {
547  P.track(I,me,false) ;
548 
550  {
551  list.push_back(P);
552  angle.push_back(k);
553  if (vpDEBUG_ENABLE(3)) {
554  ip.set_i( P.i );
555  ip.set_j( P.j );
556 
558  }
559  }
560  else {
561  if (vpDEBUG_ENABLE(3)) {
562  ip.set_i( P.i );
563  ip.set_j( P.j );
565  }
566  }
567  }
568  }
569  }
570 
571  suppressPoints() ;
572 
573  me->setRange(memory_range);
574  me->setMu1(memory_mu1);
575  me->setMu2(memory_mu2);
576 }
577 
578 
582 void
583 vpMeEllipse::setExtremities()
584 {
585  double alphamin = +1e6;
586  double alphamax = -1e6;
587  double imin = 0;
588  double jmin = 0;
589  double imax = 0;
590  double jmax = 0;
591 
592  // Loop through list of sites to track
593  std::list<double>::const_iterator itAngle = angle.begin();
594 
595  for(std::list<vpMeSite>::const_iterator itList=list.begin(); itList!=list.end(); ++itList){
596  vpMeSite s = *itList;//current reference pixel
597  double alpha = *itAngle;
598  if (alpha < alphamin)
599  {
600  alphamin = alpha;
601  imin = s.ifloat ;
602  jmin = s.jfloat ;
603  }
604 
605  if (alpha > alphamax)
606  {
607  alphamax = alpha;
608  imax = s.ifloat ;
609  jmax = s.jfloat ;
610  }
611  ++itAngle;
612  }
613 
614  alpha1 = alphamin;
615  alpha2 = alphamax;
616  iP1.set_ij(imin,jmin);
617  iP2.set_ij(imax,jmax);
618 }
619 
620 
626 void
627 vpMeEllipse::leastSquare()
628 {
629  // Construction du systeme Ax=b
631  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
632  unsigned int i ;
633 
634  vpMeSite p_me ;
635 
636  unsigned int iter =0 ;
638  vpRobust r(numberOfSignal()) ;
639  r.setThreshold(2);
640  r.setIteration(0) ;
642  D.setIdentity() ;
643  vpMatrix DA, DAmemory ;
644  vpColVector DAx ;
646  w =1 ;
647  unsigned int nos_1 = numberOfSignal() ;
648 
649  if (list.size() < 3)
650  {
651  vpERROR_TRACE("Not enough point") ;
653  "not enough point")) ;
654  }
655 
656  if (circle ==false)
657  {
658  vpMatrix A(numberOfSignal(),5) ;
659  vpColVector x(5);
660 
661  unsigned int k =0 ;
662  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
663  p_me = *it;
664  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
665  {
666  A[k][0] = vpMath::sqr(p_me.jfloat) ;
667  A[k][1] = 2 * p_me.ifloat * p_me.jfloat ;
668  A[k][2] = 2 * p_me.ifloat ;
669  A[k][3] = 2 * p_me.jfloat ;
670  A[k][4] = 1 ;
671 
672  b_[k] = - vpMath::sqr(p_me.ifloat) ;
673  k++ ;
674  }
675  }
676 
677  while (iter < 4 )
678  {
679  DA = D*A ;
680  vpMatrix DAp ;
681 
682  x = DA.pseudoInverse(1e-26) *D*b_ ;
683 
684  vpColVector residu(nos_1);
685  residu = b_ - A*x;
686  r.setIteration(iter) ;
687  r.MEstimator(vpRobust::TUKEY,residu,w) ;
688 
689  k = 0;
690  for (i=0 ; i < nos_1 ; i++)
691  {
692  D[k][k] =w[k] ;
693  k++;
694  }
695  iter++;
696  }
697 
698  k =0 ;
699  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
700  p_me = *it;
701  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
702  {
703  if (w[k] < thresholdWeight)
704  {
706 
707  *it = p_me;
708  }
709  k++ ;
710  }
711  }
712  for(i = 0; i < 5; i ++)
713  K[i] = x[i];
714  }
715 
716  else
717  {
718  vpMatrix A(numberOfSignal(),3) ;
719  vpColVector x(3);
720 
721  unsigned int k =0 ;
722  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
723  p_me = *it;
724  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
725  {
726  A[k][0] = 2* p_me.ifloat ;
727  A[k][1] = 2 * p_me.jfloat ;
728  A[k][2] = 1 ;
729 
730  b_[k] = - vpMath::sqr(p_me.ifloat) - vpMath::sqr(p_me.jfloat) ;
731  k++ ;
732  }
733  }
734 
735  while (iter < 4 )
736  {
737  DA = D*A ;
738  vpMatrix DAp ;
739 
740  x = DA.pseudoInverse(1e-26) *D*b_ ;
741 
742  vpColVector residu(nos_1);
743  residu = b_ - A*x;
744  r.setIteration(iter) ;
745  r.MEstimator(vpRobust::TUKEY,residu,w) ;
746 
747  k = 0;
748  for (i=0 ; i < nos_1 ; i++)
749  {
750  D[k][k] =w[k];
751  k++;
752  }
753  iter++;
754  }
755 
756  k =0 ;
757  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
758  p_me = *it;
759  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
760  {
761  if (w[k] < thresholdWeight)
762  {
764 
765  *it = p_me;
766  }
767  k++ ;
768  }
769  }
770  for(i = 0; i < 3; i ++)
771  K[i+2] = x[i];
772  }
773  getParameters() ;
774 }
775 
776 
786 void
788 {
790 }
791 
792 
799 void
801 {
802  vpCDEBUG(1) <<" begin vpMeEllipse::initTracking()"<<std::endl ;
803 
804  const unsigned int n=5 ;
805  vpImagePoint iP[n];
806 
807  for (unsigned int k =0 ; k < n ; k++)
808  {
809  std::cout << "Click points "<< k+1 <<"/" << n ;
810  std::cout << " on the ellipse in the trigonometric order" <<std::endl ;
811  vpDisplay::getClick(I, iP[k], true);
813  vpDisplay::flush(I);
814  std::cout << iP[k] << std::endl;
815  }
816 
817  iP1 = iP[0];
818  iP2 = iP[n-1];
819 
820  initTracking(I, n, iP) ;
821 }
822 
823 
834 void
835 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const unsigned int n,
836  vpImagePoint *iP)
837 {
838  vpCDEBUG(1) <<" begin vpMeEllipse::initTracking()"<<std::endl ;
839 
840  if (circle==false)
841  {
842  vpMatrix A(n,5) ;
843  vpColVector b_(n) ;
844  vpColVector x(5) ;
845 
846  // Construction du systeme Ax=b
848  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
849 
850  for (unsigned int k =0 ; k < n ; k++)
851  {
852  A[k][0] = vpMath::sqr(iP[k].get_j()) ;
853  A[k][1] = 2* iP[k].get_i() * iP[k].get_j() ;
854  A[k][2] = 2* iP[k].get_i() ;
855  A[k][3] = 2* iP[k].get_j() ;
856  A[k][4] = 1 ;
857 
858  b_[k] = - vpMath::sqr(iP[k].get_i()) ;
859  }
860 
861  K = A.pseudoInverse(1e-26)*b_ ;
862  std::cout << K << std::endl;
863  }
864  else
865  {
866  vpMatrix A(n,3) ;
867  vpColVector b_(n) ;
868  vpColVector x(3) ;
869 
870  vpColVector Kc(3) ;
871  for (unsigned int k =0 ; k < n ; k++)
872  {
873  A[k][0] = 2* iP[k].get_i() ;
874  A[k][1] = 2* iP[k].get_j() ;
875  A[k][2] = 1 ;
876 
877  b_[k] = - vpMath::sqr(iP[k].get_i()) - vpMath::sqr(iP[k].get_j()) ;
878  }
879 
880  Kc = A.pseudoInverse(1e-26)*b_ ;
881  K[0] = 1 ;
882  K[1] = 0 ;
883  K[2] = Kc[0] ;
884  K[3] = Kc[1] ;
885  K[4] = Kc[2] ;
886 
887  std::cout << K << std::endl;
888  }
889 
890  iP1 = iP[0];
891  iP2 = iP[n-1];
892 
893  getParameters() ;
894  computeAngle(iP1, iP2) ;
895  display(I, vpColor::green) ;
896 
897  sample(I) ;
898 
899  // 2. On appelle ce qui n'est pas specifique
900  {
902  }
903 
904  try{
905  track(I) ;
906  }
907  catch(...)
908  {
909  vpERROR_TRACE("Error caught") ;
910  throw ;
911  }
913  vpDisplay::flush(I) ;
914 
915 }
916 
922 void
924 {
925  vpCDEBUG(1) <<"begin vpMeEllipse::track()"<<std::endl ;
926 
927  static int iter =0 ;
928  // 1. On fait ce qui concerne les ellipse (peut etre vide)
929  {
930  }
931 
932  //vpDisplay::display(I) ;
933  // 2. On appelle ce qui n'est pas specifique
934  {
935 
936  try{
937  vpMeTracker::track(I) ;
938  }
939  catch(...)
940  {
941  vpERROR_TRACE("Error caught") ;
942  throw ;
943  }
944  // std::cout << "number of signals " << numberOfSignal() << std::endl ;
945  }
946 
947  // 3. On revient aux ellipses
948  {
949  // Estimation des parametres de la droite aux moindres carre
950  suppressPoints() ;
951  setExtremities() ;
952 
953 
954  try{
955  leastSquare() ; }
956  catch(...)
957  {
958  vpERROR_TRACE("Error caught") ;
959  throw ;
960  }
961 
962  seekExtremities(I) ;
963 
964  setExtremities() ;
965 
966  try
967  {
968  leastSquare() ;
969  }
970  catch(...)
971  {
972  vpERROR_TRACE("Error caught") ;
973  throw ;
974  }
975 
976  // suppression des points rejetes par la regression robuste
977  suppressPoints() ;
978  setExtremities() ;
979 
980  //reechantillonage si necessaire
981  reSample(I) ;
982 
983  // remet a jour l'angle delta pour chaque point de la liste
984 
985  updateTheta() ;
986 
987  computeMoments();
988 
989  // Remise a jour de delta dans la liste de site me
990  if (vpDEBUG_ENABLE(2))
991  {
992  display(I,vpColor::red) ;
994  vpDisplay::flush(I) ;
995  }
996 // computeAngle(iP1, iP2) ;
997 //
998 // if (iter%5==0)
999 // {
1000 // sample(I) ;
1001 // try{
1002 // leastSquare() ; }
1003 // catch(...)
1004 // {
1005 // vpERROR_TRACE("Error caught") ;
1006 // throw ;
1007 // }
1008 // computeAngle(iP1, iP2) ;
1009 // }
1010 // seekExtremities(I) ;
1011 //
1012 // vpMeTracker::display(I) ;
1013 // // vpDisplay::flush(I) ;
1014 //
1015 // // remet a jour l'angle theta pour chaque point de la liste
1016 // updateTheta() ;
1017 
1018  }
1019 
1020  iter++ ;
1021 
1022 
1023  vpCDEBUG(1) << "end vpMeEllipse::track()"<<std::endl ;
1024 
1025 }
1026 
1027 
1033 void
1034 vpMeEllipse::computeMoments()
1035 {
1036  double tane = tan(-1/e);
1037  m00 = M_PI*a*b;
1038  m10 = m00*iPc.get_i();
1039  m01 = m00*iPc.get_j();
1040  m20 = m00*(a*a+b*b*tane*tane)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_i();
1041  m02 = m00*(a*a*tane*tane+b*b)/(4*(1+tane*tane))+m00*iPc.get_j()*iPc.get_j();
1042  m11 = m00*tane*(a*a-b*b)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_j();
1043  mu11 = m11 - iPc.get_j()*m10;
1044  mu02 = m02 - iPc.get_j()*m01;
1045  mu20 = m20 - iPc.get_i()*m10;
1046 }
1047 
1048 
1049 
1050 
1051 
1052 
1053 
1054 
1055 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
1056 
1060 void
1061 vpMeEllipse::computeAngle(int ip1, int jp1, double &_alpha1,
1062  int ip2, int jp2, double &_alpha2)
1063 {
1064 
1065  getParameters() ;
1066  double j1, i1, j11, i11;
1067  j1 = i1 = 0.0 ;
1068 
1069  int number_of_points = 2000 ;
1070  double incr = 2 * M_PI / number_of_points ; // angle increment
1071 
1072  double dmin1 = 1e6 ;
1073  double dmin2 = 1e6 ;
1074 
1075  double k = -M_PI ;
1076  while(k < M_PI) {
1077 
1078  j1 = a *cos(k) ; // equation of an ellipse
1079  i1 = b *sin(k) ; // equation of an ellipse
1080 
1081  // (i1,j1) are the coordinates on the origin centered ellipse ;
1082  // a rotation by "e" and a translation by (xci,jc) are done
1083  // to get the coordinates of the point on the shifted ellipse
1084  j11 = iPc.get_j() + ce *j1 - se *i1 ;
1085  i11 = iPc.get_i() -( se *j1 + ce *i1) ;
1086 
1087  double d = vpMath::sqr(ip1-i11) + vpMath::sqr(jp1-j11) ;
1088  if (d < dmin1)
1089  {
1090  dmin1 = d ;
1091  alpha1 = k ;
1092  _alpha1 = k ;
1093  }
1094  d = vpMath::sqr(ip2-i11) + vpMath::sqr(jp2-j11) ;
1095  if (d < dmin2)
1096  {
1097  dmin2 = d ;
1098  alpha2 = k ;
1099  _alpha2 = k ;
1100  }
1101  k += incr ;
1102  }
1103 
1104  if (alpha2 <alpha1) alpha2 += 2*M_PI ;
1105 
1106  vpCDEBUG(1) << "end vpMeEllipse::computeAngle(..)" << alpha1 << " " << alpha2 << std::endl ;
1107 
1108 }
1109 
1110 
1114 void
1115 vpMeEllipse::computeAngle(int ip1, int jp1, int ip2, int jp2)
1116 {
1117 
1118  double a1, a2 ;
1119  computeAngle(ip1,jp1,a1, ip2, jp2,a2) ;
1120 }
1121 
1122 
1123 void
1124 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const unsigned int n,
1125  unsigned *i, unsigned *j)
1126 {
1127  vpCDEBUG(1) <<" begin vpMeEllipse::initTracking()"<<std::endl ;
1128 
1129  if (circle==false)
1130  {
1131  vpMatrix A(n,5) ;
1132  vpColVector b_(n) ;
1133  vpColVector x(5) ;
1134 
1135  // Construction du systeme Ax=b
1137  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
1138 
1139  for (unsigned int k =0 ; k < n ; k++)
1140  {
1141  A[k][0] = vpMath::sqr(j[k]) ;
1142  A[k][1] = 2* i[k] * j[k] ;
1143  A[k][2] = 2* i[k] ;
1144  A[k][3] = 2* j[k] ;
1145  A[k][4] = 1 ;
1146 
1147  b_[k] = - vpMath::sqr(i[k]) ;
1148  }
1149 
1150  K = A.pseudoInverse(1e-26)*b_ ;
1151  std::cout << K << std::endl;
1152  }
1153  else
1154  {
1155  vpMatrix A(n,3) ;
1156  vpColVector b_(n) ;
1157  vpColVector x(3) ;
1158 
1159  vpColVector Kc(3) ;
1160  for (unsigned int k =0 ; k < n ; k++)
1161  {
1162  A[k][0] = 2* i[k] ;
1163  A[k][1] = 2* j[k] ;
1164 
1165  A[k][2] = 1 ;
1166  b_[k] = - vpMath::sqr(i[k]) - vpMath::sqr(j[k]) ;
1167  }
1168 
1169  Kc = A.pseudoInverse(1e-26)*b_ ;
1170  K[0] = 1 ;
1171  K[1] = 0 ;
1172  K[2] = Kc[0] ;
1173  K[3] = Kc[1] ;
1174  K[4] = Kc[2] ;
1175 
1176  std::cout << K << std::endl;
1177  }
1178  iP1.set_i( i[0] );
1179  iP1.set_j( j[0] );
1180  iP2.set_i( i[n-1] );
1181  iP2.set_j( j[n-1] );
1182 
1183  getParameters() ;
1184  computeAngle(iP1, iP2) ;
1185  display(I, vpColor::green) ;
1186 
1187  sample(I) ;
1188 
1189  // 2. On appelle ce qui n'est pas specifique
1190  {
1192  }
1193 
1194  try{
1195  track(I) ;
1196  }
1197  catch(...)
1198  {
1199  vpERROR_TRACE("Error caught") ;
1200  throw ;
1201  }
1203  vpDisplay::flush(I) ;
1204 
1205 }
1206 #endif // Deprecated
1207 
1229  const double &A, const double &B, const double &E,
1230  const double & smallalpha, const double &highalpha,
1231  vpColor color)
1232 {
1233  double j1, i1;
1234  vpImagePoint iP11;
1235  double j2, i2;
1236  vpImagePoint iP22;
1237  j1 = j2 = i1 = i2 = 0 ;
1238 
1239  double incr = vpMath::rad(2) ; // angle increment
1240 
1241  vpDisplay::displayCross(I,center,20,vpColor::red) ;
1242 
1243  double k = smallalpha ;
1244  while (k+incr<highalpha)
1245  {
1246  j1 = A *cos(k) ; // equation of an ellipse
1247  i1 = B *sin(k) ; // equation of an ellipse
1248 
1249  j2 = A *cos(k+incr) ; // equation of an ellipse
1250  i2 = B *sin(k+incr) ; // equation of an ellipse
1251 
1252  // (i1,j1) are the coordinates on the origin centered ellipse ;
1253  // a rotation by "e" and a translation by (xci,jc) are done
1254  // to get the coordinates of the point on the shifted ellipse
1255  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1256  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1257  // to get the coordinates of the point on the shifted ellipse
1258  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1259  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1260 
1261  vpDisplay::displayLine(I, iP11, iP22, color, 3) ;
1262 
1263  k += incr ;
1264  }
1265 
1266  j1 = A *cos(smallalpha) ; // equation of an ellipse
1267  i1 = B *sin(smallalpha) ; // equation of an ellipse
1268 
1269  j2 = A *cos(highalpha) ; // equation of an ellipse
1270  i2 = B *sin(highalpha) ; // equation of an ellipse
1271 
1272  // (i1,j1) are the coordinates on the origin centered ellipse ;
1273  // a rotation by "e" and a translation by (xci,jc) are done
1274  // to get the coordinates of the point on the shifted ellipse
1275  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1276  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1277  // to get the coordinates of the point on the shifted ellipse
1278  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1279  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1280 
1281  vpDisplay::displayLine(I, center, iP11, vpColor::red, 3) ;
1282  vpDisplay::displayLine(I, center, iP22, vpColor::blue, 3) ;
1283 }
1284 
1306  const double &A, const double &B, const double &E,
1307  const double & smallalpha, const double &highalpha,
1308  vpColor color)
1309 {
1310  double j1, i1;
1311  vpImagePoint iP11;
1312  double j2, i2;
1313  vpImagePoint iP22;
1314  j1 = j2 = i1 = i2 = 0 ;
1315 
1316  double incr = vpMath::rad(2) ; // angle increment
1317 
1318  vpDisplay::displayCross(I,center,20,vpColor::red) ;
1319 
1320  double k = smallalpha ;
1321  while (k+incr<highalpha)
1322  {
1323  j1 = A *cos(k) ; // equation of an ellipse
1324  i1 = B *sin(k) ; // equation of an ellipse
1325 
1326  j2 = A *cos(k+incr) ; // equation of an ellipse
1327  i2 = B *sin(k+incr) ; // equation of an ellipse
1328 
1329  // (i1,j1) are the coordinates on the origin centered ellipse ;
1330  // a rotation by "e" and a translation by (xci,jc) are done
1331  // to get the coordinates of the point on the shifted ellipse
1332  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1333  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1334  // to get the coordinates of the point on the shifted ellipse
1335  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1336  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1337 
1338  vpDisplay::displayLine(I, iP11, iP22, color, 3) ;
1339 
1340  k += incr ;
1341  }
1342 
1343  j1 = A *cos(smallalpha) ; // equation of an ellipse
1344  i1 = B *sin(smallalpha) ; // equation of an ellipse
1345 
1346  j2 = A *cos(highalpha) ; // equation of an ellipse
1347  i2 = B *sin(highalpha) ; // equation of an ellipse
1348 
1349  // (i1,j1) are the coordinates on the origin centered ellipse ;
1350  // a rotation by "e" and a translation by (xci,jc) are done
1351  // to get the coordinates of the point on the shifted ellipse
1352  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1353  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1354  // to get the coordinates of the point on the shifted ellipse
1355  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1356  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1357 
1358  vpDisplay::displayLine(I, center, iP11, vpColor::red, 3) ;
1359  vpDisplay::displayLine(I, center, iP22, vpColor::blue, 3) ;
1360 }
double a
is the semiminor axis of the ellipse.
Definition: vpMeEllipse.h:313
unsigned int getRange() const
Definition: vpMe.h:236
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
double m01
Definition: vpMeEllipse.h:339
double e
is the angle made by the major axis and the i axis of the image frame .
Definition: vpMeEllipse.h:317
void initTracking(const vpImage< unsigned char > &I)
double mu02
Definition: vpMeEllipse.h:337
void init()
Definition: vpMeSite.cpp:73
double get_i() const
Definition: vpImagePoint.h:194
unsigned int getWidth() const
Definition: vpImage.h:159
double jfloat
Definition: vpMeSite.h:100
unsigned int numberOfSignal()
#define vpERROR_TRACE
Definition: vpDebug.h:395
double getMu1() const
Definition: vpMe.h:178
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:76
double thresholdWeight
Threshold for the robust least square.
Definition: vpMeEllipse.h:343
Class to define colors available for display functionnalities.
Definition: vpColor.h:125
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:321
double alpha
Definition: vpMeSite.h:104
int i
Definition: vpMeSite.h:98
Class that tracks an ellipse moving edges.
Definition: vpMeEllipse.h:142
#define vpDEBUG_ENABLE(level)
Definition: vpDebug.h:530
#define vpDERROR_TRACE
Definition: vpDebug.h:459
double mu20
Definition: vpMeEllipse.h:337
static const vpColor green
Definition: vpColor.h:170
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1994
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:205
double b
is the semimajor axis of the ellipse.
Definition: vpMeEllipse.h:315
double se
Value of sin(e).
Definition: vpMeEllipse.h:331
void setMu1(const double &mu_1)
Definition: vpMe.h:171
static const vpColor red
Definition: vpColor.h:167
vpMeSiteState getState() const
Definition: vpMeSite.h:202
double ifloat
Definition: vpMeSite.h:100
virtual ~vpMeEllipse()
double m20
Definition: vpMeEllipse.h:341
void set_i(const double ii)
Definition: vpImagePoint.h:158
void track(const vpImage< unsigned char > &Im)
std::list< vpMeSite > list
Definition: vpMeTracker.h:80
Error that can be emited by the vpTracker class and its derivates.
vpImagePoint iP2
The coordinates of the point corresponding to the highest angle. More things about the are given at...
Definition: vpMeEllipse.h:323
vpImagePoint iPc
The coordinates of the ellipse center.
Definition: vpMeEllipse.h:311
double m11
Second order raw moments.
Definition: vpMeEllipse.h:341
double alpha1
The smallest angle.
Definition: vpMeEllipse.h:325
static double sqr(double x)
Definition: vpMath.h:106
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:152
void display(const vpImage< unsigned char > &I, vpColor col)
void track(const vpImage< unsigned char > &I)
Track sampled pixels.
double mu11
Second order central moments.
Definition: vpMeEllipse.h:337
double m10
First order raw moments.
Definition: vpMeEllipse.h:339
Contains abstract elements for a Distance to Feature type feature.
Definition: vpMeTracker.h:71
vpColVector K
Definition: vpMeEllipse.h:309
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:189
double m00
Surface.
Definition: vpMeEllipse.h:335
#define vpCDEBUG(level)
Definition: vpDebug.h:506
static double rad(double deg)
Definition: vpMath.h:100
std::list< double > angle
Stores the value of the angle for each vpMeSite.
Definition: vpMeEllipse.h:333
void set_j(const double jj)
Definition: vpImagePoint.h:169
void setMu2(const double &mu_2)
Definition: vpMe.h:185
double getMu2() const
Definition: vpMe.h:192
int j
Definition: vpMeSite.h:98
double m02
Definition: vpMeEllipse.h:341
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
void track(const vpImage< unsigned char > &im, const vpMe *me, const bool test_contraste=true)
Definition: vpMeSite.cpp:381
vpMe * me
Moving edges initialisation parameters.
Definition: vpMeTracker.h:82
Contains an M-Estimator and various influence function.
Definition: vpRobust.h:63
void initTracking(const vpImage< unsigned char > &I)
unsigned int getHeight() const
Definition: vpImage.h:150
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1861
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:92
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:327
void setRange(const unsigned int &r)
Definition: vpMe.h:229
double getSampleStep() const
Definition: vpMe.h:278
vpMeSite::vpMeSiteDisplayType selectDisplay
Definition: vpMeTracker.h:87
virtual void display(const vpImage< unsigned char > &I, vpColor col)=0
double ce
Value of cos(e).
Definition: vpMeEllipse.h:329
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:180
static const vpColor blue
Definition: vpColor.h:173