ViSP  2.8.0
vpMeLine.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMeLine.cpp 4140 2013-02-21 10:50:22Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 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 
153 void
155 {
156  if (!me) {
157  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
159  "Moving edges not initialized")) ;
160  }
161 
162  int rows = (int)I.getHeight() ;
163  int cols = (int)I.getWidth() ;
164  double n_sample;
165 
166  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
167  {
168  vpERROR_TRACE("function called with sample step = 0") ;
170  "sample step = 0")) ;
171  }
172 
173  // i, j portions of the line_p
174  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
175  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
176 
177  double length_p = sqrt((vpMath::sqr(diffsi)+vpMath::sqr(diffsj)));
178  if(std::fabs(length_p)<=std::numeric_limits<double>::epsilon())
179  throw(vpTrackingException(vpTrackingException::fatalError,"points too close of each other to define a line")) ;
180  // number of samples along line_p
181  n_sample = length_p/(double)me->getSampleStep();
182 
183  double stepi = diffsi/(double)n_sample;
184  double stepj = diffsj/(double)n_sample;
185 
186  // Choose starting point
187  double is = PExt[1].ifloat;
188  double js = PExt[1].jfloat;
189 
190  // Delete old list
191  list.clear();
192 
193  // sample positions at i*me->getSampleStep() interval along the
194  // line_p, starting at PSiteExt[0]
195 
196  vpImagePoint ip;
197  for(int i=0; i<=vpMath::round(n_sample); i++)
198  {
199  // If point is in the image, add to the sample list
200  if(!outOfImage(vpMath::round(is), vpMath::round(js), 0, rows, cols))
201  {
202  vpMeSite pix ; //= list.value();
203  pix.init((int)is, (int)js, delta, 0, sign) ;
205 
206  if(vpDEBUG_ENABLE(3))
207  {
208  ip.set_i( is );
209  ip.set_j( js );
211  }
212 
213  list.push_back(pix);
214  }
215  is += stepi;
216  js += stepj;
217 
218  }
219 
220  vpCDEBUG(1) << "end vpMeLine::sample() : ";
221  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
222 }
223 
224 
237 void
239 {
240  vpMeLine::display(I,PExt[0],PExt[1],list,a,b,c,col);
241 }
242 
243 
251 void
253 {
254  vpImagePoint ip1, ip2;
255 
256  std::cout << "Click on the line first point..." <<std::endl ;
257  while (vpDisplay::getClick(I, ip1)!=true) ;
259  vpDisplay::flush(I);
260  std::cout << "Click on the line second point..." <<std::endl ;
261  while (vpDisplay::getClick(I, ip2)!=true) ;
263  vpDisplay::flush(I);
264 
265  try
266  {
267  initTracking(I, ip1, ip2) ;
268  }
269  catch(...)
270  {
271  vpERROR_TRACE("Error caught") ;
272  throw ;
273  }
274 
275 }
276 
277 
284 void
286 {
287  vpMatrix A(numberOfSignal(),2) ;
288  vpColVector x(2), x_1(2) ;
289  x_1 = 0;
290 
291  unsigned int i ;
292 
293  vpRobust r(numberOfSignal()) ;
294  r.setThreshold(2);
295  r.setIteration(0) ;
297  D.setIdentity() ;
298  vpMatrix DA, DAmemory ;
299  vpColVector DAx ;
302  w =1 ;
303  vpMeSite p ;
304  unsigned int iter =0 ;
305  unsigned int nos_1 = 0 ;
306  double distance = 100;
307 
308  if (list.size() <= 2 || numberOfSignal() <= 2)
309  {
310  //vpERROR_TRACE("Not enough point") ;
311  vpCDEBUG(1) << "Not enough point";
313  "not enough point")) ;
314  }
315 
316  if ((fabs(b) >=0.9)) // Construction du systeme Ax=B
317  // a i + j + c = 0
318  // A = (i 1) B = (-j)
319  {
320  nos_1 = numberOfSignal() ;
321  unsigned int k =0 ;
322  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
323  p = *it;
325  {
326  A[k][0] = p.ifloat ;
327  A[k][1] = 1 ;
328  B[k] = -p.jfloat ;
329  k++ ;
330  }
331  }
332 
333  while (iter < 4 && distance > 0.05)
334  {
335  DA = D*A ;
336  x = DA.pseudoInverse(1e-26) *D*B ;
337 
338  vpColVector residu(nos_1);
339  residu = B - A*x;
340  r.setIteration(iter) ;
341  r.MEstimator(vpRobust::TUKEY,residu,w) ;
342 
343  k = 0;
344  for (i=0 ; i < nos_1 ; i++)
345  {
346  D[k][k] =w[k] ;
347  k++;
348  }
349  iter++ ;
350  distance = fabs(x[0]-x_1[0])+fabs(x[1]-x_1[1]);
351  x_1 = x;
352  }
353 
354  k =0 ;
355  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
356  p = *it;
358  {
359  if (w[k] < 0.2)
360  {
362 
363  *it = p;
364  }
365  k++ ;
366  }
367  }
368 
369  // mise a jour de l'equation de la droite
370  a = x[0] ;
371  b = 1 ;
372  c = x[1] ;
373 
374  double s =sqrt( vpMath::sqr(a)+vpMath::sqr(b)) ;
375  a /= s ;
376  b /= s ;
377  c /= s ;
378  }
379 
380 
381  else // Construction du systeme Ax=B
382  // i + bj + c = 0
383  // A = (j 1) B = (-i)
384  {
385  nos_1 = numberOfSignal() ;
386  unsigned int k =0 ;
387  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
388  p = *it;
390  {
391  A[k][0] = p.jfloat ;
392  A[k][1] = 1 ;
393  B[k] = -p.ifloat ;
394  k++ ;
395  }
396  }
397 
398  while (iter < 4 && distance > 0.05)
399  {
400  DA = D*A ;
401  x = DA.pseudoInverse(1e-26) *D*B ;
402 
403  vpColVector residu(nos_1);
404  residu = B - A*x;
405  r.setIteration(iter) ;
406  r.MEstimator(vpRobust::TUKEY,residu,w) ;
407 
408  k = 0;
409  for (i=0 ; i < nos_1 ; i++)
410  {
411  D[k][k] =w[k] ;
412  k++;
413  }
414  iter++ ;
415  distance = fabs(x[0]-x_1[0])+fabs(x[1]-x_1[1]);
416  x_1 = x;
417  }
418 
419 
420  k =0 ;
421  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
422  p = *it;
424  {
425  if (w[k] < 0.2)
426  {
428 
429  *it = p;
430  }
431  k++ ;
432  }
433  }
434  a = 1 ;
435  b = x[0] ;
436  c = x[1] ;
437 
438  double s = sqrt(vpMath::sqr(a)+vpMath::sqr(b)) ;
439  a /= s ;
440  b /= s ;
441  c /= s ;
442  }
443 
444  // mise a jour du delta
445  delta = atan2(a,b) ;
446 
447  normalizeAngle(delta) ;
448 }
449 
450 
451 
461 void
463  const vpImagePoint &ip1,
464  const vpImagePoint &ip2)
465 {
466  vpCDEBUG(1) <<" begin vpMeLine::initTracking()"<<std::endl ;
467 
468  int i1s, j1s, i2s, j2s;
469 
470  i1s = vpMath::round( ip1.get_i() );
471  i2s = vpMath::round( ip2.get_i() );
472  j1s = vpMath::round( ip1.get_j() );
473  j2s = vpMath::round( ip2.get_j() );
474 
475  try{
476 
477  // 1. On fait ce qui concerne les droites (peut etre vide)
478  {
479  // Points extremites
480  PExt[0].ifloat = (float)ip1.get_i() ;
481  PExt[0].jfloat = (float)ip1.get_j() ;
482  PExt[1].ifloat = (float)ip2.get_i() ;
483  PExt[1].jfloat = (float)ip2.get_j() ;
484 
485  double angle = atan2((double)(i1s-i2s),(double)(j1s-j2s)) ;
486  a = cos(angle) ;
487  b = sin(angle) ;
488 
489  // Real values of a, b can have an other sign. So to get the good values
490  // of a and b in order to initialise then c, we call track(I) just below
491 
492  computeDelta(delta,i1s,j1s,i2s,j2s) ;
493  delta_1 = delta;
494 
495  // vpTRACE("a: %f b: %f c: %f -b/a: %f delta: %f", a, b, c, -(b/a), delta);
496 
497  sample(I) ;
498 
499  }
500  // 2. On appelle ce qui n'est pas specifique
501  {
503  }
504  // Call track(I) to give the good sign to a and b and to initialise c which can be used for the display
505  track(I);
506  }
507  catch(...)
508  {
509  vpERROR_TRACE("Error caught") ;
510  throw ;
511  }
512  vpCDEBUG(1) <<" end vpMeLine::initTracking()"<<std::endl ;
513 }
514 
515 
519 void
521 {
522  // Loop through list of sites to track
523  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ){
524  vpMeSite s = *it;//current reference pixel
525 
527  it = list.erase(it);
528  else
529  ++it;
530  }
531 }
532 
533 
537 void
539 {
540  double imin = +1e6 ;
541  double jmin = +1e6;
542  double imax = -1 ;
543  double jmax = -1 ;
544 
545 
546  // Loop through list of sites to track
547  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
548  vpMeSite s = *it;//current reference pixel
549  if (s.ifloat < imin)
550  {
551  imin = s.ifloat ;
552  jmin = s.jfloat ;
553  }
554 
555  if (s.ifloat > imax)
556  {
557  imax = s.ifloat ;
558  jmax = s.jfloat ;
559  }
560  }
561 
562  PExt[0].ifloat = imin ;
563  PExt[0].jfloat = jmin ;
564  PExt[1].ifloat = imax ;
565  PExt[1].jfloat = jmax ;
566 
567  if (fabs(imin-imax) < 25)
568  {
569  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
570  vpMeSite s = *it;//current reference pixel
571  if (s.jfloat < jmin)
572  {
573  imin = s.ifloat ;
574  jmin = s.jfloat ;
575  }
576 
577  if (s.jfloat > jmax)
578  {
579  imax = s.ifloat ;
580  jmax = s.jfloat ;
581  }
582  }
583  PExt[0].ifloat = imin ;
584  PExt[0].jfloat = jmin ;
585  PExt[1].ifloat = imax ;
586  PExt[1].jfloat = jmax ;
587  }
588 }
589 
600 void
602 {
603  vpCDEBUG(1) <<"begin vpMeLine::sample() : "<<std::endl ;
604 
605  if (!me) {
606  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
608  "Moving edges not initialized")) ;
609  }
610 
611  int rows = (int)I.getHeight() ;
612  int cols = (int)I.getWidth() ;
613  double n_sample;
614 
615  //if (me->getSampleStep()==0)
616  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
617  {
618 
619  vpERROR_TRACE("function called with sample step = 0") ;
621  "sample step = 0")) ;
622  }
623 
624  // i, j portions of the line_p
625  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
626  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
627 
628  double s = vpMath::sqr(diffsi)+vpMath::sqr(diffsj) ;
629 
630  double di = diffsi/sqrt(s) ; // pas de risque de /0 car d(P1,P2) >0
631  double dj = diffsj/sqrt(s) ;
632 
633  double length_p = sqrt((vpMath::sqr(diffsi)+vpMath::sqr(diffsj)));
634 
635  // number of samples along line_p
636  n_sample = length_p/(double)me->getSampleStep();
637  double sample = (double)me->getSampleStep();
638 
639  vpMeSite P ;
640  P.init((int) PExt[0].ifloat, (int)PExt[0].jfloat, delta_1, 0, sign) ;
642 
643  unsigned int memory_range = me->getRange() ;
644  me->setRange(1);
645 
646  vpImagePoint ip;
647 
648  for (int i=0 ; i < 3 ; i++)
649  {
650  P.ifloat = P.ifloat + di*sample ; P.i = (int)P.ifloat ;
651  P.jfloat = P.jfloat + dj*sample ; P.j = (int)P.jfloat ;
652 
653  if(!outOfImage(P.i, P.j, 5, rows, cols))
654  {
655  P.track(I,me,false) ;
656 
658  {
659  list.push_back(P);
660  if (vpDEBUG_ENABLE(3)) {
661  ip.set_i( P.i );
662  ip.set_j( P.j );
663 
665  }
666  }
667  else {
668  if (vpDEBUG_ENABLE(3)) {
669  ip.set_i( P.i );
670  ip.set_j( P.j );
672  }
673  }
674  }
675  }
676 
677  P.init((int) PExt[1].ifloat, (int)PExt[1].jfloat, delta_1, 0, sign) ;
679  for (int i=0 ; i < 3 ; i++)
680  {
681  P.ifloat = P.ifloat - di*sample ; P.i = (int)P.ifloat ;
682  P.jfloat = P.jfloat - dj*sample ; P.j = (int)P.jfloat ;
683 
684  if(!outOfImage(P.i, P.j, 5, rows, cols))
685  {
686  P.track(I,me,false) ;
687 
689  {
690  list.push_back(P);
691  if (vpDEBUG_ENABLE(3)) {
692  ip.set_i( P.i );
693  ip.set_j( P.j );
695  }
696  }
697  else {
698  if (vpDEBUG_ENABLE(3)) {
699  ip.set_i( P.i );
700  ip.set_j( P.j );
702  }
703  }
704  }
705  }
706 
707  me->setRange(memory_range);
708 
709  vpCDEBUG(1) <<"end vpMeLine::sample() : " ;
710  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
711 }
712 
713 
725 void
727 {
728  double i1,j1,i2,j2 ;
729 
730  if (!me) {
731  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
733  "Moving edges not initialized")) ;
734  }
735 
736  project(a,b,c,PExt[0].ifloat,PExt[0].jfloat,i1,j1) ;
737  project(a,b,c,PExt[1].ifloat,PExt[1].jfloat,i2,j2) ;
738 
739  // Points extremites
740  PExt[0].ifloat = i1 ;
741  PExt[0].jfloat = j1 ;
742  PExt[1].ifloat = i2 ;
743  PExt[1].jfloat = j2 ;
744 
745  double d = sqrt(vpMath::sqr(i1-i2)+vpMath::sqr(j1-j2)) ;
746 
747  unsigned int n = numberOfSignal() ;
748  double expecteddensity = d / (double)me->getSampleStep();
749 
750  if ((double)n<0.9*expecteddensity)
751  {
752  double delta_new = delta;
753  delta = delta_1;
754  sample(I) ;
755  delta = delta_new;
756  // 2. On appelle ce qui n'est pas specifique
757  {
759  }
760  }
761 }
762 
767 void
769 {
770  vpMeSite p ;
771 
772  double angle = delta + M_PI/2;
773  double diff = 0;
774 
775  while (angle<0) angle += M_PI;
776  while (angle>M_PI) angle -= M_PI;
777 
778  angle = vpMath::round(angle * 180 / M_PI) ;
779 
780  //if(fabs(angle) == 180 )
781  if(std::fabs(std::fabs(angle) - 180) <= std::numeric_limits<double>::epsilon())
782  {
783  angle= 0 ;
784  }
785 
786  //std::cout << "angle theta : " << theta << std::endl ;
787  diff = fabs(angle - angle_1);
788  if (diff > 90)
789  sign *= -1;
790 
791  angle_1 = angle;
792 
793  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
794  p = *it;
795  p.alpha = delta ;
796  p.mask_sign = sign;
797  *it = p;
798  }
799  delta_1 = delta;
800 }
801 
802 
809 void
811 {
812  vpCDEBUG(1) <<"begin vpMeLine::track()"<<std::endl ;
813 
814  // 1. On fait ce qui concerne les droites (peut etre vide)
815  {
816  }
817  // 2. On appelle ce qui n'est pas specifique
818  {
819  vpMeTracker::track(I) ;
820  }
821 
822  // 3. On revient aux droites
823  {
824  // supression des points rejetes par les ME
825  suppressPoints() ;
826  setExtremities() ;
827 
828 
829  // Estimation des parametres de la droite aux moindres carre
830  try
831  {
832  leastSquare() ;
833  }
834  catch(...)
835  {
836  vpERROR_TRACE("Error caught") ;
837  throw ;
838  }
839 
840 
841  // recherche de point aux extremite de la droites
842  // dans le cas d'un glissement
843  seekExtremities(I) ;
844 
845  setExtremities() ;
846  try
847  {
848  leastSquare() ;
849  }
850  catch(...)
851  {
852  vpERROR_TRACE("Error caught") ;
853  throw ;
854  }
855 
856  // suppression des points rejetes par la regression robuste
857  suppressPoints() ;
858  setExtremities() ;
859 
860  //reechantillonage si necessaire
861  reSample(I) ;
862 
863  // remet a jour l'angle delta pour chaque point de la liste
864 
865  updateDelta() ;
866 
867  // Remise a jour de delta dans la liste de site me
868  if (vpDEBUG_ENABLE(2))
869  {
870  display(I,vpColor::red) ;
872  vpDisplay::flush(I) ;
873  }
874 
875 
876  }
877 
878  computeRhoTheta(I) ;
879 
880  vpCDEBUG(1) <<"end vpMeLine::track()"<<std::endl ;
881 }
882 
883 void vpMeLine::update_indices(double theta,int i,int j,int incr,int& i1,int& i2,int& j1,int& j2){
884  i1 = (int)(i + cos(theta) *incr) ;
885  j1 = (int)(j + sin(theta) *incr) ;
886 
887  i2 = (int)(i - cos(theta) *incr) ;
888  j2 = (int)(j - sin(theta) *incr) ;
889 }
890 
897 void
899 {
900  //rho = -c ;
901  //theta = atan2(a,b) ;
902  rho = fabs(c);
903  theta = atan2(b,a) ;
904 
905  while (theta >= M_PI) theta -=M_PI ;
906  while (theta < 0) theta +=M_PI ;
907 
909 
910  /* while(theta < -M_PI) theta += 2*M_PI ;
911  while(theta >= M_PI) theta -= 2*M_PI ;
912 
913  // If theta is between -90 and -180 get the equivalent
914  // between 0 and 90
915  if(theta <-M_PI/2)
916  {
917  theta += M_PI ;
918  rho *= -1 ;
919  }
920  // If theta is between 90 and 180 get the equivalent
921  // between 0 and -90
922  if(theta >M_PI/2)
923  {
924  theta -= M_PI ;
925  rho *= -1 ;
926  }
927  */
928  // convention pour choisir le signe de rho
929  int i,j ;
930  i = vpMath::round((PExt[0].ifloat + PExt[1].ifloat )/2) ;
931  j = vpMath::round((PExt[0].jfloat + PExt[1].jfloat )/2) ;
932 
933  int end = false ;
934  int incr = 10 ;
935 
936 
937  int i1=0,i2=0,j1=0,j2=0 ;
938  unsigned char v1=0,v2=0 ;
939 
940  int width_ = (int)I.getWidth();
941  int height_ = (int)I.getHeight();
942  update_indices(theta,i,j,incr,i1,i2,j1,j2);
943 
944  if(i1<0 || i1>=height_ || i2<0 || i2>=height_ ||
945  j1<0 || j1>=width_ || j2<0 || j2>=width_){
946  double rho_lim1 = fabs((double)i/cos(theta));
947  double rho_lim2 = fabs((double)j/sin(theta));
948 
949  double co_rho_lim1 = fabs(((double)(height_-i))/cos(theta));
950  double co_rho_lim2 = fabs(((double)(width_-j))/sin(theta));
951 
952  double rho_lim = std::min(rho_lim1,rho_lim2);
953  double co_rho_lim = std::min(co_rho_lim1,co_rho_lim2);
954  incr = (int)std::floor(std::min(rho_lim,co_rho_lim));
955  if(incr<INCR_MIN){
956  vpERROR_TRACE("increment is too small") ;
958  "increment is too small")) ;
959  }
960  update_indices(theta,i,j,incr,i1,i2,j1,j2);
961  }
962 
963  while (!end)
964  {
965  end = true;
966  unsigned int i1_ = static_cast<unsigned int>(i1);
967  unsigned int j1_ = static_cast<unsigned int>(j1);
968  unsigned int i2_ = static_cast<unsigned int>(i2);
969  unsigned int j2_ = static_cast<unsigned int>(j2);
970  v1=I[i1_][j1_];
971  v2=I[i2_][j2_];
972  if (abs(v1-v2) < 1)
973  {
974 
975  incr-- ;
976  end = false ;
977  if (incr==1)
978  {
979  std::cout << "In CStraightLine::GetParameters() " ;
980  std::cout << " Error Tracking " << abs(v1-v2) << std::endl ;
981  }
982  }
983  update_indices(theta,i,j,incr,i1,i2,j1,j2);
984  }
985 
986  if (theta >=0 && theta <= M_PI/2)
987  {
988  if (v2 < v1)
989  {
990  theta += M_PI;
991  rho *= -1;
992  }
993  }
994 
995  else
996  {
997  double jinter;
998  jinter = -c/b;
999  if (v2 < v1)
1000  {
1001  theta += M_PI;
1002  if (jinter > 0)
1003  {
1004  rho *= -1;
1005  }
1006  }
1007 
1008  else
1009  {
1010  if (jinter < 0)
1011  {
1012  rho *= -1;
1013  }
1014  }
1015  }
1016 
1017  if (vpDEBUG_ENABLE(2))
1018  {
1019  vpImagePoint ip, ip1, ip2;
1020 
1021  ip.set_i( i );
1022  ip.set_j( j );
1023  ip1.set_i( i1 );
1024  ip1.set_j( j1 );
1025  ip2.set_i( i2 );
1026  ip2.set_j( j2 );
1027 
1029  vpDisplay::displayArrow(I, ip, ip2, vpColor::red) ;
1030  }
1031  }
1032 
1033 }
1034 
1045 double
1047 {
1048  return rho ;
1049 }
1050 
1054 double
1056 {
1057  return theta ;
1058 }
1059 
1067 void
1069 {
1070  /*Return the coordinates of the extremities of the line*/
1071  ip1.set_i( PExt[0].ifloat );
1072  ip1.set_j( PExt[0].jfloat );
1073  ip2.set_i( PExt[1].ifloat );
1074  ip2.set_j( PExt[1].jfloat );
1075 }
1076 
1077 
1090 bool
1091 vpMeLine::intersection(const vpMeLine &line1, const vpMeLine &line2,
1092  vpImagePoint &ip)
1093 {
1094  double denom = 0;
1095  double a1 = line1.a;
1096  double b1 = line1.b;
1097  double c1 = line1.c;
1098  double a2 = line2.a;
1099  double b2 = line2.b;
1100  double c2 = line2.c;
1101  double i=0, j=0;
1102 
1103  try{
1104 
1105  if (a1 > 0.1)
1106  {
1107  denom = (-(a2/a1) * b1 + b2);
1108 
1109  //if (denom == 0)
1110  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
1111  {
1112  std::cout << "!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
1113  return (false);
1114  }
1115 
1116  //if (denom != 0 )
1117  if (std::fabs(denom) > std::numeric_limits<double>::epsilon())
1118  {
1119  j = ( (a2/a1)*c1 - c2 ) / denom;
1120  i = (-b1*j - c1) / a1;
1121  }
1122  }
1123 
1124  else
1125  {
1126  denom = (-(b2/b1) * a1 + a2);
1127 
1128  //if (denom == 0)
1129  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
1130  {
1131  std::cout << "!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
1132  return (false);
1133  }
1134 
1135  //if (denom != 0 )
1136  if (std::fabs(denom) > std::numeric_limits<double>::epsilon())
1137  {
1138  i = ( (b2/b1)*c1 - c2 ) / denom;
1139  j = (-a1*i - c1) / b1;
1140  }
1141  }
1142  ip.set_i( i );
1143  ip.set_j( j );
1144 
1145  return (true);
1146  }
1147  catch(...)
1148  {
1149  return (false);
1150  }
1151 }
1152 
1172 void vpMeLine::display(const vpImage<unsigned char>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1173  const double &A, const double &B, const double &C,
1174  const vpColor &color, unsigned int thickness)
1175 {
1176  vpImagePoint ip1, ip2;
1177 
1178  if (fabs(A) < fabs(B)) {
1179  double i1, j1, i2, j2;
1180  i1 = 0;
1181  j1 = (-A*i1 -C) / B;
1182  i2 = I.getHeight() - 1.0;
1183  j2 = (-A*i2 -C) / B;
1184 
1185  ip1.set_i( i1 );
1186  ip1.set_j( j1 );
1187  ip2.set_i( i2 );
1188  ip2.set_j( j2 );
1189  vpDisplay::displayLine(I, ip1, ip2, color);
1190  //vpDisplay::flush(I);
1191 
1192  }
1193  else {
1194  double i1, j1, i2, j2;
1195  j1 = 0;
1196  i1 = -(B * j1 + C) / A;
1197  j2 = I.getWidth() - 1.0;
1198  i2 = -(B * j2 + C) / A;
1199 
1200  ip1.set_i( i1 );
1201  ip1.set_j( j1 );
1202  ip2.set_i( i2 );
1203  ip2.set_j( j2 );
1204  vpDisplay::displayLine(I, ip1, ip2, color);
1205  //vpDisplay::flush(I);
1206  }
1207 
1208  ip1.set_i( PExt1.ifloat );
1209  ip1.set_j( PExt1.jfloat );
1210  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1211 
1212  ip1.set_i( PExt2.ifloat );
1213  ip1.set_j( PExt2.jfloat );
1214  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1215 }
1216 
1236 void vpMeLine::display(const vpImage<vpRGBa>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1237  const double &A, const double &B, const double &C,
1238  const vpColor &color, unsigned int thickness)
1239 {
1240  vpImagePoint ip1, ip2;
1241 
1242  if (fabs(A) < fabs(B)) {
1243  double i1, j1, i2, j2;
1244  i1 = 0;
1245  j1 = (-A*i1 -C) / B;
1246  i2 = I.getHeight() - 1.0;
1247  j2 = (-A*i2 -C) / B;
1248 
1249  ip1.set_i( i1 );
1250  ip1.set_j( j1 );
1251  ip2.set_i( i2 );
1252  ip2.set_j( j2 );
1253  vpDisplay::displayLine(I, ip1, ip2, color);
1254  //vpDisplay::flush(I);
1255 
1256  }
1257  else {
1258  double i1, j1, i2, j2;
1259  j1 = 0;
1260  i1 = -(B * j1 + C) / A;
1261  j2 = I.getWidth() - 1.0;
1262  i2 = -(B * j2 + C) / A;
1263 
1264  ip1.set_i( i1 );
1265  ip1.set_j( j1 );
1266  ip2.set_i( i2 );
1267  ip2.set_j( j2 );
1268  vpDisplay::displayLine(I, ip1, ip2, color);
1269  //vpDisplay::flush(I);
1270  }
1271 
1272  ip1.set_i( PExt1.ifloat );
1273  ip1.set_j( PExt1.jfloat );
1274  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1275 
1276  ip1.set_i( PExt2.ifloat );
1277  ip1.set_j( PExt2.jfloat );
1278  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1279 }
1280 
1302 void vpMeLine::display(const vpImage<unsigned char>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1303  const std::list<vpMeSite> &site_list,
1304  const double &A, const double &B, const double &C,
1305  const vpColor &color, unsigned int thickness)
1306 {
1307  vpImagePoint ip;
1308 
1309  for(std::list<vpMeSite>::const_iterator it=site_list.begin(); it!=site_list.end(); ++it){
1310  vpMeSite pix = *it;
1311  ip.set_i( pix.ifloat );
1312  ip.set_j( pix.jfloat );
1313 
1314  if (pix.getState() == vpMeSite::M_ESTIMATOR)
1315  vpDisplay::displayCross(I, ip, 5, vpColor::green,thickness);
1316  else
1317  vpDisplay::displayCross(I, ip, 5, color,thickness);
1318 
1319  //vpDisplay::flush(I);
1320  }
1321 
1322  vpImagePoint ip1, ip2;
1323 
1324  if (fabs(A) < fabs(B)) {
1325  double i1, j1, i2, j2;
1326  i1 = 0;
1327  j1 = (-A*i1 -C) / B;
1328  i2 = I.getHeight() - 1.0;
1329  j2 = (-A*i2 -C) / B;
1330 
1331  ip1.set_i( i1 );
1332  ip1.set_j( j1 );
1333  ip2.set_i( i2 );
1334  ip2.set_j( j2 );
1335  vpDisplay::displayLine(I, ip1, ip2, color);
1336  //vpDisplay::flush(I);
1337 
1338  }
1339  else {
1340  double i1, j1, i2, j2;
1341  j1 = 0;
1342  i1 = -(B * j1 + C) / A;
1343  j2 = I.getWidth() - 1.0;
1344  i2 = -(B * j2 + C) / A;
1345 
1346  ip1.set_i( i1 );
1347  ip1.set_j( j1 );
1348  ip2.set_i( i2 );
1349  ip2.set_j( j2 );
1350  vpDisplay::displayLine(I, ip1, ip2, color);
1351  //vpDisplay::flush(I);
1352  }
1353 
1354  ip1.set_i( PExt1.ifloat );
1355  ip1.set_j( PExt1.jfloat );
1356  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1357 
1358  ip1.set_i( PExt2.ifloat );
1359  ip1.set_j( PExt2.jfloat );
1360  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1361 }
1362 
1384 void vpMeLine::display(const vpImage<vpRGBa>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1385  const std::list<vpMeSite> &site_list,
1386  const double &A, const double &B, const double &C,
1387  const vpColor &color, unsigned int thickness)
1388 {
1389  vpImagePoint ip;
1390 
1391  for(std::list<vpMeSite>::const_iterator it=site_list.begin(); it!=site_list.end(); ++it){
1392  vpMeSite pix = *it;
1393  ip.set_i( pix.ifloat );
1394  ip.set_j( pix.jfloat );
1395 
1396  if (pix.getState() == vpMeSite::M_ESTIMATOR)
1397  vpDisplay::displayCross(I, ip, 5, vpColor::green,thickness);
1398  else
1399  vpDisplay::displayCross(I, ip, 5, color,thickness);
1400 
1401  //vpDisplay::flush(I);
1402  }
1403 
1404  vpImagePoint ip1, ip2;
1405 
1406  if (fabs(A) < fabs(B)) {
1407  double i1, j1, i2, j2;
1408  i1 = 0;
1409  j1 = (-A*i1 -C) / B;
1410  i2 = I.getHeight() - 1.0;
1411  j2 = (-A*i2 -C) / B;
1412 
1413  ip1.set_i( i1 );
1414  ip1.set_j( j1 );
1415  ip2.set_i( i2 );
1416  ip2.set_j( j2 );
1417  vpDisplay::displayLine(I, ip1, ip2, color);
1418  //vpDisplay::flush(I);
1419 
1420  }
1421  else {
1422  double i1, j1, i2, j2;
1423  j1 = 0;
1424  i1 = -(B * j1 + C) / A;
1425  j2 = I.getWidth() - 1.0;
1426  i2 = -(B * j2 + C) / A;
1427 
1428  ip1.set_i( i1 );
1429  ip1.set_j( j1 );
1430  ip2.set_i( i2 );
1431  ip2.set_j( j2 );
1432  vpDisplay::displayLine(I, ip1, ip2, color);
1433  //vpDisplay::flush(I);
1434  }
1435 
1436  ip1.set_i( PExt1.ifloat );
1437  ip1.set_j( PExt1.jfloat );
1438  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1439 
1440  ip1.set_i( PExt2.ifloat );
1441  ip1.set_j( PExt2.jfloat );
1442  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1443 }
1444 
void reSample(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:726
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:180
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:159
double jfloat
Definition: vpMeSite.h:100
unsigned int numberOfSignal()
#define vpERROR_TRACE
Definition: vpDebug.h:379
double getTheta() const
Definition: vpMeLine.cpp:1055
double angle
Definition: vpMeLine.h:166
void setExtremities()
Definition: vpMeLine.cpp:538
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:125
double delta
Definition: vpMeLine.h:165
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:170
double alpha
Definition: vpMeSite.h:104
int i
Definition: vpMeSite.h:98
void track(const vpImage< unsigned char > &Im)
Definition: vpMeLine.cpp:810
int mask_sign
Definition: vpMeSite.h:102
#define vpDERROR_TRACE
Definition: vpDebug.h:431
static const vpColor green
Definition: vpColor.h:170
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1991
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:192
void leastSquare()
Definition: vpMeLine.cpp:285
static const vpColor red
Definition: vpColor.h:167
#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:238
double ifloat
Definition: vpMeSite.h:100
double rho
Definition: vpMeLine.h:164
virtual ~vpMeLine()
Definition: vpMeLine.cpp:138
void computeRhoTheta(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:898
void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:1110
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:768
void getExtremities(vpImagePoint &ip1, vpImagePoint &ip2)
Definition: vpMeLine.cpp:1068
double theta
Definition: vpMeLine.h:164
static double sqr(double x)
Definition: vpMath.h:106
void sample(const vpImage< unsigned char > &image)
Definition: vpMeLine.cpp:154
Class that tracks in an image a line moving edges.
Definition: vpMeLine.h:156
void suppressPoints()
Definition: vpMeLine.cpp:520
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
double delta_1
Definition: vpMeLine.h:165
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:252
#define vpCDEBUG(niv)
Definition: vpDebug.h:478
double a
Parameter a of the line equation a*i + b*j + c = 0.
Definition: vpMeLine.h:178
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:189
vpMeSite PExt[2]
Definition: vpMeLine.h:162
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:179
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:167
void initTracking(const vpImage< unsigned char > &I)
double angle_1
Definition: vpMeLine.h:166
static bool intersection(const vpMeLine &line1, const vpMeLine &line2, vpImagePoint &ip)
Definition: vpMeLine.cpp:1091
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:1812
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:278
double getRho() const
Definition: vpMeLine.cpp:1046
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:601
virtual void display(const vpImage< unsigned char > &I, vpColor col)=0
vpColVector p
Definition: vpTracker.h:78
static const vpColor blue
Definition: vpColor.h:173