ViSP  2.9.0
vpMeLine.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMeLine.cpp 4649 2014-02-07 14:57:11Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Moving edges.
36  *
37  * Authors:
38  * Eric Marchand
39  *
40  *****************************************************************************/
41 
42 
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 #include <algorithm> // std::min
62 
63 #define INCR_MIN 1
64 
65 void computeDelta(double &delta, int i1, int j1, int i2, int j2);
66 
67 static void
68 normalizeAngle(double &delta)
69 {
70  while (delta > M_PI) { delta -= M_PI ; }
71  while (delta < -M_PI) { delta += M_PI ; }
72 }
73 
74 void
75 computeDelta(double &delta, int i1, int j1, int i2, int j2)
76 {
77 
78  double B = double(i1-i2) ;
79  double A = double(j1-j2) ;
80 
81  delta = atan2(B,A) ;
82  delta -= M_PI/2.0 ;
83  normalizeAngle(delta) ;
84 
85 }
86 
87 static void
88 project(double a, double b, double c,
89  double i, double j, double &ip,double &jp)
90 {
91  if (fabs(a)>fabs(b))
92  {
93  jp = (vpMath::sqr(a)*j - a*b*i - c*b)/(vpMath::sqr(a)+vpMath::sqr(b)) ;
94  ip = (-c-b*jp)/a;
95  }
96  else
97  {
98  ip = (vpMath::sqr(b)*i-a*b*j-c*a)/(vpMath::sqr(a)+vpMath::sqr(b)) ;
99  jp = (-c-a*ip)/b;
100  }
101 }
102 
109  : rho(0.), theta(0.), delta(0.), delta_1(0.), angle(0.), angle_1(90), sign(1),
110  _useIntensityForRho(true), a(0.), b(0.), c(0.)
111 {
112 }
119  : vpMeTracker(meline),
120  rho(0.), theta(0.), delta(0.), delta_1(0.), angle(0.), angle_1(90), sign(1),
121  _useIntensityForRho(true), a(0.), b(0.), c(0.)
122 
123 {
124  rho = meline.rho;
125  theta = meline.theta;
126  delta = meline.delta;
127  delta_1 = meline.delta_1;
128  angle = meline.angle;
129  angle_1 = meline.angle_1;
130  sign = meline.sign;
131 
132  a = meline.a;
133  b = meline.b;
134  c = meline.c;
136  PExt[0] = meline.PExt[0];
137  PExt[1] = meline.PExt[1];
138 }
139 
146 {
147  list.clear();
148 }
149 
160 void
162 {
163  if (!me) {
164  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
166  "Moving edges not initialized")) ;
167  }
168 
169  int rows = (int)I.getHeight() ;
170  int cols = (int)I.getWidth() ;
171  double n_sample;
172 
173  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
174  {
175  vpERROR_TRACE("function called with sample step = 0") ;
177  "sample step = 0")) ;
178  }
179 
180  // i, j portions of the line_p
181  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
182  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
183 
184  double length_p = sqrt((vpMath::sqr(diffsi)+vpMath::sqr(diffsj)));
185  if(std::fabs(length_p)<=std::numeric_limits<double>::epsilon())
186  throw(vpTrackingException(vpTrackingException::fatalError,"points too close of each other to define a line")) ;
187  // number of samples along line_p
188  n_sample = length_p/(double)me->getSampleStep();
189 
190  double stepi = diffsi/(double)n_sample;
191  double stepj = diffsj/(double)n_sample;
192 
193  // Choose starting point
194  double is = PExt[1].ifloat;
195  double js = PExt[1].jfloat;
196 
197  // Delete old list
198  list.clear();
199 
200  // sample positions at i*me->getSampleStep() interval along the
201  // line_p, starting at PSiteExt[0]
202 
203  vpImagePoint ip;
204  for(int i=0; i<=vpMath::round(n_sample); i++)
205  {
206  // If point is in the image, add to the sample list
207  if(!outOfImage(vpMath::round(is), vpMath::round(js), 0, rows, cols))
208  {
209  vpMeSite pix ; //= list.value();
210  pix.init((int)is, (int)js, delta, 0, sign) ;
212 
213  if(vpDEBUG_ENABLE(3))
214  {
215  ip.set_i( is );
216  ip.set_j( js );
218  }
219 
220  list.push_back(pix);
221  }
222  is += stepi;
223  js += stepj;
224 
225  }
226 
227  vpCDEBUG(1) << "end vpMeLine::sample() : ";
228  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
229 }
230 
231 
244 void
246 {
247  vpMeLine::display(I,PExt[0],PExt[1],list,a,b,c,col);
248 }
249 
250 
258 void
260 {
261  vpImagePoint ip1, ip2;
262 
263  std::cout << "Click on the line first point..." <<std::endl ;
264  while (vpDisplay::getClick(I, ip1)!=true) ;
266  vpDisplay::flush(I);
267  std::cout << "Click on the line second point..." <<std::endl ;
268  while (vpDisplay::getClick(I, ip2)!=true) ;
270  vpDisplay::flush(I);
271 
272  try
273  {
274  initTracking(I, ip1, ip2) ;
275  }
276  catch(...)
277  {
278  vpERROR_TRACE("Error caught") ;
279  throw ;
280  }
281 
282 }
283 
284 
291 void
293 {
294  vpMatrix A(numberOfSignal(),2) ;
295  vpColVector x(2), x_1(2) ;
296  x_1 = 0;
297 
298  unsigned int i ;
299 
300  vpRobust r(numberOfSignal()) ;
301  r.setThreshold(2);
302  r.setIteration(0) ;
304  D.setIdentity() ;
305  vpMatrix DA, DAmemory ;
306  vpColVector DAx ;
309  w =1 ;
310  vpMeSite p_me ;
311  unsigned int iter =0 ;
312  unsigned int nos_1 = 0 ;
313  double distance = 100;
314 
315  if (list.size() <= 2 || numberOfSignal() <= 2)
316  {
317  //vpERROR_TRACE("Not enough point") ;
318  vpCDEBUG(1) << "Not enough point";
320  "not enough point")) ;
321  }
322 
323  if ((fabs(b) >=0.9)) // Construction du systeme Ax=B
324  // a i + j + c = 0
325  // A = (i 1) B = (-j)
326  {
327  nos_1 = numberOfSignal() ;
328  unsigned int k =0 ;
329  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
330  p_me = *it;
331  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
332  {
333  A[k][0] = p_me.ifloat ;
334  A[k][1] = 1 ;
335  B[k] = -p_me.jfloat ;
336  k++ ;
337  }
338  }
339 
340  while (iter < 4 && distance > 0.05)
341  {
342  DA = D*A ;
343  x = DA.pseudoInverse(1e-26) *D*B ;
344 
345  vpColVector residu(nos_1);
346  residu = B - A*x;
347  r.setIteration(iter) ;
348  r.MEstimator(vpRobust::TUKEY,residu,w) ;
349 
350  k = 0;
351  for (i=0 ; i < nos_1 ; i++)
352  {
353  D[k][k] =w[k] ;
354  k++;
355  }
356  iter++ ;
357  distance = fabs(x[0]-x_1[0])+fabs(x[1]-x_1[1]);
358  x_1 = x;
359  }
360 
361  k =0 ;
362  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
363  p_me = *it;
364  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
365  {
366  if (w[k] < 0.2)
367  {
369 
370  *it = p_me;
371  }
372  k++ ;
373  }
374  }
375 
376  // mise a jour de l'equation de la droite
377  a = x[0] ;
378  b = 1 ;
379  c = x[1] ;
380 
381  double s =sqrt( vpMath::sqr(a)+vpMath::sqr(b)) ;
382  a /= s ;
383  b /= s ;
384  c /= s ;
385  }
386 
387 
388  else // Construction du systeme Ax=B
389  // i + bj + c = 0
390  // A = (j 1) B = (-i)
391  {
392  nos_1 = numberOfSignal() ;
393  unsigned int k =0 ;
394  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
395  p_me = *it;
396  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
397  {
398  A[k][0] = p_me.jfloat ;
399  A[k][1] = 1 ;
400  B[k] = -p_me.ifloat ;
401  k++ ;
402  }
403  }
404 
405  while (iter < 4 && distance > 0.05)
406  {
407  DA = D*A ;
408  x = DA.pseudoInverse(1e-26) *D*B ;
409 
410  vpColVector residu(nos_1);
411  residu = B - A*x;
412  r.setIteration(iter) ;
413  r.MEstimator(vpRobust::TUKEY,residu,w) ;
414 
415  k = 0;
416  for (i=0 ; i < nos_1 ; i++)
417  {
418  D[k][k] =w[k] ;
419  k++;
420  }
421  iter++ ;
422  distance = fabs(x[0]-x_1[0])+fabs(x[1]-x_1[1]);
423  x_1 = x;
424  }
425 
426  k =0 ;
427  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
428  p_me = *it;
429  if (p_me.getState() == vpMeSite::NO_SUPPRESSION)
430  {
431  if (w[k] < 0.2)
432  {
434 
435  *it = p_me;
436  }
437  k++ ;
438  }
439  }
440  a = 1 ;
441  b = x[0] ;
442  c = x[1] ;
443 
444  double s = sqrt(vpMath::sqr(a)+vpMath::sqr(b)) ;
445  a /= s ;
446  b /= s ;
447  c /= s ;
448  }
449 
450  // mise a jour du delta
451  delta = atan2(a,b) ;
452 
453  normalizeAngle(delta) ;
454 }
455 
456 
457 
467 void
469  const vpImagePoint &ip1,
470  const vpImagePoint &ip2)
471 {
472  vpCDEBUG(1) <<" begin vpMeLine::initTracking()"<<std::endl ;
473 
474  int i1s, j1s, i2s, j2s;
475 
476  i1s = vpMath::round( ip1.get_i() );
477  i2s = vpMath::round( ip2.get_i() );
478  j1s = vpMath::round( ip1.get_j() );
479  j2s = vpMath::round( ip2.get_j() );
480 
481  try{
482 
483  // 1. On fait ce qui concerne les droites (peut etre vide)
484  {
485  // Points extremites
486  PExt[0].ifloat = (float)ip1.get_i() ;
487  PExt[0].jfloat = (float)ip1.get_j() ;
488  PExt[1].ifloat = (float)ip2.get_i() ;
489  PExt[1].jfloat = (float)ip2.get_j() ;
490 
491  double angle_ = atan2((double)(i1s-i2s),(double)(j1s-j2s)) ;
492  a = cos(angle_) ;
493  b = sin(angle_) ;
494 
495  // Real values of a, b can have an other sign. So to get the good values
496  // of a and b in order to initialise then c, we call track(I) just below
497 
498  computeDelta(delta,i1s,j1s,i2s,j2s) ;
499  delta_1 = delta;
500 
501  // vpTRACE("a: %f b: %f c: %f -b/a: %f delta: %f", a, b, c, -(b/a), delta);
502 
503  sample(I) ;
504 
505  }
506  // 2. On appelle ce qui n'est pas specifique
507  {
509  }
510  // Call track(I) to give the good sign to a and b and to initialise c which can be used for the display
511  track(I);
512  }
513  catch(...)
514  {
515  vpERROR_TRACE("Error caught") ;
516  throw ;
517  }
518  vpCDEBUG(1) <<" end vpMeLine::initTracking()"<<std::endl ;
519 }
520 
521 
525 void
527 {
528  // Loop through list of sites to track
529  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ){
530  vpMeSite s = *it;//current reference pixel
531 
533  it = list.erase(it);
534  else
535  ++it;
536  }
537 }
538 
539 
543 void
545 {
546  double imin = +1e6 ;
547  double jmin = +1e6;
548  double imax = -1 ;
549  double jmax = -1 ;
550 
551 
552  // Loop through list of sites to track
553  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
554  vpMeSite s = *it;//current reference pixel
555  if (s.ifloat < imin)
556  {
557  imin = s.ifloat ;
558  jmin = s.jfloat ;
559  }
560 
561  if (s.ifloat > imax)
562  {
563  imax = s.ifloat ;
564  jmax = s.jfloat ;
565  }
566  }
567 
568  PExt[0].ifloat = imin ;
569  PExt[0].jfloat = jmin ;
570  PExt[1].ifloat = imax ;
571  PExt[1].jfloat = jmax ;
572 
573  if (fabs(imin-imax) < 25)
574  {
575  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
576  vpMeSite s = *it;//current reference pixel
577  if (s.jfloat < jmin)
578  {
579  imin = s.ifloat ;
580  jmin = s.jfloat ;
581  }
582 
583  if (s.jfloat > jmax)
584  {
585  imax = s.ifloat ;
586  jmax = s.jfloat ;
587  }
588  }
589  PExt[0].ifloat = imin ;
590  PExt[0].jfloat = jmin ;
591  PExt[1].ifloat = imax ;
592  PExt[1].jfloat = jmax ;
593  }
594 }
595 
606 void
608 {
609  vpCDEBUG(1) <<"begin vpMeLine::sample() : "<<std::endl ;
610 
611  if (!me) {
612  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
614  "Moving edges not initialized")) ;
615  }
616 
617  int rows = (int)I.getHeight() ;
618  int cols = (int)I.getWidth() ;
619  double n_sample;
620 
621  //if (me->getSampleStep()==0)
622  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
623  {
624 
625  vpERROR_TRACE("function called with sample step = 0") ;
627  "sample step = 0")) ;
628  }
629 
630  // i, j portions of the line_p
631  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
632  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
633 
634  double s = vpMath::sqr(diffsi)+vpMath::sqr(diffsj) ;
635 
636  double di = diffsi/sqrt(s) ; // pas de risque de /0 car d(P1,P2) >0
637  double dj = diffsj/sqrt(s) ;
638 
639  double length_p = sqrt((vpMath::sqr(diffsi)+vpMath::sqr(diffsj)));
640 
641  // number of samples along line_p
642  n_sample = length_p/(double)me->getSampleStep();
643  double sample_step = (double)me->getSampleStep();
644 
645  vpMeSite P ;
646  P.init((int) PExt[0].ifloat, (int)PExt[0].jfloat, delta_1, 0, sign) ;
648 
649  unsigned int memory_range = me->getRange() ;
650  me->setRange(1);
651 
652  vpImagePoint ip;
653 
654  for (int i=0 ; i < 3 ; i++)
655  {
656  P.ifloat = P.ifloat + di*sample_step ; P.i = (int)P.ifloat ;
657  P.jfloat = P.jfloat + dj*sample_step ; P.j = (int)P.jfloat ;
658 
659  if(!outOfImage(P.i, P.j, 5, rows, cols))
660  {
661  P.track(I,me,false) ;
662 
664  {
665  list.push_back(P);
666  if (vpDEBUG_ENABLE(3)) {
667  ip.set_i( P.i );
668  ip.set_j( P.j );
669 
671  }
672  }
673  else {
674  if (vpDEBUG_ENABLE(3)) {
675  ip.set_i( P.i );
676  ip.set_j( P.j );
678  }
679  }
680  }
681  }
682 
683  P.init((int) PExt[1].ifloat, (int)PExt[1].jfloat, delta_1, 0, sign) ;
685  for (int i=0 ; i < 3 ; i++)
686  {
687  P.ifloat = P.ifloat - di*sample_step ; P.i = (int)P.ifloat ;
688  P.jfloat = P.jfloat - dj*sample_step ; P.j = (int)P.jfloat ;
689 
690  if(!outOfImage(P.i, P.j, 5, rows, cols))
691  {
692  P.track(I,me,false) ;
693 
695  {
696  list.push_back(P);
697  if (vpDEBUG_ENABLE(3)) {
698  ip.set_i( P.i );
699  ip.set_j( P.j );
701  }
702  }
703  else {
704  if (vpDEBUG_ENABLE(3)) {
705  ip.set_i( P.i );
706  ip.set_j( P.j );
708  }
709  }
710  }
711  }
712 
713  me->setRange(memory_range);
714 
715  vpCDEBUG(1) <<"end vpMeLine::sample() : " ;
716  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
717 }
718 
719 
731 void
733 {
734  double i1,j1,i2,j2 ;
735 
736  if (!me) {
737  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
739  "Moving edges not initialized")) ;
740  }
741 
742  project(a,b,c,PExt[0].ifloat,PExt[0].jfloat,i1,j1) ;
743  project(a,b,c,PExt[1].ifloat,PExt[1].jfloat,i2,j2) ;
744 
745  // Points extremites
746  PExt[0].ifloat = i1 ;
747  PExt[0].jfloat = j1 ;
748  PExt[1].ifloat = i2 ;
749  PExt[1].jfloat = j2 ;
750 
751  double d = sqrt(vpMath::sqr(i1-i2)+vpMath::sqr(j1-j2)) ;
752 
753  unsigned int n = numberOfSignal() ;
754  double expecteddensity = d / (double)me->getSampleStep();
755 
756  if ((double)n<0.9*expecteddensity)
757  {
758  double delta_new = delta;
759  delta = delta_1;
760  sample(I) ;
761  delta = delta_new;
762  // 2. On appelle ce qui n'est pas specifique
763  {
765  }
766  }
767 }
768 
773 void
775 {
776  vpMeSite p_me ;
777 
778  double angle_ = delta + M_PI/2;
779  double diff = 0;
780 
781  while (angle_<0) angle_ += M_PI;
782  while (angle_>M_PI) angle_ -= M_PI;
783 
784  angle_ = vpMath::round(angle_ * 180 / M_PI) ;
785 
786  //if(fabs(angle_) == 180 )
787  if(std::fabs(std::fabs(angle_) - 180) <= std::numeric_limits<double>::epsilon())
788  {
789  angle_= 0 ;
790  }
791 
792  //std::cout << "angle theta : " << theta << std::endl ;
793  diff = fabs(angle_ - angle_1);
794  if (diff > 90)
795  sign *= -1;
796 
797  angle_1 = angle_;
798 
799  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
800  p_me = *it;
801  p_me.alpha = delta ;
802  p_me.mask_sign = sign;
803  *it = p_me;
804  }
805  delta_1 = delta;
806 }
807 
808 
815 void
817 {
818  vpCDEBUG(1) <<"begin vpMeLine::track()"<<std::endl ;
819 
820  // 1. On fait ce qui concerne les droites (peut etre vide)
821  {
822  }
823  // 2. On appelle ce qui n'est pas specifique
824  {
825  vpMeTracker::track(I) ;
826  }
827 
828  // 3. On revient aux droites
829  {
830  // supression des points rejetes par les ME
831  suppressPoints() ;
832  setExtremities() ;
833 
834 
835  // Estimation des parametres de la droite aux moindres carre
836  try
837  {
838  leastSquare() ;
839  }
840  catch(...)
841  {
842  vpERROR_TRACE("Error caught") ;
843  throw ;
844  }
845 
846 
847  // recherche de point aux extremite de la droites
848  // dans le cas d'un glissement
849  seekExtremities(I) ;
850 
851  setExtremities() ;
852  try
853  {
854  leastSquare() ;
855  }
856  catch(...)
857  {
858  vpERROR_TRACE("Error caught") ;
859  throw ;
860  }
861 
862  // suppression des points rejetes par la regression robuste
863  suppressPoints() ;
864  setExtremities() ;
865 
866  //reechantillonage si necessaire
867  reSample(I) ;
868 
869  // remet a jour l'angle delta pour chaque point de la liste
870 
871  updateDelta() ;
872 
873  // Remise a jour de delta dans la liste de site me
874  if (vpDEBUG_ENABLE(2))
875  {
876  display(I,vpColor::red) ;
878  vpDisplay::flush(I) ;
879  }
880 
881 
882  }
883 
884  computeRhoTheta(I) ;
885 
886  vpCDEBUG(1) <<"end vpMeLine::track()"<<std::endl ;
887 }
888 
889 void vpMeLine::update_indices(double theta,int i,int j,int incr,int& i1,int& i2,int& j1,int& j2){
890  i1 = (int)(i + cos(theta) *incr) ;
891  j1 = (int)(j + sin(theta) *incr) ;
892 
893  i2 = (int)(i - cos(theta) *incr) ;
894  j2 = (int)(j - sin(theta) *incr) ;
895 }
896 
903 void
905 {
906  //rho = -c ;
907  //theta = atan2(a,b) ;
908  rho = fabs(c);
909  theta = atan2(b,a) ;
910 
911  while (theta >= M_PI) theta -=M_PI ;
912  while (theta < 0) theta +=M_PI ;
913 
915 
916  /* while(theta < -M_PI) theta += 2*M_PI ;
917  while(theta >= M_PI) theta -= 2*M_PI ;
918 
919  // If theta is between -90 and -180 get the equivalent
920  // between 0 and 90
921  if(theta <-M_PI/2)
922  {
923  theta += M_PI ;
924  rho *= -1 ;
925  }
926  // If theta is between 90 and 180 get the equivalent
927  // between 0 and -90
928  if(theta >M_PI/2)
929  {
930  theta -= M_PI ;
931  rho *= -1 ;
932  }
933  */
934  // convention pour choisir le signe de rho
935  int i,j ;
936  i = vpMath::round((PExt[0].ifloat + PExt[1].ifloat )/2) ;
937  j = vpMath::round((PExt[0].jfloat + PExt[1].jfloat )/2) ;
938 
939  int end = false ;
940  int incr = 10 ;
941 
942 
943  int i1=0,i2=0,j1=0,j2=0 ;
944  unsigned char v1=0,v2=0 ;
945 
946  int width_ = (int)I.getWidth();
947  int height_ = (int)I.getHeight();
948  update_indices(theta,i,j,incr,i1,i2,j1,j2);
949 
950  if(i1<0 || i1>=height_ || i2<0 || i2>=height_ ||
951  j1<0 || j1>=width_ || j2<0 || j2>=width_){
952  double rho_lim1 = fabs((double)i/cos(theta));
953  double rho_lim2 = fabs((double)j/sin(theta));
954 
955  double co_rho_lim1 = fabs(((double)(height_-i))/cos(theta));
956  double co_rho_lim2 = fabs(((double)(width_-j))/sin(theta));
957 
958  double rho_lim = std::min(rho_lim1,rho_lim2);
959  double co_rho_lim = std::min(co_rho_lim1,co_rho_lim2);
960  incr = (int)std::floor(std::min(rho_lim,co_rho_lim));
961  if(incr<INCR_MIN){
962  vpERROR_TRACE("increment is too small") ;
964  "increment is too small")) ;
965  }
966  update_indices(theta,i,j,incr,i1,i2,j1,j2);
967  }
968 
969  while (!end)
970  {
971  end = true;
972  unsigned int i1_ = static_cast<unsigned int>(i1);
973  unsigned int j1_ = static_cast<unsigned int>(j1);
974  unsigned int i2_ = static_cast<unsigned int>(i2);
975  unsigned int j2_ = static_cast<unsigned int>(j2);
976  v1=I[i1_][j1_];
977  v2=I[i2_][j2_];
978  if (abs(v1-v2) < 1)
979  {
980 
981  incr-- ;
982  end = false ;
983  if (incr==1)
984  {
985  std::cout << "In CStraightLine::GetParameters() " ;
986  std::cout << " Error Tracking " << abs(v1-v2) << std::endl ;
987  }
988  }
989  update_indices(theta,i,j,incr,i1,i2,j1,j2);
990  }
991 
992  if (theta >=0 && theta <= M_PI/2)
993  {
994  if (v2 < v1)
995  {
996  theta += M_PI;
997  rho *= -1;
998  }
999  }
1000 
1001  else
1002  {
1003  double jinter;
1004  jinter = -c/b;
1005  if (v2 < v1)
1006  {
1007  theta += M_PI;
1008  if (jinter > 0)
1009  {
1010  rho *= -1;
1011  }
1012  }
1013 
1014  else
1015  {
1016  if (jinter < 0)
1017  {
1018  rho *= -1;
1019  }
1020  }
1021  }
1022 
1023  if (vpDEBUG_ENABLE(2))
1024  {
1025  vpImagePoint ip, ip1, ip2;
1026 
1027  ip.set_i( i );
1028  ip.set_j( j );
1029  ip1.set_i( i1 );
1030  ip1.set_j( j1 );
1031  ip2.set_i( i2 );
1032  ip2.set_j( j2 );
1033 
1035  vpDisplay::displayArrow(I, ip, ip2, vpColor::red) ;
1036  }
1037  }
1038 
1039 }
1040 
1051 double
1053 {
1054  return rho ;
1055 }
1056 
1060 double
1062 {
1063  return theta ;
1064 }
1065 
1073 void
1075 {
1076  /*Return the coordinates of the extremities of the line*/
1077  ip1.set_i( PExt[0].ifloat );
1078  ip1.set_j( PExt[0].jfloat );
1079  ip2.set_i( PExt[1].ifloat );
1080  ip2.set_j( PExt[1].jfloat );
1081 }
1082 
1083 
1096 bool
1097 vpMeLine::intersection(const vpMeLine &line1, const vpMeLine &line2,
1098  vpImagePoint &ip)
1099 {
1100  double denom = 0;
1101  double a1 = line1.a;
1102  double b1 = line1.b;
1103  double c1 = line1.c;
1104  double a2 = line2.a;
1105  double b2 = line2.b;
1106  double c2 = line2.c;
1107  double i=0, j=0;
1108 
1109  try{
1110 
1111  if (a1 > 0.1)
1112  {
1113  denom = (-(a2/a1) * b1 + b2);
1114 
1115  //if (denom == 0)
1116  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
1117  {
1118  std::cout << "!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
1119  return (false);
1120  }
1121 
1122  //if (denom != 0 )
1123  if (std::fabs(denom) > std::numeric_limits<double>::epsilon())
1124  {
1125  j = ( (a2/a1)*c1 - c2 ) / denom;
1126  i = (-b1*j - c1) / a1;
1127  }
1128  }
1129 
1130  else
1131  {
1132  denom = (-(b2/b1) * a1 + a2);
1133 
1134  //if (denom == 0)
1135  if (std::fabs(denom) <= std::numeric_limits<double>::epsilon())
1136  {
1137  std::cout << "!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
1138  return (false);
1139  }
1140 
1141  //if (denom != 0 )
1142  if (std::fabs(denom) > std::numeric_limits<double>::epsilon())
1143  {
1144  i = ( (b2/b1)*c1 - c2 ) / denom;
1145  j = (-a1*i - c1) / b1;
1146  }
1147  }
1148  ip.set_i( i );
1149  ip.set_j( j );
1150 
1151  return (true);
1152  }
1153  catch(...)
1154  {
1155  return (false);
1156  }
1157 }
1158 
1178 void vpMeLine::display(const vpImage<unsigned char>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1179  const double &A, const double &B, const double &C,
1180  const vpColor &color, unsigned int thickness)
1181 {
1182  vpImagePoint ip1, ip2;
1183 
1184  if (fabs(A) < fabs(B)) {
1185  double i1, j1, i2, j2;
1186  i1 = 0;
1187  j1 = (-A*i1 -C) / B;
1188  i2 = I.getHeight() - 1.0;
1189  j2 = (-A*i2 -C) / B;
1190 
1191  ip1.set_i( i1 );
1192  ip1.set_j( j1 );
1193  ip2.set_i( i2 );
1194  ip2.set_j( j2 );
1195  vpDisplay::displayLine(I, ip1, ip2, color);
1196  //vpDisplay::flush(I);
1197 
1198  }
1199  else {
1200  double i1, j1, i2, j2;
1201  j1 = 0;
1202  i1 = -(B * j1 + C) / A;
1203  j2 = I.getWidth() - 1.0;
1204  i2 = -(B * j2 + C) / A;
1205 
1206  ip1.set_i( i1 );
1207  ip1.set_j( j1 );
1208  ip2.set_i( i2 );
1209  ip2.set_j( j2 );
1210  vpDisplay::displayLine(I, ip1, ip2, color);
1211  //vpDisplay::flush(I);
1212  }
1213 
1214  ip1.set_i( PExt1.ifloat );
1215  ip1.set_j( PExt1.jfloat );
1216  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1217 
1218  ip1.set_i( PExt2.ifloat );
1219  ip1.set_j( PExt2.jfloat );
1220  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1221 }
1222 
1242 void vpMeLine::display(const vpImage<vpRGBa>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1243  const double &A, const double &B, const double &C,
1244  const vpColor &color, unsigned int thickness)
1245 {
1246  vpImagePoint ip1, ip2;
1247 
1248  if (fabs(A) < fabs(B)) {
1249  double i1, j1, i2, j2;
1250  i1 = 0;
1251  j1 = (-A*i1 -C) / B;
1252  i2 = I.getHeight() - 1.0;
1253  j2 = (-A*i2 -C) / B;
1254 
1255  ip1.set_i( i1 );
1256  ip1.set_j( j1 );
1257  ip2.set_i( i2 );
1258  ip2.set_j( j2 );
1259  vpDisplay::displayLine(I, ip1, ip2, color);
1260  //vpDisplay::flush(I);
1261 
1262  }
1263  else {
1264  double i1, j1, i2, j2;
1265  j1 = 0;
1266  i1 = -(B * j1 + C) / A;
1267  j2 = I.getWidth() - 1.0;
1268  i2 = -(B * j2 + C) / A;
1269 
1270  ip1.set_i( i1 );
1271  ip1.set_j( j1 );
1272  ip2.set_i( i2 );
1273  ip2.set_j( j2 );
1274  vpDisplay::displayLine(I, ip1, ip2, color);
1275  //vpDisplay::flush(I);
1276  }
1277 
1278  ip1.set_i( PExt1.ifloat );
1279  ip1.set_j( PExt1.jfloat );
1280  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1281 
1282  ip1.set_i( PExt2.ifloat );
1283  ip1.set_j( PExt2.jfloat );
1284  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1285 }
1286 
1308 void vpMeLine::display(const vpImage<unsigned char>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1309  const std::list<vpMeSite> &site_list,
1310  const double &A, const double &B, const double &C,
1311  const vpColor &color, unsigned int thickness)
1312 {
1313  vpImagePoint ip;
1314 
1315  for(std::list<vpMeSite>::const_iterator it=site_list.begin(); it!=site_list.end(); ++it){
1316  vpMeSite pix = *it;
1317  ip.set_i( pix.ifloat );
1318  ip.set_j( pix.jfloat );
1319 
1320  if (pix.getState() == vpMeSite::M_ESTIMATOR)
1321  vpDisplay::displayCross(I, ip, 5, vpColor::green,thickness);
1322  else
1323  vpDisplay::displayCross(I, ip, 5, color,thickness);
1324 
1325  //vpDisplay::flush(I);
1326  }
1327 
1328  vpImagePoint ip1, ip2;
1329 
1330  if (fabs(A) < fabs(B)) {
1331  double i1, j1, i2, j2;
1332  i1 = 0;
1333  j1 = (-A*i1 -C) / B;
1334  i2 = I.getHeight() - 1.0;
1335  j2 = (-A*i2 -C) / B;
1336 
1337  ip1.set_i( i1 );
1338  ip1.set_j( j1 );
1339  ip2.set_i( i2 );
1340  ip2.set_j( j2 );
1341  vpDisplay::displayLine(I, ip1, ip2, color);
1342  //vpDisplay::flush(I);
1343 
1344  }
1345  else {
1346  double i1, j1, i2, j2;
1347  j1 = 0;
1348  i1 = -(B * j1 + C) / A;
1349  j2 = I.getWidth() - 1.0;
1350  i2 = -(B * j2 + C) / A;
1351 
1352  ip1.set_i( i1 );
1353  ip1.set_j( j1 );
1354  ip2.set_i( i2 );
1355  ip2.set_j( j2 );
1356  vpDisplay::displayLine(I, ip1, ip2, color);
1357  //vpDisplay::flush(I);
1358  }
1359 
1360  ip1.set_i( PExt1.ifloat );
1361  ip1.set_j( PExt1.jfloat );
1362  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1363 
1364  ip1.set_i( PExt2.ifloat );
1365  ip1.set_j( PExt2.jfloat );
1366  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1367 }
1368 
1390 void vpMeLine::display(const vpImage<vpRGBa>& I,const vpMeSite &PExt1, const vpMeSite &PExt2,
1391  const std::list<vpMeSite> &site_list,
1392  const double &A, const double &B, const double &C,
1393  const vpColor &color, unsigned int thickness)
1394 {
1395  vpImagePoint ip;
1396 
1397  for(std::list<vpMeSite>::const_iterator it=site_list.begin(); it!=site_list.end(); ++it){
1398  vpMeSite pix = *it;
1399  ip.set_i( pix.ifloat );
1400  ip.set_j( pix.jfloat );
1401 
1402  if (pix.getState() == vpMeSite::M_ESTIMATOR)
1403  vpDisplay::displayCross(I, ip, 5, vpColor::green,thickness);
1404  else
1405  vpDisplay::displayCross(I, ip, 5, color,thickness);
1406 
1407  //vpDisplay::flush(I);
1408  }
1409 
1410  vpImagePoint ip1, ip2;
1411 
1412  if (fabs(A) < fabs(B)) {
1413  double i1, j1, i2, j2;
1414  i1 = 0;
1415  j1 = (-A*i1 -C) / B;
1416  i2 = I.getHeight() - 1.0;
1417  j2 = (-A*i2 -C) / B;
1418 
1419  ip1.set_i( i1 );
1420  ip1.set_j( j1 );
1421  ip2.set_i( i2 );
1422  ip2.set_j( j2 );
1423  vpDisplay::displayLine(I, ip1, ip2, color);
1424  //vpDisplay::flush(I);
1425 
1426  }
1427  else {
1428  double i1, j1, i2, j2;
1429  j1 = 0;
1430  i1 = -(B * j1 + C) / A;
1431  j2 = I.getWidth() - 1.0;
1432  i2 = -(B * j2 + C) / A;
1433 
1434  ip1.set_i( i1 );
1435  ip1.set_j( j1 );
1436  ip2.set_i( i2 );
1437  ip2.set_j( j2 );
1438  vpDisplay::displayLine(I, ip1, ip2, color);
1439  //vpDisplay::flush(I);
1440  }
1441 
1442  ip1.set_i( PExt1.ifloat );
1443  ip1.set_j( PExt1.jfloat );
1444  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1445 
1446  ip1.set_i( PExt2.ifloat );
1447  ip1.set_j( PExt2.jfloat );
1448  vpDisplay::displayCross(I, ip1, 10, vpColor::green,thickness);
1449 }
1450 
void reSample(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:732
unsigned int getRange() const
Definition: vpMe.h:236
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
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:136
double get_i() const
Definition: vpImagePoint.h:194
unsigned int getWidth() const
Definition: vpImage.h:159
double jfloat
Definition: vpMeSite.h:100
unsigned int numberOfSignal()
#define vpERROR_TRACE
Definition: vpDebug.h:395
double getTheta() const
Definition: vpMeLine.cpp:1061
double angle
Definition: vpMeLine.h:166
void setExtremities()
Definition: vpMeLine.cpp:544
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)
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:816
int mask_sign
Definition: vpMeSite.h:102
#define vpDEBUG_ENABLE(level)
Definition: vpDebug.h:530
#define vpDERROR_TRACE
Definition: vpDebug.h:459
static const vpColor green
Definition: vpColor.h:170
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1994
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:205
void leastSquare()
Definition: vpMeLine.cpp:292
static const vpColor red
Definition: vpColor.h:167
vpMeSiteState getState() const
Definition: vpMeSite.h:202
void display(const vpImage< unsigned char > &I, vpColor col)
Definition: vpMeLine.cpp:245
double ifloat
Definition: vpMeSite.h:100
double rho
Definition: vpMeLine.h:164
virtual ~vpMeLine()
Definition: vpMeLine.cpp:145
void set_i(const double ii)
Definition: vpImagePoint.h:158
void computeRhoTheta(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:904
void setIdentity(const double &val=1.0)
Definition: vpMatrix.cpp:1159
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:774
void getExtremities(vpImagePoint &ip1, vpImagePoint &ip2)
Definition: vpMeLine.cpp:1074
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:161
Class that tracks in an image a line moving edges.
Definition: vpMeLine.h:156
void suppressPoints()
Definition: vpMeLine.cpp:526
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:259
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
#define vpCDEBUG(level)
Definition: vpDebug.h:506
vpMeSite PExt[2]
Definition: vpMeLine.h:162
void set_j(const double jj)
Definition: vpImagePoint.h:169
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:381
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:1097
unsigned int getHeight() const
Definition: vpImage.h:150
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1861
virtual bool getClick(bool blocking=true)=0
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
virtual void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)=0
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:1052
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:607
virtual void display(const vpImage< unsigned char > &I, vpColor col)=0
static const vpColor blue
Definition: vpColor.h:173