Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpMe.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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  *
37  *****************************************************************************/
38 
46 #include <visp3/me/vpMe.h>
47 #include <visp3/core/vpColVector.h>
48 #include <visp3/core/vpMath.h>
49 #include <stdlib.h>
50 #ifndef DOXYGEN_SHOULD_SKIP_THIS
51 
52 
53 struct point
54 {
55  double x ;
56  double y ;
57 } ;
58 
59 struct droite
60 {
61  double a ;
62  double b ;
63  double c ;
64 } ;
65 
66 
67 
68 
69 
70 
71 
72 template <class Type>
73 inline void
74 permute(Type & a, Type & b)
75 {
76  Type t = a;
77  a = b;
78  b = t;
79 }
80 
81 static droite
82 droite_cartesienne(point P, point Q)
83 {
84  droite PQ;
85 
86  PQ.a = P.y-Q.y;
87  PQ.b = Q.x-P.x;
88  PQ.c = Q.y*P.x - Q.x*P.y;
89 
90  return(PQ);
91 }
92 
93 
94 
95 static point
96 point_intersection(droite D1, droite D2)
97 {
98  point I;
99  double det; // determinant des 2 vect.normaux
100 
101  det = (D1.a*D2.b - D2.a*D1.b); // interdit D1,D2 paralleles
102  I.x = (D2.c*D1.b - D1.c*D2.b)/det;
103  I.y = (D1.c*D2.a - D2.c*D1.a)/det;
104 
105  return(I);
106 }
107 
108 static void
109 recale(point & P,
110  double Xmin, double Ymin, double Xmax, double Ymax)
111 {
112  if(vpMath::equal(P.x,Xmin))
113  P.x=Xmin; // a peu pres => exactement !
114  if(vpMath::equal(P.x,Xmax))
115  P.x=Xmax;
116 
117  if(vpMath::equal(P.y,Ymin))
118  P.y=Ymin;
119  if(vpMath::equal(P.y,Ymax))
120  P.y=Ymax;
121 }
122 
123 
124 static void
125 permute(point &A, point &B)
126 {
127  point C ;
128 
129  if (A.x>B.x) // fonction sans doute a tester...
130  {
131  C = A ;
132  A = B ;
133  B = C ;
134  }
135 }
136 
137 
138 // vrai si partie visible
139 static bool
140 clipping (point A, point B,
141  double Xmin, double Ymin, double Xmax, double Ymax,
142  point & Ac , point & Bc )// resultat: A,B clippes
143 {
144  droite AB, D[4];
145  D[0].a = 1; D[0].b = 0; D[0].c = -Xmin;
146  D[1].a = 1; D[1].b = 0; D[1].c = -Xmax;
147  D[2].a = 0; D[2].b = 1; D[2].c = -Ymin;
148  D[3].a = 0; D[3].b = 1; D[3].c = -Ymax;
149 
150  point P[2];
151  P[0]=A; P[1]=B;
152  int code_P[2], // codes de P[n]
153  i, bit_i, // i -> (0000100...)
154  n;
155 
156  AB = droite_cartesienne(A,B);
157 
158  for ( ; ; ) // 2 sorties directes internes
159  {
160  // CALCULE CODE DE VISIBILITE (Sutherland & Sproul)
161  // ================================================
162  for(n=0; n<2; n++)
163  {
164  code_P[n] = 0000;
165 
166  if( P[n].x < Xmin )
167  code_P[n] |= 1; // positionne bit0
168  if( P[n].x > Xmax )
169  code_P[n] |= 2; // .. bit1
170  if( P[n].y < Ymin )
171  code_P[n] |= 4; // .. bit2
172  if( P[n].y > Ymax )
173  code_P[n] |= 8; // .. bit3
174  }
175 
176 
177  // 2 CAS OU L'ON PEUT CONCLURE => sortie
178  // =====================================
179  if((code_P[0] | code_P[1])==0000) // Aucun bit a 1
180  /* NE TRIE PLUS LE RESULTAT ! S_relative() en tient compte
181  { if(P[0].x < P[1].x) // Rend le couple de points
182  { Ac=P[0]; Bc=P[1]; } // clippes (ordonnes selon
183  else { Ac=P[1]; Bc=P[0]; } // leur abscisse x)
184  */
185  {
186  Ac=P[0]; Bc=P[1];
187  if(vpMath::equal(Ac.x,Bc.x) && vpMath::equal(Ac.y,Bc.y))
188  return(false); // AB = 1 point = invisible
189  else
190  return(true); // Partie de AB clippee visible!
191  }
192 
193  if((code_P[0] & code_P[1])!=0000) // au moins 1 bit commun
194  {
195  return(false); // AB completement invisible!
196  }
197 
198 
199  // CAS GENERAL (on sait que code_P[0 ou 1] a au moins un bit a 1
200  // - clippe le point P[n] qui sort de la fenetre (coupe Droite i)
201  // - reboucle avec le nouveau couple de points
202  // ================================================================
203  if(code_P[0] != 0000)
204  {
205  n=0; // c'est P[0] qu'on clippera
206  for(i=0,bit_i=1; !(code_P[0] & bit_i); i++,bit_i<<=1){;}
207  }
208  else
209  {
210  n=1; // c'est P[1] qu'on clippera
211  for(i=0,bit_i=1; !(code_P[1] & bit_i); i++,bit_i<<=1){;}
212  }
213 
214  P[n] = point_intersection(AB,D[i]); // clippe le point concerne
215 
216 
217  // RECALE EXACTEMENT LE POINT (calcul flottant => arrondi)
218  // AFIN QUE LE CALCUL DES CODES NE BOUCLE PAS INDEFINIMENT
219  // =======================================================
220  recale(P[n], Xmin,Ymin,Xmax,Ymax);
221 
222  }
223 
224 }
225 
226 
227 // calcule la surface relative des 2 portions definies
228 // par le segment PQ sur le carre Xmin,Ymin,Xmax,Ymax
229 // Rem : P,Q tries sur x, et donc seulement 6 cas
230 static double
231 S_relative(point P, point Q,
232  double Xmin, double Ymin, double Xmax, double Ymax)
233 {
234 
235  if(Q.x < P.x) // tri le couple de points
236  permute(P,Q); // selon leur abscisse x
237 
238 
239 
240  recale(P, Xmin,Ymin,Xmax,Ymax); // permet des calculs de S_relative
241  recale(Q, Xmin,Ymin,Xmax,Ymax); // moins approximatifs.
242 
243  //if(P.x==Xmin && Q.x==Xmax)
244  if((std::fabs(P.x-Xmin) <= vpMath::maximum(std::fabs(P.x),std::fabs(Xmin))*std::numeric_limits<double>::epsilon())
245  &&
246  (std::fabs(Q.x-Xmax) <= vpMath::maximum(std::fabs(Q.x),std::fabs(Xmax))*std::numeric_limits<double>::epsilon()))
247  return( fabs(Ymax+Ymin-P.y-Q.y) );
248 
249  //if( (P.y==Ymin && Q.y==Ymax) ||
250  // (Q.y==Ymin && P.y==Ymax))
251  if( ( (std::fabs(P.y-Ymin) <= vpMath::maximum(std::fabs(P.y),std::fabs(Ymin))*std::numeric_limits<double>::epsilon())
252  &&
253  (std::fabs(Q.y-Ymax) <= vpMath::maximum(std::fabs(Q.y),std::fabs(Ymax))*std::numeric_limits<double>::epsilon()) )
254  ||
255  ( (std::fabs(Q.y-Ymin) <= vpMath::maximum(std::fabs(Q.y),std::fabs(Ymin))*std::numeric_limits<double>::epsilon())
256  &&
257  (std::fabs(P.y-Ymax) <= vpMath::maximum(std::fabs(P.y),std::fabs(Ymax))*std::numeric_limits<double>::epsilon()) ) )
258  return( fabs(Xmax+Xmin-P.x-Q.x) );
259 
260  //if( P.x==Xmin && Q.y==Ymax )
261  if( std::fabs(P.x-Xmin) <= vpMath::maximum(std::fabs(P.x),std::fabs(Xmin))*std::numeric_limits<double>::epsilon()
262  &&
263  std::fabs(Q.y-Ymax) <= vpMath::maximum(std::fabs(Q.y),std::fabs(Ymax))*std::numeric_limits<double>::epsilon() )
264  return( 1-(Ymax-P.y)*(Q.x-Xmin) );
265  //if( P.x==Xmin && Q.y==Ymin )
266  if( std::fabs(P.x-Xmin) <= vpMath::maximum(std::fabs(P.x),std::fabs(Xmin))*std::numeric_limits<double>::epsilon()
267  &&
268  std::fabs(Q.y-Ymin) <= vpMath::maximum(std::fabs(Q.y),std::fabs(Ymin))*std::numeric_limits<double>::epsilon() )
269  return( 1-(P.y-Ymin)*(Q.x-Xmin) );
270  //if( P.y==Ymin && Q.x==Xmax )
271  if( std::fabs(P.y-Ymin) <= vpMath::maximum(std::fabs(P.y),std::fabs(Ymin))*std::numeric_limits<double>::epsilon()
272  && std::fabs(Q.x-Xmax) <= vpMath::maximum(std::fabs(Q.x),std::fabs(Xmax))*std::numeric_limits<double>::epsilon() )
273  return( 1-(Xmax-P.x)*(Q.y-Ymin) );
274  //if( P.y==Ymax && Q.x==Xmax )
275  if( std::fabs(P.y-Ymax) <= vpMath::maximum(std::fabs(P.y),std::fabs(Ymax))*std::numeric_limits<double>::epsilon()
276  && std::fabs(Q.x-Xmax) <= vpMath::maximum(std::fabs(Q.x),std::fabs(Xmax))*std::numeric_limits<double>::epsilon())
277  return( 1-(Xmax-P.x)*(Ymax-Q.y) );
278 
279 
280  printf("utils_ecm: ERREUR dans S_relative (%f,%f) (%f,%f) %f %f %f %f\n",
281  P.x,P.y,Q.x,Q.y,Xmin,Ymin,Xmax,Ymax);
282  exit(-1); // DEBUG Stoppe net l'execution
283 }
284 
285 
286 static void
287 calcul_masques(vpColVector &angle, // definitions des angles theta
288  unsigned int n, // taille masques (PAIRE ou IMPAIRE Ok)
289  vpMatrix *M) // resultat M[theta](n,n)
290 {
291  // Le coef |a| = |1/2n| n'est pas incorpore dans M(i,j) (=> que des int)
292 
293  unsigned int i_theta, // indice (boucle sur les masques)
294  i,j; // indices de boucle sur M(i,j)
295  double X,Y, // point correspondant/centre du masque
296  moitie = ((double)n)/2.0; // moitie REELLE du masque
297  point P1,Q1,P,Q; // clippe Droite(theta) P1,Q1 -> P,Q
298  int sgn; // signe de M(i,j)
299  double v; // ponderation de M(i,j)
300 
301  unsigned int nb_theta = angle.getRows() ;
302 
303  for(i_theta=0; i_theta<nb_theta; i_theta++)
304  {
305  double theta = M_PI/180*angle[i_theta]; // indice i -> theta(i) en radians
306  // angle[] dans [0,180[
307  double cos_theta = cos(theta); // vecteur directeur de l'ECM
308  double sin_theta = sin(theta); // associe au masque
309 
310  // PRE-CALCULE 2 POINTS DE D(theta) BIEN EN DEHORS DU MASQUE
311  // =========================================================
312  //if( angle[i_theta]==90 ) // => tan(theta) infinie !
313  if( std::fabs(angle[i_theta]-90) <= vpMath::maximum(std::fabs(angle[i_theta]), 90.)*std::numeric_limits<double>::epsilon() ) // => tan(theta) infinie !
314  {
315  P1.x=0; P1.y=-(int)n;
316  Q1.x=0; Q1.y= n;
317  }
318  else
319  {
320  double tan_theta = sin_theta/cos_theta; // pente de la droite D(theta)
321  P1.x=-(int)n; P1.y=tan_theta*(-(int)n);
322  Q1.x=n; Q1.y=tan_theta*n;
323  }
324 
325  // CALCULE MASQUE M(theta)
326  // ======================
327  M[i_theta].resize(n,n); // allocation (si necessaire)
328 
329  for(i=0,Y=-moitie+0.5 ; i<n ; i++,Y++)
330  {
331  for(j=0,X=-moitie+0.5 ; j<n ; j++,X++)
332  {
333  // produit vectoriel dir_droite*(X,Y)
334  sgn = vpMath::sign(cos_theta*Y - sin_theta*X);
335 
336  // Resultat = P,Q
337  if( clipping(P1,Q1, X-0.5,Y-0.5,X+0.5,Y+0.5, P,Q) )
338  {
339  // v dans [0,1]
340  v=S_relative(P,Q, X-0.5,Y-0.5,X+0.5,Y+0.5);
341  }
342  else
343  v=1; // PQ ne coupe pas le pixel(i,j)
344 
345  M[i_theta][i][j] = vpMath::round(100*sgn*v);
346 
347  // 2 chiffres significatifs
348  // M(i,j) sans incorporer le coef a
349  }
350  }
351  }
352 
353 }
354 
355 #endif
356 
362 void
364 {
365 
366  if (mask != NULL)
367  delete [] mask;
368 
369  mask = new vpMatrix[n_mask] ;
370 
371  vpColVector angle(n_mask) ;
372 
373  unsigned int angle_pas ;
374  angle_pas = 180 / n_mask ;
375 
376  unsigned int k =0 ;
377  for (unsigned int i = 0 ; /* i < 180, */ k < n_mask ; i += angle_pas)
378  angle[k++] = i ;
379 
380  calcul_masques(angle, mask_size, mask ) ;
381 
382 }
383 
384 
385 
386 void
388 {
389 
390  std::cout<< std::endl ;
391  std::cout<<"Moving edges settings " <<std::endl ;
392  std::cout<< std::endl ;
393  std::cout<<" Size of the convolution masks...."<<mask_size<<"x"<<mask_size<<" pixels"<<std::endl ;
394  std::cout<<" Number of masks.................."<<n_mask<<" "<<std::endl ;
395  std::cout<<" Query range +/- J................"<<range<<" pixels "<<std::endl ;
396  std::cout<<" Likelihood test ratio............"<<threshold<<std::endl ;
397  std::cout<<" Contrast tolerance +/-..........."<< mu1 * 100<<"% and "<<mu2 * 100<<"% "<<std::endl ;
398  std::cout<<" Sample step......................"<<sample_step<<" pixels"<<std::endl ;
399  std::cout<<" Strip............................"<<strip<<" pixels "<<std::endl ;
400  std::cout<<" Min_Samplestep..................."<<min_samplestep<<" pixels "<<std::endl ;
401 }
402 
404  : threshold(1500), mu1(0.5), mu2(0.5), min_samplestep(4), anglestep(1), mask_sign(0),
405  range(4), sample_step(10), ntotal_sample(0), points_to_track(500), mask_size(5),
406  n_mask(180), strip(2), mask(NULL)
407 {
408  //ntotal_sample = 0; // not sure that it is used
409  //points_to_track = 500; // not sure that it is used
410  anglestep = (180 / n_mask) ;
411 
412  initMask() ;
413 }
414 
415 vpMe::vpMe(const vpMe &me)
416  : threshold(1500), mu1(0.5), mu2(0.5), min_samplestep(4), anglestep(1), mask_sign(0),
417  range(4), sample_step(10), ntotal_sample(0), points_to_track(500), mask_size(5),
418  n_mask(180), strip(2), mask(NULL)
419 {
420  *this = me;
421 }
422 
424 const
426 {
427  if (mask != NULL) {
428  delete [] mask;
429  mask = NULL ;
430  }
431  threshold = me.threshold ;
432  mu1 = me.mu1 ;
433  mu2 = me.mu2 ;
435  anglestep = me.anglestep ;
436  mask_size = me.mask_size ;
437  n_mask = me.n_mask ;
438  mask_sign = me.mask_sign ;
439  range = me.range ;
440  sample_step = me.sample_step ;
443  strip = me.strip ;
444 
445  initMask() ;
446  return *this;
447 }
448 
449 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
450 const
453 {
454  if (mask != NULL) {
455  delete [] mask;
456  mask = NULL ;
457  }
458  threshold = std::move(me.threshold);
459  mu1 = std::move(me.mu1);
460  mu2 = std::move(me.mu2);
461  min_samplestep = std::move(me.min_samplestep);
462  anglestep = std::move(me.anglestep);
463  mask_size = std::move(me.mask_size);
464  n_mask = std::move(me.n_mask);
465  mask_sign = std::move(me.mask_sign);
466  range = std::move(me.range);
467  sample_step = std::move(me.sample_step);
468  ntotal_sample = std::move(me.ntotal_sample);
469  points_to_track = std::move(me.points_to_track);
470  strip = std::move(me.strip);
471 
472  initMask() ;
473  return *this;
474 }
475 #endif
476 
478 {
479  if (mask != NULL)
480  {
481  delete [] mask ;
482  mask = NULL;
483  }
484 }
485 
486 
487 void
488 vpMe::setMaskNumber(const unsigned int &n)
489 {
490  n_mask = n ;
491  anglestep = 180 / n_mask ;
492  initMask() ;
493 }
494 
495 void
496 vpMe::setMaskSize(const unsigned int &s)
497 {
498  mask_size = s ;
499  initMask() ;
500 }
501 
502 
503 
504 
double threshold
Definition: vpMe.h:66
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:97
const vpMe & operator=(const vpMe &me)
Copy operator.
Definition: vpMe.cpp:425
void resize(const unsigned int nrows, const unsigned int ncols, const bool flagNullify=true)
Definition: vpArray2D.h:167
vpMatrix * mask
Definition: vpMe.h:86
unsigned int range
Definition: vpMe.h:72
void setMaskNumber(const unsigned int &a)
Definition: vpMe.cpp:488
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:306
int ntotal_sample
Distance between sampled points (in pixels)
Definition: vpMe.h:74
Definition: vpMe.h:59
int mask_sign
Definition: vpMe.h:71
static int round(const double x)
Definition: vpMath.h:249
void initMask()
Definition: vpMe.cpp:363
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:140
unsigned int mask_size
convolution masks' size in pixels (masks are square),
Definition: vpMe.h:77
void setMaskSize(const unsigned int &a)
Definition: vpMe.cpp:496
int points_to_track
Definition: vpMe.h:75
virtual ~vpMe()
Definition: vpMe.cpp:477
vpMe()
Array of matrices defining the different masks (one for every angle step).
Definition: vpMe.cpp:403
unsigned int getRows() const
Return the number of rows of the 2D array.
Definition: vpArray2D.h:152
double min_samplestep
Contrast continuity parameter (right boundary)
Definition: vpMe.h:69
unsigned int n_mask
the number of convolution masks available for tracking ; defines resolution.
Definition: vpMe.h:79
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
int strip
Definition: vpMe.h:84
double mu1
Likelihood ratio threshold.
Definition: vpMe.h:67
double mu2
Contrast continuity parameter (left boundary)
Definition: vpMe.h:68
void print()
Definition: vpMe.cpp:387
unsigned int anglestep
Definition: vpMe.h:70
static int() sign(double x)
Definition: vpMath.h:275
double sample_step
Seek range - on both sides of the reference pixel.
Definition: vpMe.h:73