Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
vpMeSite.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
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 https://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 
39 #include <cmath> // std::fabs
40 #include <limits> // numeric_limits
41 #include <stdlib.h>
42 #include <map>
43 
44 #include <visp3/core/vpTrackingException.h>
45 #include <visp3/me/vpMe.h>
46 #include <visp3/me/vpMeSite.h>
47 
48 BEGIN_VISP_NAMESPACE
49 
50 #ifndef DOXYGEN_SHOULD_SKIP_THIS
51 
52 struct vpMeSiteHypothesis
53 {
54  vpMeSiteHypothesis(vpMeSite *site, double l, double c) : site(site), likelihood(l), contrast(c)
55  { }
56 
57  vpMeSite *site;
58  double likelihood;
59  double contrast;
60 };
61 
62 static bool horsImage(int i, int j, int half, int rows, int cols)
63 {
64  int half_1 = half + 1;
65  int half_3 = half + 3;
66  return ((0 < (half_1 - i)) || (((i - rows) + half_3) > 0) || (0 < (half_1 - j)) || (((j - cols) + half_3) > 0));
67 }
68 #endif
69 
71 {
72  // Site components
73  m_alpha = 0.0;
74  m_convlt = 0.0;
75  m_weight = -1;
76  m_contrastThreshold = 10000.0;
77 
78  m_selectDisplay = NONE;
79 
80  // Pixel components
81  m_i = 0;
82  m_j = 0;
83  m_ifloat = m_i;
84  m_jfloat = m_j;
85 
86  m_mask_sign = 1;
87 
88  m_normGradient = 0;
89 
90  m_state = NO_SUPPRESSION;
91 }
92 
94  : m_i(0), m_j(0), m_ifloat(0), m_jfloat(0), m_mask_sign(1), m_alpha(0.), m_convlt(0.), m_normGradient(0),
95  m_weight(1), m_contrastThreshold(10000.0), m_selectDisplay(NONE), m_state(NO_SUPPRESSION)
96 { }
97 
98 vpMeSite::vpMeSite(const double &ip, const double &jp)
99  : m_i(0), m_j(0), m_ifloat(0), m_jfloat(0), m_mask_sign(1), m_alpha(0.), m_convlt(0.), m_normGradient(0),
100  m_weight(1), m_contrastThreshold(10000.0), m_selectDisplay(NONE), m_state(NO_SUPPRESSION)
101 {
102  m_i = vpMath::round(ip);
103  m_j = vpMath::round(jp);
104  m_ifloat = ip;
105  m_jfloat = jp;
106 }
107 
109  : m_i(0), m_j(0), m_ifloat(0), m_jfloat(0), m_mask_sign(1), m_alpha(0.), m_convlt(0.), m_normGradient(0),
110  m_weight(1), m_contrastThreshold(10000.0), m_selectDisplay(NONE), m_state(NO_SUPPRESSION)
111 {
112  *this = mesite;
113 }
114 
115 // More an Update than init
116 // For points in meter form (to avoid approximations)
117 void vpMeSite::init(const double &ip, const double &jp, const double &alphap)
118 {
119  // Note: keep old value of m_convlt, contrast and threshold
120  m_selectDisplay = NONE;
121 
122  m_ifloat = ip;
123  m_i = vpMath::round(ip);
124  m_jfloat = jp;
125  m_j = vpMath::round(jp);
126  m_alpha = alphap;
127  m_mask_sign = 1;
128 }
129 
130 // initialise with convolution()
131 void vpMeSite::init(const double &ip, const double &jp, const double &alphap, const double &convltp)
132 {
133  m_selectDisplay = NONE;
134  m_ifloat = ip;
135  m_i = static_cast<int>(ip);
136  m_jfloat = jp;
137  m_j = static_cast<int>(jp);
138  m_alpha = alphap;
139  m_convlt = convltp;
140  m_mask_sign = 1;
141 }
142 
143 // initialise with convolution and sign
144 void vpMeSite::init(const double &ip, const double &jp, const double &alphap, const double &convltp, const int &sign)
145 {
146  m_selectDisplay = NONE;
147  m_ifloat = ip;
148  m_i = static_cast<int>(ip);
149  m_jfloat = jp;
150  m_j = static_cast<int>(jp);
151  m_alpha = alphap;
152  m_convlt = convltp;
153  m_mask_sign = sign;
154 }
155 
156 // initialise with convolution and sign
157 void vpMeSite::init(const double &ip, const double &jp, const double &alphap, const double &convltp, const int &sign, const double &contrastThreshold)
158 {
159  m_selectDisplay = NONE;
160  m_ifloat = ip;
161  m_i = static_cast<int>(ip);
162  m_jfloat = jp;
163  m_j = static_cast<int>(jp);
164  m_alpha = alphap;
165  m_convlt = convltp;
166  m_mask_sign = sign;
167  m_contrastThreshold = contrastThreshold;
168 }
169 
171 {
172  m_i = m.m_i;
173  m_j = m.m_j;
174  m_ifloat = m.m_ifloat;
175  m_jfloat = m.m_jfloat;
177  m_alpha = m.m_alpha;
178  m_convlt = m.m_convlt;
180  m_weight = m.m_weight;
182  m_selectDisplay = m.m_selectDisplay;
183  m_state = m.m_state;
184 
185  return *this;
186 }
187 
188 vpMeSite *vpMeSite::getQueryList(const vpImage<unsigned char> &I, const int &range) const
189 {
190  unsigned int range_ = static_cast<unsigned int>(range);
191  // Size of query list includes the point on the line
192  vpMeSite *list_query_pixels = new vpMeSite[(2 * range_) + 1];
193 
194  // range : +/- the range within which the pixel's
195  // correspondent will be sought
196 
197  double salpha = sin(m_alpha);
198  double calpha = cos(m_alpha);
199  int n = 0;
200  vpImagePoint ip;
201 
202  for (int k = -range; k <= range; ++k) {
203  double ii = m_ifloat + (k * salpha);
204  double jj = m_jfloat + (k * calpha);
205 
206  // Display
207  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RANGE)) {
208  ip.set_i(ii);
209  ip.set_j(jj);
211  }
212 
213  // Copy parent's convolution
214  vpMeSite pel;
216  pel.setDisplay(m_selectDisplay); // Display
217 
218  // Add site to the query list
219  list_query_pixels[n] = pel;
220  ++n;
221  }
222 
223  return list_query_pixels;
224 }
225 
226 // Specific function for ME
228 {
229  int half;
230  int height_ = static_cast<int>(I.getHeight());
231  int width_ = static_cast<int>(I.getWidth());
232 
233  double conv = 0.0;
234  unsigned int msize = me->getMaskSize();
235  half = static_cast<int>((msize - 1) >> 1);
236 
237  if (horsImage(m_i, m_j, half + me->getStrip(), height_, width_)) {
238  conv = 0.0;
239  m_i = 0;
240  m_j = 0;
241  }
242  else {
243  // Calculate tangent angle from normal
244  double theta = m_alpha + (M_PI / 2);
245  // Move tangent angle to within 0->M_PI for a positive
246  // mask index
247  while (theta < 0) {
248  theta += M_PI;
249  }
250  while (theta > M_PI) {
251  theta -= M_PI;
252  }
253 
254  // Convert radians to degrees
255  int thetadeg = vpMath::round((theta * 180) / M_PI);
256 
257  const int flatAngle = 180;
258  if (abs(thetadeg) == flatAngle) {
259  thetadeg = 0;
260  }
261 
262  unsigned int index_mask = static_cast<unsigned int>(thetadeg / static_cast<double>(me->getAngleStep()));
263 
264  unsigned int i_ = static_cast<unsigned int>(m_i);
265  unsigned int j_ = static_cast<unsigned int>(m_j);
266  unsigned int half_ = static_cast<unsigned int>(half);
267 
268  unsigned int ihalf = i_ - half_;
269  unsigned int jhalf = j_ - half_;
270 
271  for (unsigned int a = 0; a < msize; ++a) {
272  unsigned int ihalfa = ihalf + a;
273  for (unsigned int b = 0; b < msize; ++b) {
274  conv += m_mask_sign * me->getMask()[index_mask][a][b] * I(ihalfa, jhalf + b);
275  }
276  }
277  }
278 
279  return conv;
280 }
281 
282 void vpMeSite::track(const vpImage<unsigned char> &I, const vpMe *me, const bool &test_contrast)
283 {
284  int max_rank = -1;
285  double max_convolution = 0;
286  double max = 0;
287  double contrast = 0;
288 
289  // range = +/- range of pixels within which the correspondent
290  // of the current pixel will be sought
291  unsigned int range = me->getRange();
292  const unsigned int normalSides = 2;
293  const unsigned int numQueries = range * normalSides + 1;
294 
295  vpMeSite *list_query_pixels = getQueryList(I, static_cast<int>(range));
296 
297  double contrast_max = 1 + me->getMu2();
298  double contrast_min = 1 - me->getMu1();
299 
300  double threshold = computeFinalThreshold(*me);
301 
302  if (test_contrast) {
303  double diff = 1e6;
304  for (unsigned int n = 0; n < numQueries; ++n) {
305  // convolution results
306 
307  double convolution_ = list_query_pixels[n].convolution(I, me);
308  // luminance ratio of reference pixel to potential correspondent pixel
309  // the luminance must be similar, hence the ratio value should
310  // lay between, for instance, 0.5 and 1.5 (parameter tolerance)
311  const double likelihood = fabs(convolution_ + m_convlt);
312 
313  if (likelihood > threshold) {
314  contrast = convolution_ / m_convlt;
315  if ((contrast > contrast_min) && (contrast < contrast_max) && (fabs(1 - contrast) < diff)) {
316  diff = fabs(1 - contrast);
317  max_convolution = convolution_;
318  max = likelihood;
319  max_rank = static_cast<int>(n);
320  }
321  }
322  }
323  }
324  else { // test on contrast only
325  for (unsigned int n = 0; n < numQueries; ++n) {
326 
327  // convolution results
328  double convolution_ = list_query_pixels[n].convolution(I, me);
329  const double likelihood = fabs(2 * convolution_);
330  if ((likelihood > max) && (likelihood > threshold)) {
331  max_convolution = convolution_;
332  max = likelihood;
333  max_rank = static_cast<int>(n);
334  }
335  }
336  }
337 
338  vpImagePoint ip;
339 
340  if (max_rank >= 0) {
341  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
342  ip.set_i(list_query_pixels[max_rank].m_i);
343  ip.set_j(list_query_pixels[max_rank].m_j);
345  }
346 
347  *this = list_query_pixels[max_rank]; // The vpMeSite2 is replaced by the
348  // vpMeSite2 of max likelihood
349  m_normGradient = vpMath::sqr(max_convolution);
350 
351  m_convlt = max_convolution;
352  }
353  else // none of the query sites is better than the threshold
354  {
355  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
356  ip.set_i(list_query_pixels[0].m_i);
357  ip.set_j(list_query_pixels[0].m_j);
359  }
360  m_normGradient = 0;
361  if (std::fabs(contrast) > std::numeric_limits<double>::epsilon()) {
362  m_state = CONTRAST; // contrast suppression
363  }
364  else {
365  m_state = THRESHOLD; // threshold suppression
366  }
367 
368  }
369  delete[] list_query_pixels;
370 }
371 
372 void vpMeSite::trackMultipleHypotheses(const vpImage<unsigned char> &I, const vpMe &me, const bool &test_contrast,
373 std::vector<vpMeSite> &outputHypotheses, const unsigned numCandidates)
374 {
375 
376  // range = +/- range of pixels within which the correspondent
377  // of the current pixel will be sought
378  unsigned int range = me.getRange();
379  const unsigned int numQueries = range * 2 + 1;
380 
381  if (numCandidates > numQueries) {
382  throw vpException(vpException::badValue, "Error in vpMeSite::track: the number of retained hypotheses cannot superior to the number of queried sites.");
383  }
384 
385  vpMeSite *list_query_pixels = getQueryList(I, static_cast<int>(range));
386 
387  // Insert into a map, where the key is the sorting criterion (negative likelihood or contrast diff)
388  // and the key is the ME site + its computed likelihood and contrast.
389  // After computation: iterating on the map is guaranteed to be done with the keys being sorted according to the criterion.
390  // Multimap allows to have multiple values (sites) with the same key (likelihood/contrast diff)
391  // Only the candidates that are above the threshold are kept
392  std::multimap<double, vpMeSiteHypothesis> candidates;
393 
394  const double contrast_max = 1 + me.getMu2();
395  const double contrast_min = 1 - me.getMu1();
396 
397  const double threshold = computeFinalThreshold(me);
398 
399  // First step: compute likelihoods and contrasts for all queries
400  if (test_contrast) {
401  for (unsigned int n = 0; n < numQueries; ++n) {
402  vpMeSite &query = list_query_pixels[n];
403  // convolution results
404  const double convolution_ = query.convolution(I, &me);
405  // luminance ratio of reference pixel to potential correspondent pixel
406  // the luminance must be similar, hence the ratio value should
407  // lay between, for instance, 0.5 and 1.5 (parameter tolerance)
408  const double likelihood = fabs(convolution_ + m_convlt);
409 
410  query.m_convlt = convolution_;
411  const double contrast = convolution_ / m_convlt;
412  candidates.insert(std::pair<double, vpMeSiteHypothesis>(fabs(1.0 - contrast), vpMeSiteHypothesis(&query, likelihood, contrast)));
413  }
414  }
415  else { // test on likelihood only
416  for (unsigned int n = 0; n < numQueries; ++n) {
417  // convolution results
418  vpMeSite &query = list_query_pixels[n];
419  const double convolution_ = query.convolution(I, &me);
420  const double likelihood = fabs(2 * convolution_);
421  query.m_convlt = convolution_;
422  candidates.insert(std::pair<double, vpMeSiteHypothesis>(-likelihood, vpMeSiteHypothesis(&query, likelihood, 0.0)));
423  }
424  }
425  // Take first numCandidates hypotheses: map is sorted according to the likelihood/contrast difference so we can just
426  // iterate from the start
427  outputHypotheses.resize(numCandidates);
428 
429  std::multimap<double, vpMeSiteHypothesis>::iterator it = candidates.begin();
430  if (test_contrast) {
431  for (unsigned int i = 0; i < numCandidates; ++i, ++it) {
432  outputHypotheses[i] = *(it->second.site);
433  outputHypotheses[i].m_normGradient = vpMath::sqr(outputHypotheses[i].m_convlt);
434  const double likelihood = it->second.likelihood;
435  const double contrast = it->second.contrast;
436 
437  if (likelihood > threshold) {
438  if (contrast <= contrast_min || contrast >= contrast_max) {
439  outputHypotheses[i].m_state = CONTRAST;
440  }
441  else {
442  outputHypotheses[i].m_state = NO_SUPPRESSION;
443  }
444  }
445  else {
446  outputHypotheses[i].m_state = THRESHOLD;
447  }
448  }
449  }
450  else {
451  for (unsigned int i = 0; i < numCandidates; ++i, ++it) {
452  outputHypotheses[i] = *(it->second.site);
453  const double likelihood = it->second.likelihood;
454  if (likelihood > threshold) {
455  outputHypotheses[i].m_state = NO_SUPPRESSION;
456  }
457  else {
458  outputHypotheses[i].m_state = THRESHOLD;
459  }
460  }
461  }
462 
463  const vpMeSite &bestMatch = outputHypotheses[0];
464 
465 
466  if (bestMatch.m_state != NO_SUPPRESSION) {
467  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
468 
469  vpDisplay::displayPoint(I, bestMatch.m_i, bestMatch.m_j, vpColor::red);
470  }
471  *this = outputHypotheses[0];
472  }
473  else {
474  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
475  vpDisplay::displayPoint(I, bestMatch.m_i, bestMatch.m_j, vpColor::green);
476  }
477  m_normGradient = 0;
478  }
479 
480  delete[] list_query_pixels;
481 }
482 
483 int vpMeSite::operator!=(const vpMeSite &m) { return ((m.m_i != m_i) || (m.m_j != m_j)); }
484 
485 
487 
488 void vpMeSite::display(const vpImage<vpRGBa> &I) const { vpMeSite::display(I, m_ifloat, m_jfloat, m_state); }
489 
490 // Static functions
491 
492 void vpMeSite::display(const vpImage<unsigned char> &I, const double &i, const double &j, const vpMeSiteState &state)
493 {
494  const unsigned int crossSize = 3;
495  switch (state) {
496  case NO_SUPPRESSION:
497  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::green, 1);
498  break;
499 
500  case CONTRAST:
501  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::blue, 1);
502  break;
503 
504  case THRESHOLD:
505  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::purple, 1);
506  break;
507 
508  case M_ESTIMATOR:
509  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::red, 1);
510  break;
511 
512  case OUTSIDE_ROI_MASK:
513  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::cyan, 1);
514  break;
515 
516  default:
517  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::yellow, 1);
518  }
519 }
520 
521 void vpMeSite::display(const vpImage<vpRGBa> &I, const double &i, const double &j, const vpMeSiteState &state)
522 {
523  const unsigned int cross_size = 3;
524  switch (state) {
525  case NO_SUPPRESSION:
526  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::green, 1);
527  break;
528 
529  case CONTRAST:
530  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::blue, 1);
531  break;
532 
533  case THRESHOLD:
534  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::purple, 1);
535  break;
536 
537  case M_ESTIMATOR:
538  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::red, 1);
539  break;
540 
541  case OUTSIDE_ROI_MASK:
542  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::cyan, 1);
543  break;
544 
545  default:
546  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::yellow, 1);
547  }
548 }
549 
550 VISP_EXPORT std::ostream &operator<<(std::ostream &os, vpMeSite &vpMeS)
551 {
552  return (os << "Alpha: " << vpMeS.m_alpha << " Convolution: " << vpMeS.m_convlt << " Weight: " << vpMeS.m_weight << " Threshold: " << vpMeS.m_contrastThreshold);
553 }
554 
555 END_VISP_NAMESPACE
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:614
static const vpColor red
Definition: vpColor.h:217
static const vpColor cyan
Definition: vpColor.h:226
static const vpColor blue
Definition: vpColor.h:223
static const vpColor purple
Definition: vpColor.h:228
static const vpColor yellow
Definition: vpColor.h:225
static const vpColor green
Definition: vpColor.h:220
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:309
void set_i(double ii)
Definition: vpImagePoint.h:298
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
static double sqr(double x)
Definition: vpMath.h:203
static int round(double x)
Definition: vpMath.h:410
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'....
Definition: vpMeSite.h:68
int m_mask_sign
Mask sign.
Definition: vpMeSite.h:107
vpMeSiteState
Definition: vpMeSite.h:85
@ OUTSIDE_ROI_MASK
Point is outside the region of interest mask, but retained in the ME list.
Definition: vpMeSite.h:95
@ THRESHOLD
Point not tracked due to the likelihood that is below the threshold, but retained in the ME list.
Definition: vpMeSite.h:91
@ CONTRAST
Point not tracked due to a contrast problem, but retained in the ME list.
Definition: vpMeSite.h:87
@ M_ESTIMATOR
Point detected as an outlier during virtual visual-servoing.
Definition: vpMeSite.h:92
@ NO_SUPPRESSION
Point successfully tracked.
Definition: vpMeSite.h:86
void setDisplay(vpMeSiteDisplayType select)
Definition: vpMeSite.h:264
int operator!=(const vpMeSite &m)
Definition: vpMeSite.cpp:483
double m_ifloat
Subpixel coordinates along i of a site.
Definition: vpMeSite.h:103
vpMeSite * getQueryList(const vpImage< unsigned char > &I, const int &range) const
Definition: vpMeSite.cpp:188
double m_normGradient
Convolution of Site in previous image.
Definition: vpMeSite.h:113
void display(const vpImage< unsigned char > &I) const
Definition: vpMeSite.cpp:486
double convolution(const vpImage< unsigned char > &ima, const vpMe *me)
Definition: vpMeSite.cpp:227
void init()
Definition: vpMeSite.cpp:70
double m_convlt
Convolution of Site in previous image.
Definition: vpMeSite.h:111
double m_alpha
Angle of tangent at site.
Definition: vpMeSite.h:109
@ NONE
Not displayed.
Definition: vpMeSite.h:75
@ RANGE_RESULT
Definition: vpMeSite.h:78
@ RESULT
Definition: vpMeSite.h:77
@ RANGE
Definition: vpMeSite.h:76
vpMeSite & operator=(const vpMeSite &m)
Definition: vpMeSite.cpp:170
void trackMultipleHypotheses(const vpImage< unsigned char > &I, const vpMe &me, const bool &test_contrast, std::vector< vpMeSite > &outputHypotheses, const unsigned numCandidates)
Definition: vpMeSite.cpp:372
double computeFinalThreshold(const vpMe &me) const
Definition: vpMeSite.h:329
double m_contrastThreshold
Old likelihood ratio threshold (to be avoided) or easy-to-use normalized threshold: minimal contrast.
Definition: vpMeSite.h:117
int m_j
Integer coordinates along j of a site.
Definition: vpMeSite.h:101
int m_i
Integer coordinate along i of a site.
Definition: vpMeSite.h:99
double m_jfloat
Subpixel coordinates along j of a site.
Definition: vpMeSite.h:105
vpMeSite()
Definition: vpMeSite.cpp:93
double m_weight
Uncertainty of point given as a probability between 0 and 1.
Definition: vpMeSite.h:115
void track(const vpImage< unsigned char > &I, const vpMe *me, const bool &test_contrast=true)
Definition: vpMeSite.cpp:282
Definition: vpMe.h:134
unsigned int getAngleStep() const
Definition: vpMe.h:193
double getMu1() const
Definition: vpMe.h:240
int getStrip() const
Definition: vpMe.h:282
double getMu2() const
Definition: vpMe.h:247
unsigned int getMaskSize() const
Definition: vpMe.h:225
vpMatrix * getMask() const
Definition: vpMe.h:200
unsigned int getRange() const
Definition: vpMe.h:268