ViSP  2.10.0
vpMeEllipse.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMeEllipse.cpp 4706 2014-03-28 07:52:00Z 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.),
87  thresholdWeight(0.2), expecteddensity(0.), circle(false)
88 {
89  vpCDEBUG(1) << "begin vpMeEllipse::vpMeEllipse() " << std::endl ;
90 
91  // redimensionnement du vecteur de parametre
92  // i^2 + K0 j^2 + 2 K1 i j + 2 K2 i + 2 K3 j + K4
93 
94  K.resize(5) ;
95 
96  //j1 = j2 = i1 = i2 = 0 ;
97  iP1.set_i(0);
98  iP1.set_j(0);
99  iP2.set_i(0);
100  iP2.set_j(0);
101 
102  vpCDEBUG(1) << "end vpMeEllipse::vpMeEllipse() " << std::endl ;
103 }
104 
109  : vpMeTracker(meellipse), K(), iPc(), a(0.), b(0.), e(0.), iP1(), iP2(), alpha1(0), alpha2(2*M_PI),
110  ce(0.), se(0.), angle(), m00(0.), mu11(0.), mu20(0.), mu02(0.),
111  m10(0.), m01(0.), m11(0.), m02(0.), m20(0.),
112  thresholdWeight(0.2), expecteddensity(0.), circle(false)
113 {
114  K = meellipse.K;
115  iPc = meellipse.iPc;
116  a = meellipse.a;
117  b = meellipse.b;
118  e = meellipse.e;
119 
120  iP1 = meellipse.iP1;
121  iP2 = meellipse.iP2;
122  alpha1 = meellipse.alpha1;
123  alpha2 = meellipse.alpha2;
124  ce = meellipse.ce;
125  se = meellipse.se;
126 
127  angle = meellipse.angle;
128 
129  m00 = meellipse.m00;
130  mu11 = meellipse.mu11;
131  mu20 = meellipse.mu20;
132  mu02 = meellipse.mu02;
133  m10 = meellipse.m10;
134  m01 = meellipse.m01;
135  m11 = meellipse.m11;
136  m02 = meellipse.m02;
137  m20 = meellipse.m20;
138  thresholdWeight = meellipse.thresholdWeight;
139 
140  circle = meellipse.circle;
141  expecteddensity = meellipse.expecteddensity;
142 }
143 
148 {
149  vpCDEBUG(1) << "begin vpMeEllipse::~vpMeEllipse() " << std::endl ;
150 
151  list.clear();
152  angle.clear();
153 
154  vpCDEBUG(1) << "end vpMeEllipse::~vpMeEllipse() " << std::endl ;
155 }
156 
157 
168 void
169 vpMeEllipse::sample(const vpImage<unsigned char> & I)
170 {
171  vpCDEBUG(1) <<"begin vpMeEllipse::sample() : "<<std::endl ;
172 
173  if (!me) {
174  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
176  "Moving edges not initialized")) ;
177  }
178 
179  int height = (int)I.getHeight() ;
180  int width = (int)I.getWidth() ;
181 
182  double n_sample;
183 
184  //if (me->getSampleStep()==0)
185  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
186  {
187  std::cout << "In vpMeEllipse::sample: " ;
188  std::cout << "function called with sample step = 0" ;
189  //return fatalError ;
190  }
191 
192  double j, i;//, j11, i11;
193  vpImagePoint iP11;
194  j = i = 0.0 ;
195 
196  double incr = vpMath::rad(me->getSampleStep()) ; // angle increment en degree
197  vpColor col = vpColor::red ;
198  getParameters() ;
199 
200  // Delete old list
201  list.clear();
202 
203  angle.clear();
204 
205  // sample positions
206  double k = alpha1 ;
207  while (k<alpha2)
208  {
209 // j = a *cos(k) ; // equation of an ellipse
210 // i = b *sin(k) ; // equation of an ellipse
211 
212  j = a *sin(k) ; // equation of an ellipse
213  i = b *cos(k) ; // equation of an ellipse
214 
215  // (i,j) are the coordinates on the origin centered ellipse ;
216  // a rotation by "e" and a translation by (xci,jc) are done
217  // to get the coordinates of the point on the shifted ellipse
218 // iP11.set_j( iPc.get_j() + ce *j - se *i );
219 // iP11.set_i( iPc.get_i() -( se *j + ce *i) );
220 
221  iP11.set_j( iPc.get_j() + ce *j + se *i );
222  iP11.set_i( iPc.get_i() - se *j + ce *i );
223 
224  vpDisplay::displayCross(I, iP11, 5, col) ;
225 
226  double theta ;
227  computeTheta(theta, K, iP11) ;
228 
229  // If point is in the image, add to the sample list
230  if(!outOfImage(vpMath::round(iP11.get_i()), vpMath::round(iP11.get_j()), 0, height, width))
231  {
232  vpMeSite pix ;
233  pix.init((int)iP11.get_i(), (int)iP11.get_j(), theta) ;
236 
237  if(vpDEBUG_ENABLE(3))
238  {
240  }
241  list.push_back(pix);
242  angle.push_back(k);
243  }
244  k += incr ;
245 
246  }
248 
249  n_sample = (unsigned int)list.size() ;
250 
251  vpCDEBUG(1) << "end vpMeEllipse::sample() : " ;
252  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
253 }
254 
255 
270 void
271 vpMeEllipse::reSample(const vpImage<unsigned char> &I)
272 {
273  if (!me) {
274  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
276  "Moving edges not initialized")) ;
277  }
278 
279  unsigned int n = numberOfSignal() ;
281  if ((double)n<0.9*expecteddensity){
282  sample(I) ;
283  }
284 }
285 
286 
293 void
294 vpMeEllipse::getParameters()
295 {
296 
297  double k[6] ;
298  for (unsigned int i=0 ; i < 5 ; i++)
299  k[i+1] = K[i] ;
300  k[0] = 1 ;
301 
302  double d = k[2]*k[2] - k[0]*k[1];
303 
304  iPc.set_i( (k[1] * k[3] - k[2] * k[4]) / d );
305  iPc.set_j( (k[0] * k[4] - k[2] * k[3]) / d );
306 
307  double sq = sqrt(vpMath::sqr(k[1]-k[0]) + 4.0*vpMath::sqr(k[2])) ;
308  if (circle ==true)
309  {
310  e = 0 ;
311  }
312  else
313  {
314  e = (k[1] - k[0] + sq) / (2.0*k[2]);
315  e = (-1/e) ;
316 
317  e = atan(e) ;
318  }
319 
320  if(e < 0.0) e += M_PI ;
321 
322  ce = cos(e) ;
323  se = sin(e) ;
324 
325  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]) ;
326  double a2 = num / (k[0] + k[1] + sq ) ;
327  double b2 = num / (k[0] + k[1] - sq ) ;
328 
329  a = sqrt( a2 ) ;
330  b = sqrt( b2 ) ;
331 
332 }
333 
337 void
339 {
340  std::cout << "K" << std::endl ;
341  std::cout << K.t() ;
342  std::cout << iPc << std::endl ;
343 }
344 
353 void
354 vpMeEllipse::computeAngle(vpImagePoint pt1, vpImagePoint pt2)
355 {
356 
357  getParameters() ;
358  double j1, i1, j11, i11;
359  j1 = i1 = 0.0 ;
360 
361  int number_of_points = 2000 ;
362  double incr = 2 * M_PI / number_of_points ; // angle increment
363 
364  double dmin1 = 1e6 ;
365  double dmin2 = 1e6 ;
366 
367  double k = 0 ;
368  while(k < 2*M_PI) {
369 
370 // j1 = a *cos(k) ; // equation of an ellipse
371 // i1 = b *sin(k) ; // equation of an ellipse
372 
373  j1 = a *sin(k) ; // equation of an ellipse
374  i1 = b *cos(k) ; // equation of an ellipse
375 
376  // (i1,j1) are the coordinates on the origin centered ellipse ;
377  // a rotation by "e" and a translation by (xci,jc) are done
378  // to get the coordinates of the point on the shifted ellipse
379 // j11 = iPc.get_j() + ce *j1 - se *i1 ;
380 // i11 = iPc.get_i() -( se *j1 + ce *i1) ;
381 
382  j11 = iPc.get_j() + ce *j1 + se *i1 ;
383  i11 = iPc.get_i() - se *j1 + ce *i1 ;
384 
385  double d = vpMath::sqr(pt1.get_i()-i11) + vpMath::sqr(pt1.get_j()-j11) ;
386  if (d < dmin1)
387  {
388  dmin1 = d ;
389  alpha1 = k ;
390  }
391  d = vpMath::sqr(pt2.get_i()-i11) + vpMath::sqr(pt2.get_j()-j11) ;
392  if (d < dmin2)
393  {
394  dmin2 = d ;
395  alpha2 = k ;
396  }
397  k += incr ;
398  }
399  //std::cout << "end vpMeEllipse::computeAngle(..)" << alpha1 << " " << alpha2 << std::endl ;
400 
401  if (alpha2 < alpha1)
402  alpha2 += 2 * M_PI;
403  //else if (alpha2 == alpha1)
404  else if (std::fabs(alpha2 - alpha1) < std::fabs(alpha1) * std::numeric_limits<double>::epsilon())
405  alpha2 += 2 * M_PI;
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  std::cout << "vpMeEllipse::initTracking() ellipse avant: " << iPc << " " << a << " " << b << " " << vpMath::deg(e) << " alpha: " << alpha1 << " " << alpha2 << std::endl;
895 
896  computeAngle(iP1, iP2) ;
897  std::cout << "vpMeEllipse::initTracking() ellipse apres: " << iPc << " " << a << " " << b << " " << vpMath::deg(e) << " alpha: " << alpha1 << " " << alpha2 << std::endl;
898 
900 
901  display(I, vpColor::green) ;
902  sample(I) ;
903 
904  // 2. On appelle ce qui n'est pas specifique
905  {
907  }
908 
909  try{
910  track(I) ;
911  }
912  catch(...)
913  {
914  vpERROR_TRACE("Error caught") ;
915  throw ;
916  }
918  vpDisplay::flush(I) ;
919 
920 }
921 
922 void
923 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const vpImagePoint &ic, double a_p, double b_p, double e_p,
924  double low_alpha, double high_alpha)
925 {
926  iPc = ic;
927  a = a_p;
928  b = b_p;
929  e = e_p;
930  alpha1 = low_alpha;
931  alpha2 = high_alpha;
932 
933  if (alpha2 <alpha1)
934  alpha2 += 2 * M_PI;
935 
936  ce = cos(e);
937  se = sin(e);
938 
939 // vpDisplay::displayEllipse(I, iPc, a, b, e, 0, vpMath::rad(360), vpColor::red, 2); // TODO remove debug only
940  display(I, vpColor::green) ;
941 // vpDisplay::flush(I); // TODO remove debug only
942 // std::cout << "wait click" << std::endl;
943 // vpDisplay::getClick(I); // TODO remove debug only
944  sample(I) ;
945 
946  // 2. On appelle ce qui n'est pas specifique
947  {
949  }
950 
951  try{
952  track(I) ;
953  }
954  catch(...)
955  {
956  vpERROR_TRACE("Error caught") ;
957  throw ;
958  }
960  vpDisplay::flush(I) ;
961 }
962 
968 void
970 {
971  vpCDEBUG(1) <<"begin vpMeEllipse::track()"<<std::endl ;
972 
973  static int iter =0 ;
974  // 1. On fait ce qui concerne les ellipse (peut etre vide)
975  {
976  }
977 
978  //vpDisplay::display(I) ;
979  // 2. On appelle ce qui n'est pas specifique
980  {
981 
982  try{
983  vpMeTracker::track(I) ;
984  }
985  catch(...)
986  {
987  vpERROR_TRACE("Error caught") ;
988  throw ;
989  }
990  // std::cout << "number of signals " << numberOfSignal() << std::endl ;
991  }
992 
993  // 3. On revient aux ellipses
994  {
995  // Estimation des parametres de la droite aux moindres carre
996  suppressPoints() ;
997  setExtremities() ;
998 
999 
1000  try{
1001  leastSquare() ; }
1002  catch(...)
1003  {
1004  vpERROR_TRACE("Error caught") ;
1005  throw ;
1006  }
1007 
1008  seekExtremities(I) ;
1009 
1010  setExtremities() ;
1011 
1012  try
1013  {
1014  leastSquare() ;
1015  }
1016  catch(...)
1017  {
1018  vpERROR_TRACE("Error caught") ;
1019  throw ;
1020  }
1021 
1022  // suppression des points rejetes par la regression robuste
1023  suppressPoints() ;
1024  setExtremities() ;
1025 
1026  //reechantillonage si necessaire
1027  reSample(I) ;
1028 
1029  // remet a jour l'angle delta pour chaque point de la liste
1030 
1031  updateTheta() ;
1032 
1033  computeMoments();
1034 
1035  // Remise a jour de delta dans la liste de site me
1036  if (vpDEBUG_ENABLE(2))
1037  {
1038  display(I,vpColor::red) ;
1040  vpDisplay::flush(I) ;
1041  }
1042 // computeAngle(iP1, iP2) ;
1043 //
1044 // if (iter%5==0)
1045 // {
1046 // sample(I) ;
1047 // try{
1048 // leastSquare() ; }
1049 // catch(...)
1050 // {
1051 // vpERROR_TRACE("Error caught") ;
1052 // throw ;
1053 // }
1054 // computeAngle(iP1, iP2) ;
1055 // }
1056 // seekExtremities(I) ;
1057 //
1058 // vpMeTracker::display(I) ;
1059 // // vpDisplay::flush(I) ;
1060 //
1061 // // remet a jour l'angle theta pour chaque point de la liste
1062 // updateTheta() ;
1063 
1064  }
1065 
1066  iter++ ;
1067 
1068 
1069  vpCDEBUG(1) << "end vpMeEllipse::track()"<<std::endl ;
1070 
1071 }
1072 
1073 
1079 void
1080 vpMeEllipse::computeMoments()
1081 {
1082  double tane = tan(-1/e);
1083  m00 = M_PI*a*b;
1084  m10 = m00*iPc.get_i();
1085  m01 = m00*iPc.get_j();
1086  m20 = m00*(a*a+b*b*tane*tane)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_i();
1087  m02 = m00*(a*a*tane*tane+b*b)/(4*(1+tane*tane))+m00*iPc.get_j()*iPc.get_j();
1088  m11 = m00*tane*(a*a-b*b)/(4*(1+tane*tane))+m00*iPc.get_i()*iPc.get_j();
1089  mu11 = m11 - iPc.get_j()*m10;
1090  mu02 = m02 - iPc.get_j()*m01;
1091  mu20 = m20 - iPc.get_i()*m10;
1092 }
1093 
1094 
1095 
1096 
1097 
1098 
1099 
1100 
1101 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
1102 
1106 void
1107 vpMeEllipse::computeAngle(int ip1, int jp1, double &_alpha1,
1108  int ip2, int jp2, double &_alpha2)
1109 {
1110 
1111  getParameters() ;
1112  double j1, i1, j11, i11;
1113  j1 = i1 = 0.0 ;
1114 
1115  int number_of_points = 2000 ;
1116  double incr = 2 * M_PI / number_of_points ; // angle increment
1117 
1118  double dmin1 = 1e6 ;
1119  double dmin2 = 1e6 ;
1120 
1121  double k = -M_PI ;
1122  while(k < M_PI) {
1123 
1124  j1 = a *cos(k) ; // equation of an ellipse
1125  i1 = b *sin(k) ; // equation of an ellipse
1126 
1127  // (i1,j1) are the coordinates on the origin centered ellipse ;
1128  // a rotation by "e" and a translation by (xci,jc) are done
1129  // to get the coordinates of the point on the shifted ellipse
1130  j11 = iPc.get_j() + ce *j1 - se *i1 ;
1131  i11 = iPc.get_i() -( se *j1 + ce *i1) ;
1132 
1133  double d = vpMath::sqr(ip1-i11) + vpMath::sqr(jp1-j11) ;
1134  if (d < dmin1)
1135  {
1136  dmin1 = d ;
1137  alpha1 = k ;
1138  _alpha1 = k ;
1139  }
1140  d = vpMath::sqr(ip2-i11) + vpMath::sqr(jp2-j11) ;
1141  if (d < dmin2)
1142  {
1143  dmin2 = d ;
1144  alpha2 = k ;
1145  _alpha2 = k ;
1146  }
1147  k += incr ;
1148  }
1149 
1150  if (alpha2 <alpha1) alpha2 += 2*M_PI ;
1151 
1152  vpCDEBUG(1) << "end vpMeEllipse::computeAngle(..)" << alpha1 << " " << alpha2 << std::endl ;
1153 
1154 }
1155 
1156 
1160 void
1161 vpMeEllipse::computeAngle(int ip1, int jp1, int ip2, int jp2)
1162 {
1163 
1164  double a1, a2 ;
1165  computeAngle(ip1,jp1,a1, ip2, jp2,a2) ;
1166 }
1167 
1168 
1169 void
1170 vpMeEllipse::initTracking(const vpImage<unsigned char> &I, const unsigned int n,
1171  unsigned *i, unsigned *j)
1172 {
1173  vpCDEBUG(1) <<" begin vpMeEllipse::initTracking()"<<std::endl ;
1174 
1175  if (circle==false)
1176  {
1177  vpMatrix A(n,5) ;
1178  vpColVector b_(n) ;
1179  vpColVector x(5) ;
1180 
1181  // Construction du systeme Ax=b
1183  // A = (j^2 2ij 2i 2j 1) x = (K0 K1 K2 K3 K4)^T b = (-i^2 )
1184 
1185  for (unsigned int k =0 ; k < n ; k++)
1186  {
1187  A[k][0] = vpMath::sqr(j[k]) ;
1188  A[k][1] = 2* i[k] * j[k] ;
1189  A[k][2] = 2* i[k] ;
1190  A[k][3] = 2* j[k] ;
1191  A[k][4] = 1 ;
1192 
1193  b_[k] = - vpMath::sqr(i[k]) ;
1194  }
1195 
1196  K = A.pseudoInverse(1e-26)*b_ ;
1197  std::cout << K << std::endl;
1198  }
1199  else
1200  {
1201  vpMatrix A(n,3) ;
1202  vpColVector b_(n) ;
1203  vpColVector x(3) ;
1204 
1205  vpColVector Kc(3) ;
1206  for (unsigned int k =0 ; k < n ; k++)
1207  {
1208  A[k][0] = 2* i[k] ;
1209  A[k][1] = 2* j[k] ;
1210 
1211  A[k][2] = 1 ;
1212  b_[k] = - vpMath::sqr(i[k]) - vpMath::sqr(j[k]) ;
1213  }
1214 
1215  Kc = A.pseudoInverse(1e-26)*b_ ;
1216  K[0] = 1 ;
1217  K[1] = 0 ;
1218  K[2] = Kc[0] ;
1219  K[3] = Kc[1] ;
1220  K[4] = Kc[2] ;
1221 
1222  std::cout << K << std::endl;
1223  }
1224  iP1.set_i( i[0] );
1225  iP1.set_j( j[0] );
1226  iP2.set_i( i[n-1] );
1227  iP2.set_j( j[n-1] );
1228 
1229  getParameters() ;
1230  computeAngle(iP1, iP2) ;
1231  display(I, vpColor::green) ;
1232 
1233  sample(I) ;
1234 
1235  // 2. On appelle ce qui n'est pas specifique
1236  {
1238  }
1239 
1240  try{
1241  track(I) ;
1242  }
1243  catch(...)
1244  {
1245  vpERROR_TRACE("Error caught") ;
1246  throw ;
1247  }
1249  vpDisplay::flush(I) ;
1250 
1251 }
1252 #endif // Deprecated
1253 
1277  const double &A, const double &B, const double &E,
1278  const double & smallalpha, const double &highalpha,
1279  const vpColor &color, unsigned int thickness)
1280 {
1281  double j1, i1;
1282  vpImagePoint iP11;
1283  double j2, i2;
1284  vpImagePoint iP22;
1285  j1 = j2 = i1 = i2 = 0 ;
1286 
1287  double incr = vpMath::rad(2) ; // angle increment
1288 
1289  vpDisplay::displayCross(I,center,20, vpColor::red, thickness) ;
1290 
1291  double k = smallalpha ;
1292  while (k+incr<highalpha)
1293  {
1294  j1 = A *cos(k) ; // equation of an ellipse
1295  i1 = B *sin(k) ; // equation of an ellipse
1296 
1297  j2 = A *cos(k+incr) ; // equation of an ellipse
1298  i2 = B *sin(k+incr) ; // equation of an ellipse
1299 
1300  // (i1,j1) are the coordinates on the origin centered ellipse ;
1301  // a rotation by "e" and a translation by (xci,jc) are done
1302  // to get the coordinates of the point on the shifted ellipse
1303  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1304  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1305  // to get the coordinates of the point on the shifted ellipse
1306  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1307  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1308 
1309  vpDisplay::displayLine(I, iP11, iP22, color, thickness) ;
1310 
1311  k += incr ;
1312  }
1313 
1314  j1 = A *cos(smallalpha) ; // equation of an ellipse
1315  i1 = B *sin(smallalpha) ; // equation of an ellipse
1316 
1317  j2 = A *cos(highalpha) ; // equation of an ellipse
1318  i2 = B *sin(highalpha) ; // equation of an ellipse
1319 
1320  // (i1,j1) are the coordinates on the origin centered ellipse ;
1321  // a rotation by "e" and a translation by (xci,jc) are done
1322  // to get the coordinates of the point on the shifted ellipse
1323  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1324  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1325  // to get the coordinates of the point on the shifted ellipse
1326  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1327  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1328 
1329  vpDisplay::displayLine(I, center, iP11, vpColor::red, thickness) ;
1330  vpDisplay::displayLine(I, center, iP22, vpColor::blue, thickness) ;
1331 }
1332 
1356  const double &A, const double &B, const double &E,
1357  const double & smallalpha, const double &highalpha,
1358  const vpColor &color, unsigned int thickness)
1359 {
1360  double j1, i1;
1361  vpImagePoint iP11;
1362  double j2, i2;
1363  vpImagePoint iP22;
1364  j1 = j2 = i1 = i2 = 0 ;
1365 
1366  double incr = vpMath::rad(2) ; // angle increment
1367 
1368  vpDisplay::displayCross(I,center,20, vpColor::red, thickness) ;
1369 
1370  double k = smallalpha ;
1371  while (k+incr<highalpha)
1372  {
1373  j1 = A *cos(k) ; // equation of an ellipse
1374  i1 = B *sin(k) ; // equation of an ellipse
1375 
1376  j2 = A *cos(k+incr) ; // equation of an ellipse
1377  i2 = B *sin(k+incr) ; // equation of an ellipse
1378 
1379  // (i1,j1) are the coordinates on the origin centered ellipse ;
1380  // a rotation by "e" and a translation by (xci,jc) are done
1381  // to get the coordinates of the point on the shifted ellipse
1382  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1383  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1384  // to get the coordinates of the point on the shifted ellipse
1385  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1386  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1387 
1388  vpDisplay::displayLine(I, iP11, iP22, color, thickness) ;
1389 
1390  k += incr ;
1391  }
1392 
1393  j1 = A *cos(smallalpha) ; // equation of an ellipse
1394  i1 = B *sin(smallalpha) ; // equation of an ellipse
1395 
1396  j2 = A *cos(highalpha) ; // equation of an ellipse
1397  i2 = B *sin(highalpha) ; // equation of an ellipse
1398 
1399  // (i1,j1) are the coordinates on the origin centered ellipse ;
1400  // a rotation by "e" and a translation by (xci,jc) are done
1401  // to get the coordinates of the point on the shifted ellipse
1402  iP11.set_j ( center.get_j() + cos(E) *j1 - sin(E) *i1 );
1403  iP11.set_i ( center.get_i() -( sin(E) *j1 + cos(E) *i1) );
1404  // to get the coordinates of the point on the shifted ellipse
1405  iP22.set_j ( center.get_j() + cos(E) *j2 - sin(E) *i2 );
1406  iP22.set_i ( center.get_i() -( sin(E) *j2 + cos(E) *i2) );
1407 
1408  vpDisplay::displayLine(I, center, iP11, vpColor::red, thickness) ;
1409  vpDisplay::displayLine(I, center, iP22, vpColor::blue, thickness) ;
1410 }
double a
is the semiminor axis of the ellipse.
Definition: vpMeEllipse.h:318
unsigned int getRange() const
Definition: vpMe.h:236
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
double m01
Definition: vpMeEllipse.h:344
double expecteddensity
Expected number of me to track along the ellipse.
Definition: vpMeEllipse.h:350
double e
is the angle made by the major axis and the i axis of the image frame .
Definition: vpMeEllipse.h:322
void initTracking(const vpImage< unsigned char > &I)
double mu02
Definition: vpMeEllipse.h:342
void init()
Definition: vpMeSite.cpp:73
double get_i() const
Definition: vpImagePoint.h:195
unsigned int getWidth() const
Definition: vpImage.h:161
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:348
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:326
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:342
static const vpColor green
Definition: vpColor.h:170
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2232
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:206
double b
is the semimajor axis of the ellipse.
Definition: vpMeEllipse.h:320
double se
Value of sin(e).
Definition: vpMeEllipse.h:336
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:346
void set_i(const double ii)
Definition: vpImagePoint.h:159
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:328
vpImagePoint iPc
The coordinates of the ellipse center.
Definition: vpMeEllipse.h:316
double m11
Second order raw moments.
Definition: vpMeEllipse.h:346
double alpha1
The smallest angle.
Definition: vpMeEllipse.h:330
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:342
double m10
First order raw moments.
Definition: vpMeEllipse.h:344
Contains abstract elements for a Distance to Feature type feature.
Definition: vpMeTracker.h:71
vpColVector K
Definition: vpMeEllipse.h:314
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:189
double m00
Surface.
Definition: vpMeEllipse.h:340
#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:338
void set_j(const double jj)
Definition: vpImagePoint.h:170
void setMu2(const double &mu_2)
Definition: vpMe.h:185
double getMu2() const
Definition: vpMe.h:192
int j
Definition: vpMeSite.h:98
static double deg(double rad)
Definition: vpMath.h:93
double m02
Definition: vpMeEllipse.h:346
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:152
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1932
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:93
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:332
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:334
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:181
static const vpColor blue
Definition: vpColor.h:173