Visual Servoing Platform  version 3.0.0
vpMeSite.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Moving edges.
32  *
33  * Authors:
34  * Eric Marchand
35  * Andrew Comport
36  * Aurelien Yol
37  *
38  *****************************************************************************/
39 
47 #include <visp3/me/vpMeSite.h>
48 #include <visp3/me/vpMe.h>
49 #include <visp3/core/vpTrackingException.h>
50 #include <stdlib.h>
51 #include <cmath> // std::fabs
52 #include <limits> // numeric_limits
53 #include <visp3/me/vpMeSite.h>
54 
55 
56 #ifndef DOXYGEN_SHOULD_SKIP_THIS
57 static
58 bool horsImage(int i , int j, int half, int rows, int cols)
59 {
60  //return((i < half + 1) || ( i > (rows - half - 3) )||(j < half + 1) || (j > (cols - half - 3) )) ;
61  int half_1 = half + 1;
62  int half_3 = half + 3;
63  //return((i < half + 1) || ( i > (rows - half - 3) )||(j < half + 1) || (j > (cols - half - 3) )) ;
64  return( (0 < (half_1 - i) ) || ( (i - rows + half_3) > 0 ) || ( 0 < (half_1 -j) ) || ( (j - cols + half_3) > 0 ) ) ;
65 }
66 #endif
67 
68 void
70 {
71  // Site components
72  alpha = 0.0 ;
73  convlt = 0.0 ;
74  weight=-1;
75 
76  selectDisplay = NONE ;
77 
78  // Pixel components
79  i = 0 ;
80  j = 0 ;
81  v = 0 ;
82  ifloat =i ;
83  jfloat = j ;
84  i_1 = 0 ;
85  j_1 = 0 ;
86 
87  mask_sign = 1 ;
88 
89  normGradient = 0;
90 
91  state = NO_SUPPRESSION;
92 
93 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
94  suppress = 0;
95 #endif
96 }
97 
99  : i(0), j(0), i_1(0), j_1(0), ifloat(0), jfloat(0), v(0), mask_sign(1), alpha(0.),
100  convlt(0.), normGradient(0), weight(1), selectDisplay(NONE), state(NO_SUPPRESSION)
101 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
102  , suppress(0)
103 #endif
104 {
105 }
106 
107 vpMeSite::vpMeSite(double ip, double jp)
108  : i(0), j(0), i_1(0), j_1(0), ifloat(0), jfloat(0), v(0), mask_sign(1), alpha(0.),
109  convlt(0.), normGradient(0), weight(1), selectDisplay(NONE), state(NO_SUPPRESSION)
110 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
111  , suppress(0)
112 #endif
113 {
114  i = vpMath::round(ip) ;
115  j = vpMath::round(jp) ;
116  ifloat = ip ;
117  jfloat = jp ;
118 }
119 
124  : i(0), j(0), i_1(0), j_1(0), ifloat(0), jfloat(0), v(0), mask_sign(1), alpha(0.),
125  convlt(0.), normGradient(0), weight(1), selectDisplay(NONE), state(NO_SUPPRESSION)
126 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
127  , suppress(0)
128 #endif
129 {
130  *this = mesite;
131 }
132 
133 // More an Update than init
134 // For points in meter form (to avoid approximations)
135 void
136 vpMeSite::init(double ip, double jp, double alphap)
137 {
138  // Note: keep old value of convlt, suppress and contrast
139  selectDisplay = NONE ;
140 
141  ifloat = ip;
142  i= vpMath::round(ip);
143  jfloat = jp ;
144  j = vpMath::round(jp);
145  alpha = alphap ;
146  mask_sign =1 ;
147 
148  v = 0 ;
149  i_1 = 0 ;
150  j_1 = 0 ;
151 
152 }
153 
154 // initialise with convolution
155 void
156 vpMeSite::init(double ip, double jp, double alphap, double convltp)
157 {
158  selectDisplay = NONE ;
159  ifloat = ip ;
160  i= (int)ip ;
161  jfloat = jp ;
162  j =(int)jp ;
163  alpha = alphap ;
164  convlt = convltp;
165  mask_sign =1 ;
166 
167  v = 0 ;
168  i_1 = 0 ;
169  j_1 = 0 ;
170 }
171 // initialise with convolution and sign
172 void
173 vpMeSite::init(double ip, double jp, double alphap, double convltp, int sign)
174 {
175  selectDisplay = NONE ;
176  ifloat = ip ;
177  i= (int)ip ;
178  jfloat = jp ;
179  j =(int)jp ;
180  alpha = alphap ;
181  convlt = convltp;
182  mask_sign = sign ;
183 
184  v = 0 ;
185  i_1 = 0 ;
186  j_1 = 0 ;
187 }
188 
190 {
191  i = m.i;
192  j = m.j;
193  i_1 = m.i_1;
194  j_1 = m.j_1;
195  ifloat = m.ifloat;
196  jfloat = m.jfloat;
197  v = m.v;
198  mask_sign = m.mask_sign;
199  alpha = m.alpha;
200  convlt = m.convlt;
202  weight = m.weight;
203  selectDisplay = m.selectDisplay;
204  state = m.state;
205 
206 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
207  suppress = m.suppress;
208 #endif
209 
210  return *this ;
211 }
212 
213 
214 // ===================================================================
222 // ===================================================================
223 
224 vpMeSite*
226 {
227 
228  int k ;
229 
230  int n;
231  double ii , jj ;
232  vpMeSite *list_query_pixels ;
233  list_query_pixels = NULL ;
234 
235  unsigned int range_ = static_cast<unsigned int>(range);
236  // Size of query list includes the point on the line
237  list_query_pixels = new vpMeSite[2 * range_ + 1] ;
238 
239  // range : +/- the range within which the pixel's
240  //correspondent will be sought
241 
242  double salpha = sin(alpha);
243  double calpha = cos(alpha);
244  n = 0 ;
245  vpImagePoint ip;
246 
247  for(k = -range ; k <= range ; k++)
248  {
249  ii = (ifloat+k*salpha);
250  jj = (jfloat+k*calpha);
251 
252  // Display
253  if ((selectDisplay==RANGE_RESULT)||(selectDisplay==RANGE)) {
254  ip.set_i( ii );
255  ip.set_j( jj );
257  }
258 
259  // Copy parent's convolution
260  vpMeSite pel ;
261  pel.init(ii, jj, alpha, convlt,mask_sign) ;
262  pel.setDisplay(selectDisplay) ;// Display
263 
264  // Add site to the query list
265  list_query_pixels[n] = pel ;
266  n++ ;
267  }
268 
269  return(list_query_pixels) ;
270 }
271 
272 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
273 // ===================================================================
281 // ===================================================================
282 void
283 vpMeSite::getSign(const vpImage<unsigned char> &I, const int range)
284 {
285 
286  int k ;
287 
288  double salpha = sin(alpha);
289  double calpha = cos(alpha);
290 
291  //First extremity
292  k = -range ;
293  unsigned int i1 = static_cast<unsigned int>(vpMath::round(ifloat+k*salpha));
294  unsigned int j1 = static_cast<unsigned int>(vpMath::round(jfloat+k*calpha));
295 
296  //Second extremity
297  k = range ;
298  unsigned int i2 = static_cast<unsigned int>(vpMath::round(ifloat+k*salpha));
299  unsigned int j2 = static_cast<unsigned int>(vpMath::round(jfloat+k*calpha));
300 
301  // TODO: Here check if i1,j1,i2,j2 > 0 else ??
302  if (I[i1][j1] > I[i2][j2]) mask_sign = 1 ; else mask_sign = -1 ;
303 }
304 #endif
305 
306 // Specific function for ME
307 double
309 {
310  int half;
311  unsigned int index_mask ;
312  int height_ = static_cast<int>(I.getHeight());
313  int width_ = static_cast<int>(I.getWidth());
314 
315  double conv = 0.0 ;
316  unsigned int msize = me->getMaskSize();
317  half = (static_cast<int>(msize) - 1) >> 1 ;
318 
319  if(horsImage( i , j , half + me->getStrip() , height_, width_))
320  {
321  conv = 0.0 ;
322  i = 0 ; j = 0 ;
323  }
324  else
325  {
326  // Calculate tangent angle from normal
327  double theta = alpha+M_PI/2;
328  // Move tangent angle to within 0->M_PI for a positive
329  // mask index
330  while (theta<0) theta += M_PI;
331  while (theta>M_PI) theta -= M_PI;
332 
333  // Convert radians to degrees
334  int thetadeg = vpMath::round(theta * 180 / M_PI) ;
335 
336  if(abs(thetadeg) == 180 )
337  {
338  thetadeg= 0 ;
339  }
340 
341  index_mask = (unsigned int)(thetadeg/(double)me->getAngleStep());
342 
343  unsigned int i_ = static_cast<unsigned int>(i);
344  unsigned int j_ = static_cast<unsigned int>(j);
345  unsigned int half_ = static_cast<unsigned int>(half);
346 
347  unsigned int ihalf = i_-half_ ;
348  unsigned int jhalf = j_-half_ ;
349  unsigned int ihalfa ;
350 
351  for(unsigned int a = 0 ; a < msize ; a++ )
352  {
353  ihalfa = ihalf+a ;
354  for(unsigned int b = 0 ; b < msize ; b++ )
355  {
356  conv += mask_sign* me->getMask()[index_mask][a][b] *
357  // I(i-half+a,j-half+b) ;
358  I(ihalfa,jhalf+b) ;
359  }
360  }
361 
362  }
363 
364  return(conv) ;
365 }
366 
367 
376 void
378  const vpMe *me,
379  const bool test_contraste)
380 {
381  // vpMeSite *list_query_pixels ;
382  // int max_rank =0 ;
383  // int max_rank1=0 ;
384  // int max_rank2 = 0;
385  // double convolution = 0 ;
386  // double max_convolution = 0 ;
387  // double max = 0 ;
388  // double contraste = 0;
389  // // vpDisplay::display(I) ;
390  // // vpERROR_TRACE("getclcik %d",me->getRange()) ;
391  // // vpDisplay::getClick(I) ;
392  //
393  // // range = +/- range of pixels within which the correspondent
394  // // of the current pixel will be sought
395  // int range = me->getRange() ;
396  //
397  // // std::cout << i << " " << j<<" " << range << " " << suppress << std::endl ;
398  // list_query_pixels = getQueryList(I, range) ;
399  //
400  // double contraste_max = 1 + me->getMu2();
401  // double contraste_min = 1 - me->getMu1();
402  //
403  // // array in which likelihood ratios will be stored
404  // double *likelihood= new double[ 2 * range + 1 ] ;
405  //
406  // int ii_1 = i ;
407  // int jj_1 = j ;
408  // i_1 = i ;
409  // j_1 = j ;
410  // double threshold;
411  // threshold = me->getThreshold();
412  //
413  // // std::cout <<"---------------------"<<std::endl ;
414  // for(int n = 0 ; n < 2 * range + 1 ; n++)
415  // {
416  //
417  // // convolution results
418  // convolution = list_query_pixels[n].convolution(I, me) ;
419  //
420  // // luminance ratio of reference pixel to potential correspondent pixel
421  // // the luminance must be similar, hence the ratio value should
422  // // lay between, for instance, 0.5 and 1.5 (parameter tolerance)
423  // if( test_contraste )
424  // {
425  // // Include this to eliminate temporal calculation
426  // if (convlt==0)
427  // {
428  // std::cout << "vpMeSite::track : Division by zero convlt = 0" << std::endl ;
429  // delete []list_query_pixels ;
430  // delete []likelihood;
431  // throw(vpTrackingException(vpTrackingException::initializationError,
432  // "Division by zero")) ;
433  // }
434  //
435  // // contraste = fabs(convolution / convlt) ;
436  // contraste = convolution / convlt ;
437  // // likelihood ratios
438  // if((contraste > contraste_min) && (contraste < contraste_max))
439  // likelihood[n] = fabs(convolution + convlt ) ;
440  // else
441  // likelihood[n] = 0 ;
442  // }
443  // else
444  // likelihood[n] = fabs(2*convolution) ;
445  //
446  //
447  // // establishment of the maximal likelihood ratios's rank
448  // // in the array, the value of the likelihood ratio can now be
449  // // referenced by its rank in the array
450  // if (likelihood[n] > max)
451  // {
452  // max_convolution= convolution;
453  // max = likelihood[n] ;
454  // max_rank = n ;
455  // max_rank2 = max_rank1;
456  // max_rank1 = max_rank;
457  // }
458  //
459  // }
460  //
461  // // test on the likelihood threshold if threshold==-1 then
462  // // the me->threshold is selected
463  //
464  // vpImagePoint ip;
465  //
466  // // if (test_contrast)
467  // if(max > threshold)
468  // {
469  // if ((selectDisplay==RANGE_RESULT)||(selectDisplay==RESULT))
470  // {
471  // ip.set_i( list_query_pixels[max_rank].i );
472  // ip.set_j( list_query_pixels[max_rank].j );
473  // vpDisplay::displayPoint(I, ip, vpColor::red);
474  // }
475  //
476  // *this = list_query_pixels[max_rank] ;//The vpMeSite is replaced by the vpMeSite of max likelihood
477  // normGradient = vpMath::sqr(max_convolution);
478  //
479  // convlt = max_convolution;
480  // i_1 = ii_1; //list_query_pixels[max_rank].i ;
481  // j_1 = jj_1; //list_query_pixels[max_rank].j ;
482  // delete []list_query_pixels ;
483  // delete []likelihood;
484  // }
485  // else //none of the query sites is better than the threshold
486  // {
487  // if ((selectDisplay==RANGE_RESULT)||(selectDisplay==RESULT))
488  // {
489  // ip.set_i( list_query_pixels[max_rank].i );
490  // ip.set_j( list_query_pixels[max_rank].j );
491  // vpDisplay::displayPoint(I, ip, vpColor::green);
492  // }
493  // normGradient = 0 ;
494  // if(max == 0)
495  // suppress = 1; // contrast suppression
496  // else
497  // suppress = 2; // threshold suppression
498  //
499  // delete []list_query_pixels ;
500  // delete []likelihood; // modif portage
501  // }
502 
503  vpMeSite *list_query_pixels ;
504  int max_rank =-1 ;
505  // int max_rank1=-1 ;
506  // int max_rank2 = -1;
507  double convolution_ = 0 ;
508  double max_convolution = 0 ;
509  double max = 0 ;
510  double contraste = 0;
511  // vpDisplay::display(I) ;
512  // vpERROR_TRACE("getclcik %d",me->range) ;
513  // vpDisplay::getClick(I) ;
514 
515  // range = +/- range of pixels within which the correspondent
516  // of the current pixel will be sought
517  unsigned int range = me->getRange() ;
518 
519  // std::cout << i << " " << j<<" " << range << " " << suppress << std::endl ;
520  list_query_pixels = getQueryList(I, (int)range) ;
521 
522  double contraste_max = 1 + me->getMu2();
523  double contraste_min = 1 - me->getMu1();
524 
525  // array in which likelihood ratios will be stored
526  double *likelihood= new double[ 2 * range + 1 ] ;
527 
528  int ii_1 = i ;
529  int jj_1 = j ;
530  i_1 = i ;
531  j_1 = j ;
532  double threshold;
533  threshold = me->getThreshold() ;
534  double diff = 1e6;
535 
536  // std::cout <<"---------------------"<<std::endl ;
537  for(unsigned int n = 0 ; n < 2 * range + 1 ; n++)
538  {
539  // convolution results
540  convolution_ = list_query_pixels[n].convolution(I, me) ;
541 
542  // luminance ratio of reference pixel to potential correspondent pixel
543  // the luminance must be similar, hence the ratio value should
544  // lay between, for instance, 0.5 and 1.5 (parameter tolerance)
545  if( test_contraste )
546  {
547  likelihood[n] = fabs(convolution_ + convlt );
548  if (likelihood[n]> threshold)
549  {
550  contraste = convolution_ / convlt;
551  if((contraste > contraste_min) && (contraste < contraste_max) && fabs(1-contraste) < diff)
552  {
553  diff = fabs(1-contraste);
554  max_convolution= convolution_;
555  max = likelihood[n] ;
556  max_rank = (int)n ;
557  // max_rank2 = max_rank1;
558  // max_rank1 = max_rank;
559  }
560  }
561  }
562 
563  else
564  {
565  likelihood[n] = fabs(2*convolution_) ;
566  if (likelihood[n] > max && likelihood[n] > threshold)
567  {
568  max_convolution= convolution_;
569  max = likelihood[n] ;
570  max_rank = (int)n ;
571  // max_rank2 = max_rank1;
572  // max_rank1 = max_rank;
573  }
574  }
575  }
576 
577  // test on the likelihood threshold if threshold==-1 then
578  // the me->threshold is selected
579 
580  vpImagePoint ip;
581 
582  // if (test_contrast)
583  if(max_rank >= 0)
584  {
585  if ((selectDisplay==RANGE_RESULT)||(selectDisplay==RESULT))
586  {
587  ip.set_i( list_query_pixels[max_rank].i );
588  ip.set_j( list_query_pixels[max_rank].j );
590  }
591 
592  *this = list_query_pixels[max_rank] ;//The vpMeSite2 is replaced by the vpMeSite2 of max likelihood
593  normGradient = vpMath::sqr(max_convolution);
594 
595  convlt = max_convolution;
596  i_1 = ii_1; //list_query_pixels[max_rank].i ;
597  j_1 = jj_1; //list_query_pixels[max_rank].j ;
598  delete []list_query_pixels ;
599  delete []likelihood;
600  }
601  else //none of the query sites is better than the threshold
602  {
603  if ((selectDisplay==RANGE_RESULT)||(selectDisplay==RESULT))
604  {
605  ip.set_i( list_query_pixels[0].i );
606  ip.set_j( list_query_pixels[0].j );
608  }
609  normGradient = 0 ;
610  //if(contraste != 0)
611  if(std::fabs(contraste) > std::numeric_limits<double>::epsilon())
612  state = CONSTRAST; // contrast suppression
613  else
614  state = THRESHOLD; // threshold suppression
615 
616  delete []list_query_pixels ;
617  delete []likelihood; // modif portage
618  }
619 }
620 
622 {
623  return((m.i != i) || (m.j != j)) ;
624 
625 }
626 
627 VISP_EXPORT std::ostream& operator<<(std::ostream& os, vpMeSite& vpMeS)
628 {
629 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
630  return (os << "Alpha: " << vpMeS.alpha
631  << " Convolution: " << vpMeS.convlt
632  << " Flag: " << vpMeS.suppress
633  << " Weight: " << vpMeS.weight );
634 #else
635  return (os << "Alpha: " << vpMeS.alpha
636  << " Convolution: " << vpMeS.convlt
637  << " Weight: " << vpMeS.weight );
638 #endif
639 }
640 
642 {
644 }
645 
646 //Static functions
647 
663 void vpMeSite::display(const vpImage<unsigned char>& I, const double &i, const double &j, const vpMeSiteState &state)
664 {
665  switch(state)
666  {
667  case NO_SUPPRESSION:
669  break;
670 
671  case CONSTRAST:
673  break;
674 
675  case THRESHOLD:
677  break;
678 
679  case M_ESTIMATOR:
681  break;
682 
683  case TOO_NEAR:
685  break;
686 
687  default:
689  }
690 }
691 
707 void vpMeSite::display(const vpImage<vpRGBa>& I, const double &i, const double &j, const vpMeSiteState &state)
708 {
709  switch(state)
710  {
711  case NO_SUPPRESSION:
713  break;
714 
715  case CONSTRAST:
717  break;
718 
719  case THRESHOLD:
721  break;
722 
723  case M_ESTIMATOR:
725  break;
726 
727  case TOO_NEAR:
729  break;
730 
731  default:
733  }
734 }
unsigned int getRange() const
Definition: vpMe.h:225
unsigned int getMaskSize() const
Definition: vpMe.h:153
void init()
Definition: vpMeSite.cpp:69
unsigned int getWidth() const
Definition: vpImage.h:161
double jfloat
Definition: vpMeSite.h:96
void display(const vpImage< unsigned char > &I)
Definition: vpMeSite.cpp:641
double getMu1() const
Definition: vpMe.h:167
double convolution(const vpImage< unsigned char > &ima, const vpMe *me)
Definition: vpMeSite.cpp:308
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:72
double alpha
Definition: vpMeSite.h:100
int i
Definition: vpMeSite.h:94
Definition: vpMe.h:59
int mask_sign
Definition: vpMeSite.h:98
double normGradient
Definition: vpMeSite.h:104
static const vpColor green
Definition: vpColor.h:166
static int round(const double x)
Definition: vpMath.h:248
static const vpColor red
Definition: vpColor.h:163
vpMeSite()
Definition: vpMeSite.cpp:98
double ifloat
Definition: vpMeSite.h:96
int suppress
Definition: vpMeSite.h:253
int getStrip() const
Definition: vpMe.h:281
double getThreshold() const
Definition: vpMe.h:295
void set_i(const double ii)
Definition: vpImagePoint.h:154
unsigned int getAngleStep() const
Definition: vpMe.h:239
static const vpColor cyan
Definition: vpColor.h:172
static double sqr(double x)
Definition: vpMath.h:110
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void setDisplay(vpMeSiteDisplayType select)
Definition: vpMeSite.h:148
double convlt
Definition: vpMeSite.h:102
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:267
unsigned char v
Definition: vpMeSite.h:97
vpMeSite * getQueryList(const vpImage< unsigned char > &I, const int range)
Definition: vpMeSite.cpp:225
vp_deprecated void getSign(const vpImage< unsigned char > &I, const int range)
Definition: vpMeSite.cpp:283
int j_1
Definition: vpMeSite.h:95
vpMatrix * getMask() const
Definition: vpMe.h:105
void set_j(const double jj)
Definition: vpImagePoint.h:165
double getMu2() const
Definition: vpMe.h:181
int j
Definition: vpMeSite.h:94
double weight
Definition: vpMeSite.h:106
vpMeSite & operator=(const vpMeSite &m)
Definition: vpMeSite.cpp:189
void track(const vpImage< unsigned char > &im, const vpMe *me, const bool test_contraste=true)
Definition: vpMeSite.cpp:377
unsigned int getHeight() const
Definition: vpImage.h:152
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
int i_1
Definition: vpMeSite.h:95
static const vpColor yellow
Definition: vpColor.h:171
static const vpColor purple
Definition: vpColor.h:174
int operator!=(const vpMeSite &m)
Definition: vpMeSite.cpp:621
virtual void displayPoint(const vpImagePoint &ip, const vpColor &color)=0
vpMeSiteState
Definition: vpMeSite.h:83
static const vpColor blue
Definition: vpColor.h:169