ViSP  2.8.0
vpMbtMeLine.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbtMeLine.cpp 4303 2013-07-04 14:14:00Z 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  * Make the complete tracking of an object by using its CAD model
36  *
37  * Authors:
38  * Nicolas Melchior
39  * Romain Tallonneau
40  * Eric Marchand
41  *
42  *****************************************************************************/
43 #include <visp/vpConfig.h>
44 #ifndef DOXYGEN_SHOULD_SKIP_THIS
45 
50 #include <cmath> // std::fabs
51 #include <limits> // numeric_limits
52 
53 #include <visp/vpMbtMeLine.h>
54 #include <visp/vpTrackingException.h>
55 #include <visp/vpRobust.h>
56 
58 static void
59 normalizeAngle(double &delta)
60 {
61  while (delta > M_PI) { delta -= M_PI ; }
62  while (delta < -M_PI) { delta += M_PI ; }
63 }
64 
65 
70 {
71  sign = 1;
72  theta_1 = M_PI/2;
73 }
74 
79 {
80  list.clear();
81 }
82 
95 void
96 vpMbtMeLine::initTracking(const vpImage<unsigned char> &I, const vpImagePoint &ip1, const vpImagePoint &ip2, double rho, double theta)
97 {
98  vpCDEBUG(1) <<" begin vpMeLine::initTracking()"<<std::endl ;
99 
100  try
101  {
102  // 1. On fait ce qui concerne les droites (peut etre vide)
103  // Points extremites
104  PExt[0].ifloat = (float)ip1.get_i() ;
105  PExt[0].jfloat = (float)ip1.get_j() ;
106  PExt[1].ifloat = (float)ip2.get_i() ;
107  PExt[1].jfloat = (float)ip2.get_j() ;
108 
109  this->rho = rho;
110  this->theta = theta;
111 
112  a = cos(theta);
113  b = sin(theta);
114  c = -rho;
115 
116  double d = sqrt(vpMath::sqr(ip1.get_i()-ip2.get_i())+vpMath::sqr(ip1.get_j()-ip2.get_j())) ;
117 
118  expecteddensity = d / (double)me->getSampleStep();
119 
120  delta = - theta + M_PI/2.0;
121  normalizeAngle(delta);
122  delta_1 = delta;
123 
124  sample(I) ;
125 
127  }
128  catch(...)
129  {
130 // vpERROR_TRACE("Error caught") ;
131  throw ;
132  }
133  vpCDEBUG(1) <<" end vpMeLine::initTracking()"<<std::endl ;
134 }
135 
136 
143 void
144 vpMbtMeLine::sample(const vpImage<unsigned char>& I)
145 {
146  int rows = (int)I.getHeight() ;
147  int cols = (int)I.getWidth() ;
148  double n_sample;
149 
150  //if (me->getSampleStep==0)
151  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
152  {
153  vpERROR_TRACE("function called with sample step = 0") ;
155  "sample step = 0")) ;
156  }
157 
158  // i, j portions of the line_p
159  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
160  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
161 
162  double length_p = sqrt((vpMath::sqr(diffsi)+vpMath::sqr(diffsj)));
163 
164  // number of samples along line_p
165  n_sample = length_p/(double)me->getSampleStep();
166 
167  double stepi = diffsi/(double)n_sample;
168  double stepj = diffsj/(double)n_sample;
169 
170  // Choose starting point
171  double is = PExt[1].ifloat;
172  double js = PExt[1].jfloat;
173 
174  // Delete old list
175  list.clear();
176 
177  // sample positions at i*me->getSampleStep() interval along the
178  // line_p, starting at PSiteExt[0]
179 
180  vpImagePoint ip;
181  for(int i=0; i<=vpMath::round(n_sample); i++)
182  {
183  // If point is in the image, add to the sample list
184  if(!outOfImage(vpMath::round(is), vpMath::round(js), 0, rows, cols))
185  {
186  vpMeSite pix ; //= list.value();
187  pix.init((int)is, (int)js, delta, 0, sign) ;
188 
189  pix.track(I,me,0);
190 
192 
193  if(vpDEBUG_ENABLE(3))
194  {
195  ip.set_i( is );
196  ip.set_j( js );
198  }
199 
200  list.push_back(pix);
201  }
202  is += stepi;
203  js += stepj;
204 
205  }
206 
207  vpCDEBUG(1) << "end vpMeLine::sample() : ";
208  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
209 }
210 
211 
217 void
218 vpMbtMeLine::suppressPoints(const vpImage<unsigned char> & /*I*/)
219 {
220  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ){
221  vpMeSite s = *it;//current reference pixel
222 
223  if (fabs(sin(theta)) > 0.9) // Vertical line management
224  {
225  if ((s.i < imin) ||(s.i > imax))
226  {
228  }
229  }
230 
231  else if (fabs(cos(theta)) > 0.9) // Horizontal line management
232  {
233  if ((s.j < jmin) || (s.j > jmax))
234  {
236  }
237  }
238 
239  else
240  {
241  if ((s.i < imin) ||(s.i > imax) || (s.j < jmin) || (s.j > jmax) )
242  {
244  }
245  }
246 
248  it = list.erase(it);
249  else
250  ++it;
251  }
252 }
253 
254 
260 void
261 vpMbtMeLine::seekExtremities(const vpImage<unsigned char> &I)
262 {
263  vpCDEBUG(1) <<"begin vpMeLine::sample() : "<<std::endl ;
264 
265  int rows = (int)I.getHeight() ;
266  int cols = (int)I.getWidth() ;
267  double n_sample;
268 
269  //if (me->getSampleStep()==0)
270  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
271  {
272 
273  vpERROR_TRACE("function called with sample step = 0") ;
274  throw(vpTrackingException(vpTrackingException::fatalError,"sample step = 0")) ;
275  }
276 
277  // i, j portions of the line_p
278  double diffsi = PExt[0].ifloat-PExt[1].ifloat;
279  double diffsj = PExt[0].jfloat-PExt[1].jfloat;
280 
281  double s = vpMath::sqr(diffsi)+vpMath::sqr(diffsj) ;
282 
283  double di = diffsi/sqrt(s) ; // pas de risque de /0 car d(P1,P2) >0
284  double dj = diffsj/sqrt(s) ;
285 
286  double length_p = sqrt(s); /*(vpMath::sqr(diffsi)+vpMath::sqr(diffsj))*/
287 
288  // number of samples along line_p
289  n_sample = length_p/(double)me->getSampleStep();
290  double sample = (double)me->getSampleStep();
291 
292  vpMeSite P ;
293  P.init((int) PExt[0].ifloat, (int)PExt[0].jfloat, delta_1, 0, sign) ;
295 
296  unsigned int memory_range = me->getRange() ;
297  me->setRange(1);
298 
299  for (int i=0 ; i < 3 ; i++)
300  {
301  P.ifloat = P.ifloat + di*sample ; P.i = (int)P.ifloat ;
302  P.jfloat = P.jfloat + dj*sample ; P.j = (int)P.jfloat ;
303 
304 
305  if ((P.i < imin) ||(P.i > imax) || (P.j < jmin) || (P.j > jmax) )
306  {
308  }
309  else
310  if(!outOfImage(P.i, P.j, 5, rows, cols))
311  {
312  P.track(I,me,false) ;
313 
315  {
316  list.push_back(P);
318  }
319  else
321  }
322  }
323 
324  P.init((int) PExt[1].ifloat, (int)PExt[1].jfloat, delta_1, 0, sign) ;
326  for (int i=0 ; i < 3 ; i++)
327  {
328  P.ifloat = P.ifloat - di*sample ; P.i = (int)P.ifloat ;
329  P.jfloat = P.jfloat - dj*sample ; P.j = (int)P.jfloat ;
330 
331 
332  if ((P.i < imin) ||(P.i > imax) || (P.j < jmin) || (P.j > jmax) )
333  {
335  }
336 
337  else
338  if(!outOfImage(P.i, P.j, 5, rows, cols))
339  {
340  P.track(I,me,false) ;
341 
343  {
344  list.push_back(P);
346  }
347  else
349  }
350  }
351 
352  me->setRange(memory_range);
353 
354  vpCDEBUG(1) <<"end vpMeLine::sample() : " ;
355  vpCDEBUG(1) << n_sample << " point inserted in the list " << std::endl ;
356 }
357 
368 void
369 vpMbtMeLine::reSample(const vpImage<unsigned char> &I)
370 {
371  double d = sqrt(vpMath::sqr(PExt[0].ifloat-PExt[1].ifloat)+vpMath::sqr(PExt[0].jfloat-PExt[1].jfloat)) ;
372 
373  unsigned int n = numberOfSignal() ;
374  double expecteddensity = d / (double)me->getSampleStep();
375 
376  if ((double)n<0.5*expecteddensity && n > 0)
377  {
378  double delta_new = delta;
379  delta = delta_1;
380  sample(I) ;
381  delta = delta_new;
382  // 2. On appelle ce qui n'est pas specifique
383  {
385  }
386  }
387 }
388 
389 
402 void
403 vpMbtMeLine::reSample(const vpImage<unsigned char> &I, vpImagePoint ip1, vpImagePoint ip2)
404 {
405  double d = sqrt(vpMath::sqr(ip1.get_i()-ip2.get_i())+vpMath::sqr(ip1.get_j()-ip2.get_j())) ;
406 
407  size_t n = list.size();
408  expecteddensity = d / (double)me->getSampleStep();
409 
410  if ((double)n<0.5*expecteddensity && n > 0)
411  {
412  double delta_new = delta;
413  delta = delta_1;
414  PExt[0].ifloat = (float)ip1.get_i() ;
415  PExt[0].jfloat = (float)ip1.get_j() ;
416  PExt[1].ifloat = (float)ip2.get_i() ;
417  PExt[1].jfloat = (float)ip2.get_j() ;
418  sample(I) ;
419  delta = delta_new;
420  vpMeTracker::track(I) ;
421  }
422 }
423 
427 void
428 vpMbtMeLine::updateDelta()
429 {
430  vpMeSite p ;
431 
432  double diff = 0;
433 
434  //if(fabs(theta) == M_PI )
435  if(std::fabs(std::fabs(theta) - M_PI) <= vpMath::maximum(std::fabs(theta), (double)M_PI)*std::numeric_limits<double>::epsilon() )
436  {
437  theta = 0 ;
438  }
439 
440  diff = fabs(theta - theta_1);
441  if (diff > M_PI/2.0)
442  sign *= -1;
443 
444  theta_1 = theta;
445 
446  delta = - theta + M_PI/2.0;
447  normalizeAngle(delta);
448 
449  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
450  p = *it;
451  p.alpha = delta ;
452  p.mask_sign = sign;
453  *it = p;
454  }
455  delta_1 = delta;
456 }
457 
463 void
465 {
466  // 2. On appelle ce qui n'est pas specifique
467  try
468  {
470  }
471  catch(...)
472  {
473  throw ;
474  }
475 
476  // supression des points rejetes par les ME
477  // suppressPoints(I);
478  // setExtremities();
479 }
480 
481 
489 void
490 vpMbtMeLine::updateParameters(const vpImage<unsigned char> &I, double rho, double theta)
491 {
492  this->rho = rho;
493  this->theta = theta;
494  a = cos(theta);
495  b = sin(theta);
496  c = -rho;
497  // recherche de point aux extremite de la droites
498  // dans le cas d'un glissement
499  suppressPoints(I);
500  seekExtremities(I);
501  suppressPoints(I);
502  setExtremities();
503  //reechantillonage si necessaire
504  reSample(I);
505 
506  // remet a jour l'angle delta pour chaque point de la liste
507  updateDelta();
508 }
509 
510 
520 void
521 vpMbtMeLine::updateParameters(const vpImage<unsigned char> &I, vpImagePoint ip1, vpImagePoint ip2, double rho, double theta)
522 {
523  this->rho = rho;
524  this->theta = theta;
525  a = cos(theta);
526  b = sin(theta);
527  c = -rho;
528  // recherche de point aux extremite de la droites
529  // dans le cas d'un glissement
530  suppressPoints(I);
531  seekExtremities(I);
532  suppressPoints(I);
533  setExtremities();
534  //reechantillonage si necessaire
535  reSample(I,ip1,ip2);
536 
537  // remet a jour l'angle delta pour chaque point de la liste
538  updateDelta();
539 }
540 
541 
545 void
546 vpMbtMeLine::setExtremities()
547 {
548  double imin = +1e6 ;
549  double jmin = +1e6;
550  double imax = -1 ;
551  double jmax = -1 ;
552 
553  // Loop through list of sites to track
554  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
555  vpMeSite s = *it;//current reference pixel
556  if (s.ifloat < imin)
557  {
558  imin = s.ifloat ;
559  jmin = s.jfloat ;
560  }
561 
562  if (s.ifloat > imax)
563  {
564  imax = s.ifloat ;
565  jmax = s.jfloat ;
566  }
567  }
568 
569  if ( ! list.empty() )
570  {
571  PExt[0].ifloat = imin ;
572  PExt[0].jfloat = jmin ;
573  PExt[1].ifloat = imax ;
574  PExt[1].jfloat = jmax ;
575  }
576 
577  if (fabs(imin-imax) < 25)
578  {
579  for(std::list<vpMeSite>::const_iterator it=list.begin(); it!=list.end(); ++it){
580  vpMeSite s = *it;//current reference pixel
581  if (s.jfloat < jmin)
582  {
583  imin = s.ifloat ;
584  jmin = s.jfloat ;
585  }
586 
587  if (s.jfloat > jmax)
588  {
589  imax = s.ifloat ;
590  jmax = s.jfloat ;
591  }
592  }
593 
594  if (! list.empty())
595  {
596  PExt[0].ifloat = imin ;
597  PExt[0].jfloat = jmin ;
598  PExt[1].ifloat = imax ;
599  PExt[1].jfloat = jmax ;
600  }
601  bubbleSortJ();
602  }
603 
604  else
605  bubbleSortI();
606 }
607 
608 
609 static bool sortByI(const vpMeSite& s1, const vpMeSite& s2){
610  return (s1.ifloat > s2.ifloat);
611 }
612 
613 void
614 vpMbtMeLine::bubbleSortI()
615 {
616 #if 0
617  unsigned int nbElmt = list.size();
618  for (unsigned int pass = 1; pass < nbElmt; pass++)
619  {
620  list.front();
621  for (unsigned int i=0; i < nbElmt-pass; i++)
622  {
623  vpMeSite s1 = list.value() ;
624  vpMeSite s2 = list.nextValue() ;
625  if (s1.ifloat > s2.ifloat)
626  list.swapRight();
627  else
628  list.next();
629  }
630  }
631 #endif
632  list.sort(sortByI);
633 }
634 
635 
636 static bool sortByJ(const vpMeSite& s1, const vpMeSite& s2){
637  return (s1.jfloat > s2.jfloat);
638 }
639 
640 void
641 vpMbtMeLine::bubbleSortJ()
642 {
643 #if 0
644  unsigned int nbElmt = list.size();
645  for(unsigned int pass=1; pass < nbElmt; pass++)
646  {
647  list.front();
648  for (unsigned int i=0; i < nbElmt-pass; i++)
649  {
650  vpMeSite s1 = list.value() ;
651  vpMeSite s2 = list.nextValue() ;
652  if (s1.jfloat > s2.jfloat)
653  list.swapRight();
654  else
655  list.next();
656  }
657  }
658 #endif
659  list.sort(sortByJ);
660 }
661 
662 
663 void
664 vpMbtMeLine::findSignal(const vpImage<unsigned char>& I, const vpMe *me, double *conv)
665 {
666  vpImagePoint itest(PExt[0].ifloat+(PExt[1].ifloat-PExt[0].ifloat)/2, PExt[0].jfloat+(PExt[1].jfloat-PExt[0].jfloat)/2);
667 
668  vpMeSite pix ; //= list.value();
669  pix.init(itest.get_i(), itest.get_j(), delta, 0, sign);
670 
671  vpMeSite *list_query_pixels;
672 // double convolution = 0;
673  unsigned int range = me->getRange();
674 
675  list_query_pixels = pix.getQueryList(I, (int)range);
676 
678  vpDisplay::displayLine(I,vpImagePoint(list_query_pixels[0].ifloat,list_query_pixels[0].jfloat),vpImagePoint(list_query_pixels[2*range].ifloat,list_query_pixels[2*range].jfloat),vpColor::cyan);
679  vpDisplay::displayCross(I,vpImagePoint(list_query_pixels[0].ifloat,list_query_pixels[0].jfloat),5,vpColor::orange,3);
680 
681  for(unsigned int n = 0 ; n < 2 * range + 1 ; n++)
682  {
683  conv[n] = list_query_pixels[n].convolution(I, me);
684  }
685  delete [] list_query_pixels;
686 }
687 
688 #endif
689 
void set_j(const double j)
Definition: vpImagePoint.h:156
unsigned int getRange() const
Definition: vpMe.h:236
void init()
Definition: vpMeSite.cpp:73
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 convolution(const vpImage< unsigned char > &ima, const vpMe *me)
Definition: vpMeSite.cpp:301
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:76
void track(const vpImage< unsigned char > &I)
int outOfImage(int i, int j, int half, int rows, int cols)
void set_i(const double i)
Definition: vpImagePoint.h:145
double alpha
Definition: vpMeSite.h:104
int i
Definition: vpMeSite.h:98
Contains predetermined masks for sites and holds moving edges tracking parameters.
Definition: vpMe.h:70
int mask_sign
Definition: vpMeSite.h:102
void initTracking(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, double rho, double theta)
static const vpColor green
Definition: vpColor.h:170
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:192
#define vpDEBUG_ENABLE(niv)
Definition: vpDebug.h:502
double expecteddensity
Definition: vpMbtMeLine.h:74
vpMeSiteState getState() const
Definition: vpMeSite.h:202
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
static const vpColor orange
Definition: vpColor.h:177
double ifloat
Definition: vpMeSite.h:100
std::list< vpMeSite > list
Definition: vpMeTracker.h:80
Error that can be emited by the vpTracker class and its derivates.
void updateParameters(const vpImage< unsigned char > &I, double rho, double theta)
static const vpColor cyan
Definition: vpColor.h:176
static double sqr(double x)
Definition: vpMath.h:106
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void setDisplay(vpMeSiteDisplayType select)
Definition: vpMeSite.h:152
void track(const vpImage< unsigned char > &I)
Track sampled pixels.
Contains abstract elements for a Distance to Feature type feature.
Definition: vpMeTracker.h:71
vpMeSite * getQueryList(const vpImage< unsigned char > &I, const int range)
Definition: vpMeSite.cpp:218
#define vpCDEBUG(niv)
Definition: vpDebug.h:478
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:189
int j
Definition: vpMeSite.h:98
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
void initTracking(const vpImage< unsigned char > &I)
unsigned int getHeight() const
Definition: vpImage.h:150
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
double getSampleStep() const
Definition: vpMe.h:278
vpMeSite::vpMeSiteDisplayType selectDisplay
Definition: vpMeTracker.h:87
vpColVector p
Definition: vpTracker.h:78
static const vpColor blue
Definition: vpColor.h:173