ViSP  2.6.2
vpMeLine.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMeLine.cpp 3672 2012-04-04 15:49:57Z ayol $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 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 
50 #include <visp/vpMeTracker.h>
51 #include <visp/vpMe.h>
52 #include <visp/vpMeSite.h>
53 #include <visp/vpMeLine.h>
54 #include <visp/vpRobust.h>
55 #include <visp/vpTrackingException.h>
56 #include <visp/vpImagePoint.h>
57 #include <visp/vpMath.h>
58 #include <stdlib.h>
59 #include <cmath> // std::fabs
60 #include <limits> // numeric_limits
61 #define INCR_MIN 1
62 
63 static void
64 normalizeAngle(double &delta)
65 {
66  while (delta > M_PI) { delta -= M_PI ; }
67  while (delta < -M_PI) { delta += M_PI ; }
68 }
69 
70 void
71 computeDelta(double &delta, int i1, int j1, int i2, int j2)
72 {
73 
74  double B = double(i1-i2) ;
75  double A = double(j1-j2) ;
76 
77  delta = atan2(B,A) ;
78  delta -= M_PI/2.0 ;
79  normalizeAngle(delta) ;
80 
81 }
82 
83 static void
84 project(double a, double b, double c,
85  double i, double j, double &ip,double &jp)
86 {
87  if (fabs(a)>fabs(b))
88  {
89  jp = (vpMath::sqr(a)*j - a*b*i - c*b)/(vpMath::sqr(a)+vpMath::sqr(b)) ;
90  ip = (-c-b*jp)/a;
91  }
92  else
93  {
94  ip = (vpMath::sqr(b)*i-a*b*j-c*a)/(vpMath::sqr(a)+vpMath::sqr(b)) ;
95  jp = (-c-a*ip)/b;
96  }
97 }
98 
105 {
106  sign = 1;
107  angle_1 = 90;
108  _useIntensityForRho = true;
109 }
116 {
117  rho = meline.rho;
118  theta = meline.theta;
119  delta = meline.delta;
120  delta_1 = meline.delta_1;
121  angle = meline.angle;
122  angle_1 = meline.angle_1;
123  sign = meline.sign;
124 
125  a = meline.a;
126  b = meline.b;
127  c = meline.c;
129  PExt[0] = meline.PExt[0];
130  PExt[1] = meline.PExt[1];
131 }
132 
139 {
140  list.clear();
141 }
142 
150 void
152 {
153  int rows = (int)I.getHeight() ;
154  int cols = (int)I.getWidth() ;
155  double n_sample;
156 
157  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
158  {
159  vpERROR_TRACE("function called with sample step = 0") ;
161  "sample step = 0")) ;
162  }
163 
164  // i, j portions of the line_p
165  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
166  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
167 
168  double length_p = sqrt((vpMath::sqr(diffsi)+vpMath::sqr(diffsj)));
169  if(std::fabs(length_p)<=std::numeric_limits<double>::epsilon())
170  throw(vpTrackingException(vpTrackingException::fatalError,"points too close of each other to define a line")) ;
171  // number of samples along line_p
172  n_sample = length_p/(double)me->getSampleStep();
173 
174  double stepi = diffsi/(double)n_sample;
175  double stepj = diffsj/(double)n_sample;
176 
177  // Choose starting point
178  double is = PExt[1].ifloat;
179  double js = PExt[1].jfloat;
180 
181  // Delete old list
182  list.clear();
183 
184  // sample positions at i*me->getSampleStep() interval along the
185  // line_p, starting at PSiteExt[0]
186 
187  vpImagePoint ip;
188  for(int i=0; i<=vpMath::round(n_sample); i++)
189  {
190  // If point is in the image, add to the sample list
191  if(!outOfImage(vpMath::round(is), vpMath::round(js), 0, rows, cols))
192  {
193  vpMeSite pix ; //= list.value();
194  pix.init((int)is, (int)js, delta, 0, sign) ;
196 
197  if(vpDEBUG_ENABLE(3))
198  {
199  ip.set_i( is );
200  ip.set_j( js );
202  }
203 
204  list.push_back(pix);
205  }
206  is += stepi;
207  js += stepj;
208 
209  }
210 
211  vpCDEBUG(1) << "end vpMeLine::sample() : ";
212  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
213 }
214 
215 
228 void
230 {
231  vpMeLine::display(I,PExt[0],PExt[1],list,a,b,c,col);
232 }
233 
234 
242 void
244 {
245  vpImagePoint ip1, ip2;
246 
247  std::cout << "Click on the line first point..." <<std::endl ;
248  while (vpDisplay::getClick(I, ip1)!=true) ;
249  std::cout << "Click on the line second point..." <<std::endl ;
250  while (vpDisplay::getClick(I, ip2)!=true) ;
251 
252  try
253  {
254  initTracking(I, ip1, ip2) ;
255  }
256  catch(...)
257  {
258  vpERROR_TRACE("Error caught") ;
259  throw ;
260  }
261 
262 }
263 
264 
271 void
273 {
274  vpMatrix A(numberOfSignal(),2) ;
275  vpColVector x(2), x_1(2) ;
276  x_1 = 0;
277 
278  unsigned int i ;
279 
280  vpRobust r(numberOfSignal()) ;
281  r.setThreshold(2);
282  r.setIteration(0) ;
284  D.setIdentity() ;
285  vpMatrix DA, DAmemory ;
286  vpColVector DAx ;
289  w =1 ;
290  vpMeSite p ;
291  unsigned int iter =0 ;
292  unsigned int nos_1 = 0 ;
293  double distance = 100;
294 
295  if (list.size() <= 2 || numberOfSignal() <= 2)
296  {
297  //vpERROR_TRACE("Not enough point") ;
298  vpCDEBUG(1) << "Not enough point";
300  "not enough point")) ;
301  }
302 
303  if ((fabs(b) >=0.9)) // Construction du systeme Ax=B
304  // a i + j + c = 0
305  // A = (i 1) B = (-j)
306  {
307  nos_1 = numberOfSignal() ;
308  unsigned int k =0 ;
309  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
310  p = *it;
312  {
313  A[k][0] = p.ifloat ;
314  A[k][1] = 1 ;
315  B[k] = -p.jfloat ;
316  k++ ;
317  }
318  }
319 
320  while (iter < 4 && distance > 0.05)
321  {
322  DA = D*A ;
323  x = DA.pseudoInverse(1e-26) *D*B ;
324 
325  vpColVector residu(nos_1);
326  residu = B - A*x;
327  r.setIteration(iter) ;
328  r.MEstimator(vpRobust::TUKEY,residu,w) ;
329 
330  k = 0;
331  for (i=0 ; i < nos_1 ; i++)
332  {
333  D[k][k] =w[k] ;
334  k++;
335  }
336  iter++ ;
337  distance = fabs(x[0]-x_1[0])+fabs(x[1]-x_1[1]);
338  x_1 = x;
339  }
340 
341  k =0 ;
342  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
343  p = *it;
345  {
346  if (w[k] < 0.2)
347  {
349 
350  *it = p;
351  }
352  k++ ;
353  }
354  }
355 
356  // mise a jour de l'equation de la droite
357  a = x[0] ;
358  b = 1 ;
359  c = x[1] ;
360 
361  double s =sqrt( vpMath::sqr(a)+vpMath::sqr(b)) ;
362  a /= s ;
363  b /= s ;
364  c /= s ;
365  }
366 
367 
368  else // Construction du systeme Ax=B
369  // i + bj + c = 0
370  // A = (j 1) B = (-i)
371  {
372  nos_1 = numberOfSignal() ;
373  unsigned int k =0 ;
374  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
375  p = *it;
377  {
378  A[k][0] = p.jfloat ;
379  A[k][1] = 1 ;
380  B[k] = -p.ifloat ;
381  k++ ;
382  }
383  }
384 
385  while (iter < 4 && distance > 0.05)
386  {
387  DA = D*A ;
388  x = DA.pseudoInverse(1e-26) *D*B ;
389 
390  vpColVector residu(nos_1);
391  residu = B - A*x;
392  r.setIteration(iter) ;
393  r.MEstimator(vpRobust::TUKEY,residu,w) ;
394 
395  k = 0;
396  for (i=0 ; i < nos_1 ; i++)
397  {
398  D[k][k] =w[k] ;
399  k++;
400  }
401  iter++ ;
402  distance = fabs(x[0]-x_1[0])+fabs(x[1]-x_1[1]);
403  x_1 = x;
404  }
405 
406 
407  k =0 ;
408  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
409  p = *it;
411  {
412  if (w[k] < 0.2)
413  {
415 
416  *it = p;
417  }
418  k++ ;
419  }
420  }
421  a = 1 ;
422  b = x[0] ;
423  c = x[1] ;
424 
425  double s = sqrt(vpMath::sqr(a)+vpMath::sqr(b)) ;
426  a /= s ;
427  b /= s ;
428  c /= s ;
429  }
430 
431  // mise a jour du delta
432  delta = atan2(a,b) ;
433 
434  normalizeAngle(delta) ;
435 }
436 
437 
438 
448 void
450  const vpImagePoint &ip1,
451  const vpImagePoint &ip2)
452 {
453  vpCDEBUG(1) <<" begin vpMeLine::initTracking()"<<std::endl ;
454 
455  int i1s, j1s, i2s, j2s;
456 
457  i1s = vpMath::round( ip1.get_i() );
458  i2s = vpMath::round( ip2.get_i() );
459  j1s = vpMath::round( ip1.get_j() );
460  j2s = vpMath::round( ip2.get_j() );
461 
462  try{
463 
464  // 1. On fait ce qui concerne les droites (peut etre vide)
465  {
466  // Points extremites
467  PExt[0].ifloat = (float)ip1.get_i() ;
468  PExt[0].jfloat = (float)ip1.get_j() ;
469  PExt[1].ifloat = (float)ip2.get_i() ;
470  PExt[1].jfloat = (float)ip2.get_j() ;
471 
472  double angle = atan2((double)(i1s-i2s),(double)(j1s-j2s)) ;
473  a = cos(angle) ;
474  b = sin(angle) ;
475 
476  // Real values of a, b can have an other sign. So to get the good values
477  // of a and b in order to initialise then c, we call track(I) just below
478 
479  computeDelta(delta,i1s,j1s,i2s,j2s) ;
480  delta_1 = delta;
481 
482  // vpTRACE("a: %f b: %f c: %f -b/a: %f delta: %f", a, b, c, -(b/a), delta);
483 
484  sample(I) ;
485 
486  }
487  // 2. On appelle ce qui n'est pas specifique
488  {
490  }
491  // Call track(I) to give the good sign to a and b and to initialise c which can be used for the display
492  track(I);
493  }
494  catch(...)
495  {
496  vpERROR_TRACE("Error caught") ;
497  throw ;
498  }
499  vpCDEBUG(1) <<" end vpMeLine::initTracking()"<<std::endl ;
500 }
501 
502 
506 void
508 {
509  // Loop through list of sites to track
510  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ){
511  vpMeSite s = *it;//current reference pixel
512 
514  it = list.erase(it);
515  else
516  ++it;
517  }
518 }
519 
520 
524 void
526 {
527  double imin = +1e6 ;
528  double jmin = +1e6;
529  double imax = -1 ;
530  double jmax = -1 ;
531 
532 
533  // Loop through list of sites to track
534  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
535  vpMeSite s = *it;//current reference pixel
536  if (s.ifloat < imin)
537  {
538  imin = s.ifloat ;
539  jmin = s.jfloat ;
540  }
541 
542  if (s.ifloat > imax)
543  {
544  imax = s.ifloat ;
545  jmax = s.jfloat ;
546  }
547  }
548 
549  PExt[0].ifloat = imin ;
550  PExt[0].jfloat = jmin ;
551  PExt[1].ifloat = imax ;
552  PExt[1].jfloat = jmax ;
553 
554  if (fabs(imin-imax) < 25)
555  {
556  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
557  vpMeSite s = *it;//current reference pixel
558  if (s.jfloat < jmin)
559  {
560  imin = s.ifloat ;
561  jmin = s.jfloat ;
562  }
563 
564  if (s.jfloat > jmax)
565  {
566  imax = s.ifloat ;
567  jmax = s.jfloat ;
568  }
569  }
570  PExt[0].ifloat = imin ;
571  PExt[0].jfloat = jmin ;
572  PExt[1].ifloat = imax ;
573  PExt[1].jfloat = jmax ;
574  }
575 }
576 
585 void
587 {
588  vpCDEBUG(1) <<"begin vpMeLine::sample() : "<<std::endl ;
589 
590  int rows = (int)I.getHeight() ;
591  int cols = (int)I.getWidth() ;
592  double n_sample;
593 
594  //if (me->getSampleStep()==0)
595  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
596  {
597 
598  vpERROR_TRACE("function called with sample step = 0") ;
600  "sample step = 0")) ;
601  }
602 
603  // i, j portions of the line_p
604  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
605  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
606 
607  double s = vpMath::sqr(diffsi)+vpMath::sqr(diffsj) ;
608 
609  double di = diffsi/sqrt(s) ; // pas de risque de /0 car d(P1,P2) >0
610  double dj = diffsj/sqrt(s) ;
611 
612  double length_p = sqrt((vpMath::sqr(diffsi)+vpMath::sqr(diffsj)));
613 
614  // number of samples along line_p
615  n_sample = length_p/(double)me->getSampleStep();
616  double sample = (double)me->getSampleStep();
617 
618  vpMeSite P ;
619  P.init((int) PExt[0].ifloat, (int)PExt[0].jfloat, delta_1, 0, sign) ;
621 
622  unsigned int memory_range = me->getRange() ;
623  me->setRange(1);
624 
625  vpImagePoint ip;
626 
627  for (int i=0 ; i < 3 ; i++)
628  {
629  P.ifloat = P.ifloat + di*sample ; P.i = (int)P.ifloat ;
630  P.jfloat = P.jfloat + dj*sample ; P.j = (int)P.jfloat ;
631 
632  if(!outOfImage(P.i, P.j, 5, rows, cols))
633  {
634  P.track(I,me,false) ;
635 
637  {
638  list.push_back(P);
639  if (vpDEBUG_ENABLE(3)) {
640  ip.set_i( P.i );
641  ip.set_j( P.j );
642 
644  }
645  }
646  else {
647  if (vpDEBUG_ENABLE(3)) {
648  ip.set_i( P.i );
649  ip.set_j( P.j );
651  }
652  }
653  }
654  }
655 
656  P.init((int) PExt[1].ifloat, (int)PExt[1].jfloat, delta_1, 0, sign) ;
658  for (int i=0 ; i < 3 ; i++)
659  {
660  P.ifloat = P.ifloat - di*sample ; P.i = (int)P.ifloat ;
661  P.jfloat = P.jfloat - dj*sample ; P.j = (int)P.jfloat ;
662 
663  if(!outOfImage(P.i, P.j, 5, rows, cols))
664  {
665  P.track(I,me,false) ;
666 
668  {
669  list.push_back(P);
670  if (vpDEBUG_ENABLE(3)) {
671  ip.set_i( P.i );
672  ip.set_j( P.j );
674  }
675  }
676  else {
677  if (vpDEBUG_ENABLE(3)) {
678  ip.set_i( P.i );
679  ip.set_j( P.j );
681  }
682  }
683  }
684  }
685 
686  me->setRange(memory_range);
687 
688  vpCDEBUG(1) <<"end vpMeLine::sample() : " ;
689  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
690 }
691 
692 
704 void
706 {
707 
708  double i1,j1,i2,j2 ;
709 
710  project(a,b,c,PExt[0].ifloat,PExt[0].jfloat,i1,j1) ;
711  project(a,b,c,PExt[1].ifloat,PExt[1].jfloat,i2,j2) ;
712 
713  // Points extremites
714  PExt[0].ifloat = i1 ;
715  PExt[0].jfloat = j1 ;
716  PExt[1].ifloat = i2 ;
717  PExt[1].jfloat = j2 ;
718 
719  double d = sqrt(vpMath::sqr(i1-i2)+vpMath::sqr(j1-j2)) ;
720 
721  unsigned int n = numberOfSignal() ;
722  double expecteddensity = d / (double)me->getSampleStep();
723 
724  if ((double)n<0.9*expecteddensity)
725  {
726  double delta_new = delta;
727  delta = delta_1;
728  sample(I) ;
729  delta = delta_new;
730  // 2. On appelle ce qui n'est pas specifique
731  {
733  }
734  }
735 }
736 
741 void
743 {
744  vpMeSite p ;
745 
746  double angle = delta + M_PI/2;
747  double diff = 0;
748 
749  while (angle<0) angle += M_PI;
750  while (angle>M_PI) angle -= M_PI;
751 
752  angle = vpMath::round(angle * 180 / M_PI) ;
753 
754  //if(fabs(angle) == 180 )
755  if(std::fabs(std::fabs(angle) - 180) <= std::numeric_limits<double>::epsilon())
756  {
757  angle= 0 ;
758  }
759 
760  //std::cout << "angle theta : " << theta << std::endl ;
761  diff = fabs(angle - angle_1);
762  if (diff > 90)
763  sign *= -1;
764 
765  angle_1 = angle;
766 
767  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
768  p = *it;
769  p.alpha = delta ;
770  p.mask_sign = sign;
771  *it = p;
772  }
773  delta_1 = delta;
774 }
775 
776 
783 void
785 {
786  vpCDEBUG(1) <<"begin vpMeLine::track()"<<std::endl ;
787 
788  // 1. On fait ce qui concerne les droites (peut etre vide)
789  {
790  }
791  // 2. On appelle ce qui n'est pas specifique
792  {
793  vpMeTracker::track(I) ;
794  }
795 
796  // 3. On revient aux droites
797  {
798  // supression des points rejetes par les ME
799  suppressPoints() ;
800  setExtremities() ;
801 
802 
803  // Estimation des parametres de la droite aux moindres carre
804  try
805  {
806  leastSquare() ;
807  }
808  catch(...)
809  {
810  vpERROR_TRACE("Error caught") ;
811  throw ;
812  }
813 
814 
815  // recherche de point aux extremite de la droites
816  // dans le cas d'un glissement
817  seekExtremities(I) ;
818 
819  setExtremities() ;
820  try
821  {
822  leastSquare() ;
823  }
824  catch(...)
825  {
826  vpERROR_TRACE("Error caught") ;
827  throw ;
828  }
829 
830  // suppression des points rejetes par la regression robuste
831  suppressPoints() ;
832  setExtremities() ;
833 
834  //reechantillonage si necessaire
835  reSample(I) ;
836 
837  // remet a jour l'angle delta pour chaque point de la liste
838 
839  updateDelta() ;
840 
841  // Remise a jour de delta dans la liste de site me
842  if (vpDEBUG_ENABLE(2))
843  {
844  display(I,vpColor::red) ;
846  vpDisplay::flush(I) ;
847  }
848 
849 
850  }
851 
852  computeRhoTheta(I) ;
853 
854  vpCDEBUG(1) <<"end vpMeLine::track()"<<std::endl ;
855 }
856 
857 void vpMeLine::update_indices(double theta,int i,int j,int incr,int& i1,int& i2,int& j1,int& j2){
858  i1 = (int)(i + cos(theta) *incr) ;
859  j1 = (int)(j + sin(theta) *incr) ;
860 
861  i2 = (int)(i - cos(theta) *incr) ;
862  j2 = (int)(j - sin(theta) *incr) ;
863 }
864 
871 void
873 {
874  //rho = -c ;
875  //theta = atan2(a,b) ;
876  rho = fabs(c);
877  theta = atan2(b,a) ;
878 
879  while (theta >= M_PI) theta -=M_PI ;
880  while (theta < 0) theta +=M_PI ;
881 
883 
884  /* while(theta < -M_PI) theta += 2*M_PI ;
885  while(theta >= M_PI) theta -= 2*M_PI ;
886 
887  // If theta is between -90 and -180 get the equivalent
888  // between 0 and 90
889  if(theta <-M_PI/2)
890  {
891  theta += M_PI ;
892  rho *= -1 ;
893  }
894  // If theta is between 90 and 180 get the equivalent
895  // between 0 and -90
896  if(theta >M_PI/2)
897  {
898  theta -= M_PI ;
899  rho *= -1 ;
900  }
901  */
902  // convention pour choisir le signe de rho
903  int i,j ;
904  i = vpMath::round((PExt[0].ifloat + PExt[1].ifloat )/2) ;
905  j = vpMath::round((PExt[0].jfloat + PExt[1].jfloat )/2) ;
906 
907  int end = false ;
908  int incr = 10 ;
909 
910 
911  int i1=0,i2=0,j1=0,j2=0 ;
912  unsigned char v1=0,v2=0 ;
913 
914  int width_ = (int)I.getWidth();
915  int height_ = (int)I.getHeight();
916  update_indices(theta,i,j,incr,i1,i2,j1,j2);
917 
918  if(i1<0 || i1>=height_ || i2<0 || i2>=height_ ||
919  j1<0 || j1>=width_ || j2<0 || j2>=width_){
920  double rho_lim1 = fabs((double)i/cos(theta));
921  double rho_lim2 = fabs((double)j/sin(theta));
922 
923  double co_rho_lim1 = fabs(((double)(height_-i))/cos(theta));
924  double co_rho_lim2 = fabs(((double)(width_-j))/sin(theta));
925 
926  double rho_lim = std::min(rho_lim1,rho_lim2);
927  double co_rho_lim = std::min(co_rho_lim1,co_rho_lim2);
928  incr = (int)std::floor(std::min(rho_lim,co_rho_lim));
929  if(incr<INCR_MIN){
930  vpERROR_TRACE("increment is too small") ;
932  "increment is too small")) ;
933  }
934  update_indices(theta,i,j,incr,i1,i2,j1,j2);
935  }
936 
937  while (!end)
938  {
939  end = true;
940  unsigned int i1_ = static_cast<unsigned int>(i1);
941  unsigned int j1_ = static_cast<unsigned int>(j1);
942  unsigned int i2_ = static_cast<unsigned int>(i2);
943  unsigned int j2_ = static_cast<unsigned int>(j2);
944  v1=I[i1_][j1_];
945  v2=I[i2_][j2_];
946  if (abs(v1-v2) < 1)
947  {
948 
949  incr-- ;
950  end = false ;
951  if (incr==1)
952  {
953  std::cout << "In CStraightLine::GetParameters() " ;
954  std::cout << " Error Tracking " << abs(v1-v2) << std::endl ;
955  }
956  }
957  update_indices(theta,i,j,incr,i1,i2,j1,j2);
958  }
959 
960  if (theta >=0 && theta <= M_PI/2)
961  {
962  if (v2 < v1)
963  {
964  theta += M_PI;
965  rho *= -1;
966  }
967  }
968 
969  else
970  {
971  double jinter;
972  jinter = -c/b;
973  if (v2 < v1)
974  {
975  theta += M_PI;
976  if (jinter > 0)
977  {
978  rho *= -1;
979  }
980  }
981 
982  else
983  {
984  if (jinter < 0)
985  {
986  rho *= -1;
987  }
988  }
989  }
990 
991  if (vpDEBUG_ENABLE(2))
992  {
993  vpImagePoint ip, ip1, ip2;
994 
995  ip.set_i( i );
996  ip.set_j( j );
997  ip1.set_i( i1 );
998  ip1.set_j( j1 );
999  ip2.set_i( i2 );
1000  ip2.set_j( j2 );
1001 
1003  vpDisplay::displayArrow(I, ip, ip2, vpColor::red) ;
1004  }
1005  }
1006 
1007 }
1008 
1019 double
1021 {
1022  return rho ;
1023 }
1024 
1028 double
1030 {
1031  return theta ;
1032 }
1033 
1041 void
1043 {
1044  /*Return the coordinates of the extremities of the line*/
1045  ip1.set_i( PExt[0].ifloat );
1046  ip1.set_j( PExt[0].jfloat );
1047  ip2.set_i( PExt[1].ifloat );
1048  ip2.set_j( PExt[1].jfloat );
1049 }
1050 
1051 
1064 bool
1065 vpMeLine::intersection(const vpMeLine &line1, const vpMeLine &line2,
1066  vpImagePoint &ip)
1067 {
1068  double denom = 0;
1069  double a1 = line1.a;
1070  double b1 = line1.b;
1071  double c1 = line1.c;
1072  double a2 = line2.a;
1073  double b2 = line2.b;
1074  double c2 = line2.c;
1075  double i=0, j=0;
1076 
1077  try{
1078 
1079  if (a1 > 0.1)
1080  {
1081  denom = (-(a2/a1) * b1 + b2);
1082 
1083  //if (denom == 0)
1084  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
1085  {
1086  std::cout << "!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
1087  return (false);
1088  }
1089 
1090  //if (denom != 0 )
1091  if (std::fabs(denom) > std::numeric_limits<double>::epsilon())
1092  {
1093  j = ( (a2/a1)*c1 - c2 ) / denom;
1094  i = (-b1*j - c1) / a1;
1095  }
1096  }
1097 
1098  else
1099  {
1100  denom = (-(b2/b1) * a1 + a2);
1101 
1102  //if (denom == 0)
1103  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
1104  {
1105  std::cout << "!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
1106  return (false);
1107  }
1108 
1109  //if (denom != 0 )
1110  if (std::fabs(denom) > std::numeric_limits<double>::epsilon())
1111  {
1112  i = ( (b2/b1)*c1 - c2 ) / denom;
1113  j = (-a1*i - c1) / b1;
1114  }
1115  }
1116  ip.set_i( i );
1117  ip.set_j( j );
1118 
1119  return (true);
1120  }
1121  catch(...)
1122  {
1123  return (false);
1124  }
1125 }
1126 
1146 void vpMeLine::display(const vpImage<unsigned char>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1147  const double &A, const double &B, const double &C,
1148  vpColor color, unsigned int thickness)
1149 {
1150  vpImagePoint ip1, ip2;
1151 
1152  if (fabs(A) < fabs(B)) {
1153  double i1, j1, i2, j2;
1154  i1 = 0;
1155  j1 = (-A*i1 -C) / B;
1156  i2 = I.getHeight() - 1.0;
1157  j2 = (-A*i2 -C) / B;
1158 
1159  ip1.set_i( i1 );
1160  ip1.set_j( j1 );
1161  ip2.set_i( i2 );
1162  ip2.set_j( j2 );
1163  vpDisplay::displayLine(I, ip1, ip2, color);
1164  //vpDisplay::flush(I);
1165 
1166  }
1167  else {
1168  double i1, j1, i2, j2;
1169  j1 = 0;
1170  i1 = -(B * j1 + C) / A;
1171  j2 = I.getWidth() - 1.0;
1172  i2 = -(B * j2 + C) / A;
1173 
1174  ip1.set_i( i1 );
1175  ip1.set_j( j1 );
1176  ip2.set_i( i2 );
1177  ip2.set_j( j2 );
1178  vpDisplay::displayLine(I, ip1, ip2, color);
1179  //vpDisplay::flush(I);
1180  }
1181 
1182  ip1.set_i( PExt1.ifloat );
1183  ip1.set_j( PExt1.jfloat );
1184  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1185 
1186  ip1.set_i( PExt2.ifloat );
1187  ip1.set_j( PExt2.jfloat );
1188  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1189 }
1190 
1212 void vpMeLine::display(const vpImage<unsigned char>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1213  const std::list<vpMeSite> &site_list,
1214  const double &A, const double &B, const double &C,
1215  vpColor color, unsigned int thickness)
1216 {
1217  vpImagePoint ip;
1218 
1219  for(std::list<vpMeSite>::const_iterator it=site_list.begin(); it!=site_list.end(); ++it){
1220  vpMeSite pix = *it;
1221  ip.set_i( pix.ifloat );
1222  ip.set_j( pix.jfloat );
1223 
1224 
1225  if (pix.getState() == vpMeSite::M_ESTIMATOR)
1226  vpDisplay::displayCross(I, ip, 5, vpColor::green,thickness);
1227  else
1228  vpDisplay::displayCross(I, ip, 5, color,thickness);
1229 
1230  //vpDisplay::flush(I);
1231  }
1232 
1233  vpImagePoint ip1, ip2;
1234 
1235  if (fabs(A) < fabs(B)) {
1236  double i1, j1, i2, j2;
1237  i1 = 0;
1238  j1 = (-A*i1 -C) / B;
1239  i2 = I.getHeight() - 1.0;
1240  j2 = (-A*i2 -C) / B;
1241 
1242  ip1.set_i( i1 );
1243  ip1.set_j( j1 );
1244  ip2.set_i( i2 );
1245  ip2.set_j( j2 );
1246  vpDisplay::displayLine(I, ip1, ip2, color);
1247  //vpDisplay::flush(I);
1248 
1249  }
1250  else {
1251  double i1, j1, i2, j2;
1252  j1 = 0;
1253  i1 = -(B * j1 + C) / A;
1254  j2 = I.getWidth() - 1.0;
1255  i2 = -(B * j2 + C) / A;
1256 
1257  ip1.set_i( i1 );
1258  ip1.set_j( j1 );
1259  ip2.set_i( i2 );
1260  ip2.set_j( j2 );
1261  vpDisplay::displayLine(I, ip1, ip2, color);
1262  //vpDisplay::flush(I);
1263  }
1264 
1265  ip1.set_i( PExt1.ifloat );
1266  ip1.set_j( PExt1.jfloat );
1267  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1268 
1269  ip1.set_i( PExt2.ifloat );
1270  ip1.set_j( PExt2.jfloat );
1271  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1272 }
1273 
void reSample(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:705
void set_j(const double j)
Definition: vpImagePoint.h:156
unsigned int getRange() const
Definition: vpMe.h:236
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
double c
Parameter c of the line equation a*i + b*j + c = 0.
Definition: vpMeLine.h:173
virtual void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)=0
void init()
Definition: vpMeSite.cpp:73
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Compute the weights according a residue vector and a PsiFunction.
Definition: vpRobust.cpp:138
double get_i() const
Definition: vpImagePoint.h:181
unsigned int getWidth() const
Definition: vpImage.h:154
double jfloat
Definition: vpMeSite.h:100
unsigned int numberOfSignal()
#define vpERROR_TRACE
Definition: vpDebug.h:379
double getTheta() const
Definition: vpMeLine.cpp:1029
double angle
Definition: vpMeLine.h:159
void setExtremities()
Definition: vpMeLine.cpp:525
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:76
Class to define colors available for display functionnalities.
Definition: vpColor.h:123
double delta
Definition: vpMeLine.h:158
int outOfImage(int i, int j, int half, int rows, int cols)
void set_i(const double i)
Definition: vpImagePoint.h:145
bool _useIntensityForRho
Flag to specify wether the intensity of the image at the middle point is used to compute the sign of ...
Definition: vpMeLine.h:163
double alpha
Definition: vpMeSite.h:104
int i
Definition: vpMeSite.h:98
void track(const vpImage< unsigned char > &Im)
Definition: vpMeLine.cpp:784
int mask_sign
Definition: vpMeSite.h:102
static const vpColor green
Definition: vpColor.h:168
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1964
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:192
void leastSquare()
Definition: vpMeLine.cpp:272
static const vpColor red
Definition: vpColor.h:165
#define vpDEBUG_ENABLE(niv)
Definition: vpDebug.h:502
vpMeSiteState getState() const
Definition: vpMeSite.h:202
void display(const vpImage< unsigned char > &I, vpColor col)
Definition: vpMeLine.cpp:229
double ifloat
Definition: vpMeSite.h:100
double rho
Definition: vpMeLine.h:157
virtual ~vpMeLine()
Definition: vpMeLine.cpp:138
void computeRhoTheta(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:872
void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:1108
std::list< vpMeSite > list
Definition: vpMeTracker.h:80
Error that can be emited by the vpTracker class and its derivates.
void updateDelta()
Definition: vpMeLine.cpp:742
void getExtremities(vpImagePoint &ip1, vpImagePoint &ip2)
Definition: vpMeLine.cpp:1042
double theta
Definition: vpMeLine.h:157
static double sqr(double x)
Definition: vpMath.h:106
void sample(const vpImage< unsigned char > &image)
Definition: vpMeLine.cpp:151
Class that tracks in an image a line moving edges.
Definition: vpMeLine.h:149
void suppressPoints()
Definition: vpMeLine.cpp:507
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
double delta_1
Definition: vpMeLine.h:158
void setDisplay(vpMeSiteDisplayType select)
Definition: vpMeSite.h:152
void track(const vpImage< unsigned char > &I)
Track sampled pixels.
Contains abstract elements for a Distance to Feature type feature.
Definition: vpMeTracker.h:71
void initTracking(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:243
#define vpCDEBUG(niv)
Definition: vpDebug.h:478
double a
Parameter a of the line equation a*i + b*j + c = 0.
Definition: vpMeLine.h:171
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:189
vpMeSite PExt[2]
Definition: vpMeLine.h:155
int j
Definition: vpMeSite.h:98
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
double b
Parameter b of the line equation a*i + b*j + c = 0.
Definition: vpMeLine.h:172
void track(const vpImage< unsigned char > &im, const vpMe *me, const bool test_contraste=true)
Definition: vpMeSite.cpp:370
vpMe * me
Moving edges initialisation parameters.
Definition: vpMeTracker.h:82
Contains an M-Estimator and various influence function.
Definition: vpRobust.h:63
int sign
Definition: vpMeLine.h:160
void initTracking(const vpImage< unsigned char > &I)
double angle_1
Definition: vpMeLine.h:159
static bool intersection(const vpMeLine &line1, const vpMeLine &line2, vpImagePoint &ip)
Definition: vpMeLine.cpp:1065
unsigned int getHeight() const
Definition: vpImage.h:145
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1810
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
void setRange(const unsigned int &r)
Definition: vpMe.h:229
void setThreshold(const double noise_threshold)
Definition: vpRobust.h:128
double getSampleStep() const
Definition: vpMe.h:284
double getRho() const
Definition: vpMeLine.cpp:1020
vpMeSite::vpMeSiteDisplayType selectDisplay
Definition: vpMeTracker.h:87
void setIteration(const unsigned int iter)
Set iteration.
Definition: vpRobust.h:122
void seekExtremities(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:586
virtual void display(const vpImage< unsigned char > &I, vpColor col)=0
vpColVector p
Definition: vpTracker.h:78
static const vpColor blue
Definition: vpColor.h:171