Visual Servoing Platform  version 3.6.1 under development (2025-03-17)
vpMeSite.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2025 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 outsideImage(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  m_index_prev = 90; // Middle index to have no effect on first image
93 }
94 
96  : 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),
97  m_weight(1), m_contrastThreshold(10000.0), m_selectDisplay(NONE), m_state(NO_SUPPRESSION), m_index_prev(90)
98 { }
99 
100 vpMeSite::vpMeSite(const double &ip, const double &jp)
101  : 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),
102  m_weight(1), m_contrastThreshold(10000.0), m_selectDisplay(NONE), m_state(NO_SUPPRESSION), m_index_prev(90)
103 {
104  m_i = vpMath::round(ip);
105  m_j = vpMath::round(jp);
106  m_ifloat = ip;
107  m_jfloat = jp;
108 }
109 
111  : 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),
112  m_weight(1), m_contrastThreshold(10000.0), m_selectDisplay(NONE), m_state(NO_SUPPRESSION), m_index_prev(90)
113 {
114  *this = mesite;
115 }
116 
117 // More an Update than init
118 // For points in meter form (to avoid approximations)
119 void vpMeSite::init(const double &ip, const double &jp, const double &alphap)
120 {
121  // Note: keep old value of m_convlt, contrast and threshold
122  m_selectDisplay = NONE;
123 
124  m_ifloat = ip;
125  m_i = vpMath::round(ip);
126  m_jfloat = jp;
127  m_j = vpMath::round(jp);
128  m_alpha = alphap;
129  m_mask_sign = 1;
130  m_index_prev = 90;
131 }
132 
133 // initialise with convolution()
134 void vpMeSite::init(const double &ip, const double &jp, const double &alphap, const double &convltp)
135 {
136  m_selectDisplay = NONE;
137  m_ifloat = ip;
138  m_i = static_cast<int>(ip);
139  m_jfloat = jp;
140  m_j = static_cast<int>(jp);
141  m_alpha = alphap;
142  m_convlt = convltp;
143  m_mask_sign = 1;
144  m_index_prev = 90;
145 }
146 
147 // initialise with convolution and sign
148 void vpMeSite::init(const double &ip, const double &jp, const double &alphap, const double &convltp, const int &sign)
149 {
150  m_selectDisplay = NONE;
151  m_ifloat = ip;
152  m_i = static_cast<int>(ip);
153  m_jfloat = jp;
154  m_j = static_cast<int>(jp);
155  m_alpha = alphap;
156  m_convlt = convltp;
157  m_mask_sign = sign;
158  m_index_prev = 90;
159 }
160 
161 // Initialise with convolution and sign.
162 void vpMeSite::init(const double &ip, const double &jp, const double &alphap, const double &convltp, const int &sign, const double &contrastThreshold)
163 {
164  m_selectDisplay = NONE;
165  m_ifloat = ip;
166  m_i = static_cast<int>(ip);
167  m_jfloat = jp;
168  m_j = static_cast<int>(jp);
169  m_alpha = alphap;
170  m_convlt = convltp;
171  m_mask_sign = sign;
172  m_contrastThreshold = contrastThreshold;
173  m_index_prev = 90;
174 }
175 
177 {
178  m_i = m.m_i;
179  m_j = m.m_j;
180  m_ifloat = m.m_ifloat;
181  m_jfloat = m.m_jfloat;
183  m_alpha = m.m_alpha;
184  m_convlt = m.m_convlt;
186  m_weight = m.m_weight;
188  m_selectDisplay = m.m_selectDisplay;
189  m_state = m.m_state;
190  m_index_prev = m.m_index_prev;
191  return *this;
192 }
193 
194 vpMeSite *vpMeSite::getQueryList(const vpImage<unsigned char> &I, const int &range) const
195 {
196  unsigned int range_ = static_cast<unsigned int>(range);
197  // Size of query list includes the point on the line
198  vpMeSite *list_query_pixels = new vpMeSite[(2 * range_) + 1];
199 
200  // range : +/- the range within which the pixel's
201  // correspondent will be sought
202 
203  double salpha = sin(m_alpha);
204  double calpha = cos(m_alpha);
205  int n = 0;
206  vpImagePoint ip;
207 
208  for (int k = -range; k <= range; ++k) {
209  double ii = m_ifloat + (k * salpha);
210  double jj = m_jfloat + (k * calpha);
211 
212  // Display
213  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RANGE)) {
214  ip.set_i(ii);
215  ip.set_j(jj);
217  }
218 
219  // Copy parent's convolution
220  vpMeSite pel;
222  pel.setDisplay(m_selectDisplay); // Display
223 
224  // Add site to the query list
225  list_query_pixels[n] = pel;
226  ++n;
227  }
228 
229  return list_query_pixels;
230 }
231 
236 unsigned int vpMeSite::computeMaskIndex(const double alpha, const vpMe &me)
237 {
238  // Calculate tangent angle from normal
239  double theta = alpha + (M_PI / 2);
240  // Move tangent angle to within 0->M_PI for a positive
241  // mask index
242  while (theta < 0) {
243  theta += M_PI;
244  }
245  while (theta > M_PI) {
246  theta -= M_PI;
247  }
248  // Convert radians to degrees
249  int theta_deg = vpMath::round(vpMath::deg(theta));
250 
251  const int flatAngle = 180;
252  if (abs(theta_deg) == flatAngle) {
253  theta_deg = 0;
254  }
255  unsigned int mask_index = static_cast<unsigned int>(theta_deg / static_cast<double>(me.getAngleStep()));
256  return(mask_index);
257 }
258 
260 {
261  int half;
262  int height_ = static_cast<int>(I.getHeight());
263  int width_ = static_cast<int>(I.getWidth());
264 
265  double conv = 0.0;
266  unsigned int msize = me->getMaskSize();
267  half = static_cast<int>((msize - 1) >> 1);
268 
269  if (outsideImage(m_i, m_j, half + me->getStrip(), height_, width_)) {
270  conv = 0.0;
271  m_i = 0;
272  m_j = 0;
273  }
274  else {
275  unsigned int mask_index = computeMaskIndex(m_alpha, *me);
276 
277  unsigned int i_ = static_cast<unsigned int>(m_i);
278  unsigned int j_ = static_cast<unsigned int>(m_j);
279  unsigned int half_ = static_cast<unsigned int>(half);
280 
281  unsigned int ihalf = i_ - half_;
282  unsigned int jhalf = j_ - half_;
283 
284  for (unsigned int a = 0; a < msize; ++a) {
285  unsigned int ihalfa = ihalf + a;
286  for (unsigned int b = 0; b < msize; ++b) {
287  conv += m_mask_sign * me->getMask()[mask_index][a][b] * I(ihalfa, jhalf + b);
288  }
289  }
290  }
291  return conv;
292 }
293 
297 double vpMeSite::convolution(const vpImage<unsigned char> &I, const vpMe &me, const unsigned int mask_index)
298 {
299  int half;
300  int height = static_cast<int>(I.getHeight());
301  int width = static_cast<int>(I.getWidth());
302 
303  double conv = 0.0;
304  unsigned int msize = me.getMaskSize();
305  half = static_cast<int>((msize - 1) >> 1);
306 
307  if (outsideImage(m_i, m_j, half + me.getStrip(), height, width)) {
308  conv = 0.0;
309  m_i = 0;
310  m_j = 0;
311  }
312  else {
313  unsigned int i_ = static_cast<unsigned int>(m_i);
314  unsigned int j_ = static_cast<unsigned int>(m_j);
315  unsigned int half_ = static_cast<unsigned int>(half);
316 
317  unsigned int ihalf = i_ - half_;
318  unsigned int jhalf = j_ - half_;
319 
320  for (unsigned int a = 0; a < msize; ++a) {
321  unsigned int ihalfa = ihalf + a;
322  for (unsigned int b = 0; b < msize; ++b) {
323  conv += m_mask_sign * me.getMask()[mask_index][a][b] * I(ihalfa, jhalf + b);
324  }
325  }
326  }
327  return conv;
328 }
329 
330 void vpMeSite::track(const vpImage<unsigned char> &I, const vpMe *me, const bool &test_contrast)
331 {
332  int max_rank = -1;
333  double max_convolution = 0;
334  double max = 0;
335  double contrast = 0;
336 
337  // range = +/- range of pixels within which the correspondent
338  // of the current pixel will be sought
339  unsigned int range = me->getRange();
340  const unsigned int normalSides = 2;
341  const unsigned int numQueries = range * normalSides + 1;
342  unsigned int mask_index = computeMaskIndex(m_alpha, *me);
343  vpMeSite *list_query_pixels = getQueryList(I, static_cast<int>(range));
344 
345  double contrast_max = 1 + me->getMu2();
346  double contrast_min = 1 - me->getMu1();
347 
348  double threshold = computeFinalThreshold(*me);
349 
350  if (test_contrast) { // likelihood test
351  double diff = 1e6;
352  // Change of mask sign to have a continuity at 0 and 180.
353  // Threshold at 120 to be more than the 90 initial value
354  if (vpMath::abs((int)(mask_index - m_index_prev)) > 120) {
356  }
357  for (unsigned int n = 0; n < numQueries; ++n) {
358  // Convolution results
359  list_query_pixels[n].m_mask_sign = m_mask_sign;
360  double convolution_ = list_query_pixels[n].convolution(I, *me, mask_index);
361  // no fabs since m_convlt > 0 and we look for a similar one
362  const double likelihood = convolution_ + m_convlt;
363 
364  if (likelihood > threshold) {
365  contrast = convolution_ / m_convlt;
366  if ((contrast > contrast_min) && (contrast < contrast_max) && (fabs(1 - contrast) < diff)) {
367  diff = fabs(1 - contrast);
368  max_convolution = convolution_;
369  max = likelihood;
370  max_rank = static_cast<int>(n);
371  }
372  }
373  }
374  }
375  else { // test on contrast only
376  for (unsigned int n = 0; n < numQueries; ++n) {
377  // Convolution results
378  double convolution_ = list_query_pixels[n].convolution(I, me);
379  const double likelihood = fabs(2 * convolution_);
380  if ((likelihood > max) && (likelihood > threshold)) {
381  max_convolution = convolution_;
382  max = likelihood;
383  max_rank = static_cast<int>(n);
384  }
385  }
386  // in case max_convolution < 0, change of mask sign so that m_convlt > 0
387  // for the future likelihood tests
388  if (max_convolution < 0) {
389  max_convolution = -max_convolution;
391  }
392  }
393 
394  vpImagePoint ip;
395 
396  if (max_rank >= 0) {
397  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
398  ip.set_i(list_query_pixels[max_rank].m_i);
399  ip.set_j(list_query_pixels[max_rank].m_j);
401  }
402 
403  list_query_pixels[max_rank].m_mask_sign = m_mask_sign;
404  list_query_pixels[max_rank].m_index_prev = mask_index;
405  list_query_pixels[max_rank].m_convlt = max_convolution;
406  list_query_pixels[max_rank].m_normGradient = vpMath::sqr(max_convolution);
407 
408  *this = list_query_pixels[max_rank]; // The vpMeSite2 is replaced by the vpMeSite2 of max likelihood
409  }
410  else // none of the query sites is better than the threshold
411  {
412  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
413  ip.set_i(list_query_pixels[0].m_i);
414  ip.set_j(list_query_pixels[0].m_j);
416  }
417  m_normGradient = 0;
418  if (std::fabs(contrast) > std::numeric_limits<double>::epsilon()) {
419  m_state = CONTRAST; // contrast suppression
420  }
421  else {
422  m_state = THRESHOLD; // threshold suppression
423  }
424 
425  }
426  delete[] list_query_pixels;
427 }
428 
429 void vpMeSite::trackMultipleHypotheses(const vpImage<unsigned char> &I, const vpMe &me, const bool &test_contrast,
430  std::vector<vpMeSite> &outputHypotheses, const unsigned numCandidates)
431 {
432  // range = +/- range of pixels within which the correspondent
433  // of the current pixel will be sought
434  unsigned int range = me.getRange();
435  const unsigned int normalSides = 2;
436  const unsigned int numQueries = range * normalSides + 1;
437  unsigned int mask_index = computeMaskIndex(m_alpha, me);
438 
439  if (numCandidates > numQueries) {
440  throw vpException(vpException::badValue, "Error in vpMeSite::track(): the number of retained hypotheses cannot be greater to the number of queried sites.");
441  }
442 
443  vpMeSite *list_query_pixels = getQueryList(I, static_cast<int>(range));
444 
445  // Insert into a map, where the key is the sorting criterion (negative likelihood or contrast diff)
446  // and the key is the ME site + its computed likelihood and contrast.
447  // After computation: iterating on the map is guaranteed to be done with the keys being sorted according to the criterion.
448  // Multimap allows to have multiple values (sites) with the same key (likelihood/contrast diff)
449  // Only the candidates that are above the threshold are kept
450  std::multimap<double, vpMeSiteHypothesis> candidates;
451 
452  const double contrast_max = 1 + me.getMu2();
453  const double contrast_min = 1 - me.getMu1();
454 
455  const double threshold = computeFinalThreshold(me);
456 
457  // First step: compute likelihoods and contrasts for all queries
458  if (test_contrast) {
459  // Change of mask sign to have a continuity at 0 and 180.
460  // Threshold at 120 to be more than the 90 initial value
461  if (vpMath::abs((int)(mask_index - m_index_prev)) > 120) {
463  }
464  for (unsigned int n = 0; n < numQueries; ++n) {
465  // Convolution results
466  list_query_pixels[n].m_mask_sign = m_mask_sign;
467  vpMeSite &query = list_query_pixels[n];
468  // Convolution results
469  const double convolution_ = query.convolution(I, me, mask_index);
470  // no fabs since m_convlt > 0 and we look for a similar one
471  const double likelihood = convolution_ + m_convlt;
472 
473  query.m_convlt = convolution_;
474  const double contrast = convolution_ / m_convlt;
475  candidates.insert(std::pair<double, vpMeSiteHypothesis>(fabs(1.0 - contrast), vpMeSiteHypothesis(&query, likelihood, contrast)));
476  }
477  }
478  else { // test on likelihood only
479  for (unsigned int n = 0; n < numQueries; ++n) {
480  // convolution results
481  vpMeSite &query = list_query_pixels[n];
482  const double convolution_ = query.convolution(I, &me);
483  const double likelihood = fabs(2 * convolution_);
484  query.m_convlt = convolution_;
485  candidates.insert(std::pair<double, vpMeSiteHypothesis>(-likelihood, vpMeSiteHypothesis(&query, likelihood, 0.0)));
486  }
487  }
488  // Take first numCandidates hypotheses: map is sorted according to the likelihood/contrast difference so we can just
489  // iterate from the start
490  outputHypotheses.resize(numCandidates);
491 
492  std::multimap<double, vpMeSiteHypothesis>::iterator it = candidates.begin();
493  if (test_contrast) {
494  for (unsigned int i = 0; i < numCandidates; ++i, ++it) {
495  outputHypotheses[i] = *(it->second.site);
496  outputHypotheses[i].m_normGradient = vpMath::sqr(outputHypotheses[i].m_convlt);
497  const double likelihood = it->second.likelihood;
498  const double contrast = it->second.contrast;
499 
500  if (likelihood > threshold) {
501  if (contrast <= contrast_min || contrast >= contrast_max) {
502  outputHypotheses[i].m_state = CONTRAST;
503  }
504  else {
505  outputHypotheses[i].m_state = NO_SUPPRESSION;
506  }
507  }
508  else {
509  outputHypotheses[i].m_state = THRESHOLD;
510  }
511  }
512  }
513  else {
514  for (unsigned int i = 0; i < numCandidates; ++i, ++it) {
515  outputHypotheses[i] = *(it->second.site);
516  const double likelihood = it->second.likelihood;
517  if (likelihood > threshold) {
518  outputHypotheses[i].m_state = NO_SUPPRESSION;
519  }
520  else {
521  outputHypotheses[i].m_state = THRESHOLD;
522  }
523  }
524  }
525 
526  const vpMeSite &bestMatch = outputHypotheses[0];
527 
528  if (bestMatch.m_state != NO_SUPPRESSION) {
529  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
530 
531  vpDisplay::displayPoint(I, bestMatch.m_i, bestMatch.m_j, vpColor::red);
532  }
533  *this = outputHypotheses[0];
534  }
535  else {
536  if ((m_selectDisplay == RANGE_RESULT) || (m_selectDisplay == RESULT)) {
537  vpDisplay::displayPoint(I, bestMatch.m_i, bestMatch.m_j, vpColor::green);
538  }
539  m_normGradient = 0;
540  }
541 
542  delete[] list_query_pixels;
543 }
544 
545 int vpMeSite::operator!=(const vpMeSite &m) { return ((m.m_i != m_i) || (m.m_j != m_j)); }
546 
548 
549 void vpMeSite::display(const vpImage<vpRGBa> &I) const { vpMeSite::display(I, m_ifloat, m_jfloat, m_state); }
550 
551 // Static functions
552 
553 void vpMeSite::display(const vpImage<unsigned char> &I, const double &i, const double &j, const vpMeSiteState &state)
554 {
555  const unsigned int crossSize = 3;
556  switch (state) {
557  case NO_SUPPRESSION:
558  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::green, 1);
559  break;
560 
561  case CONTRAST:
562  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::blue, 1);
563  break;
564 
565  case THRESHOLD:
566  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::purple, 1);
567  break;
568 
569  case M_ESTIMATOR:
570  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::red, 1);
571  break;
572 
573  case OUTSIDE_ROI_MASK:
574  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::cyan, 1);
575  break;
576 
577  default:
578  vpDisplay::displayCross(I, vpImagePoint(i, j), crossSize, vpColor::yellow, 1);
579  }
580 }
581 
582 void vpMeSite::display(const vpImage<vpRGBa> &I, const double &i, const double &j, const vpMeSiteState &state)
583 {
584  const unsigned int cross_size = 3;
585  switch (state) {
586  case NO_SUPPRESSION:
587  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::green, 1);
588  break;
589 
590  case CONTRAST:
591  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::blue, 1);
592  break;
593 
594  case THRESHOLD:
595  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::purple, 1);
596  break;
597 
598  case M_ESTIMATOR:
599  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::red, 1);
600  break;
601 
602  case OUTSIDE_ROI_MASK:
603  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::cyan, 1);
604  break;
605 
606  default:
607  vpDisplay::displayCross(I, vpImagePoint(i, j), cross_size, vpColor::yellow, 1);
608  }
609 }
610 
611 VISP_EXPORT std::ostream &operator<<(std::ostream &os, vpMeSite &me_site)
612 {
613  return (os << "Alpha: " << me_site.m_alpha << " Convolution: " << me_site.m_convlt << " Weight: " << me_site.m_weight << " Threshold: " << me_site.m_contrastThreshold);
614 }
615 
616 END_VISP_NAMESPACE
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:699
static const vpColor red
Definition: vpColor.h:198
static const vpColor cyan
Definition: vpColor.h:207
static const vpColor blue
Definition: vpColor.h:204
static const vpColor purple
Definition: vpColor.h:209
static const vpColor yellow
Definition: vpColor.h:206
static const vpColor green
Definition: vpColor.h:201
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 Type abs(const Type &x)
Definition: vpMath.h:269
static int round(double x)
Definition: vpMath.h:410
static double deg(double rad)
Definition: vpMath.h:119
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:280
int operator!=(const vpMeSite &m)
Definition: vpMeSite.cpp:545
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:194
double m_normGradient
Convolution of Site in previous image.
Definition: vpMeSite.h:113
unsigned int computeMaskIndex(const double alpha, const vpMe &me)
Definition: vpMeSite.cpp:236
void display(const vpImage< unsigned char > &I) const
Definition: vpMeSite.cpp:547
double convolution(const vpImage< unsigned char > &ima, const vpMe *me)
Definition: vpMeSite.cpp:259
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:176
void trackMultipleHypotheses(const vpImage< unsigned char > &I, const vpMe &me, const bool &test_contrast, std::vector< vpMeSite > &outputHypotheses, const unsigned numCandidates)
Definition: vpMeSite.cpp:429
double computeFinalThreshold(const vpMe &me) const
Definition: vpMeSite.h:345
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:95
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:330
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