44#include <visp3/core/vpTrackingException.h>
45#include <visp3/me/vpMe.h>
46#include <visp3/me/vpMeSite.h>
50#ifndef DOXYGEN_SHOULD_SKIP_THIS
52struct vpMeSiteHypothesis
54 vpMeSiteHypothesis(vpMeSite *site,
double l,
double c) : site(site), likelihood(l), contrast(c)
62static bool outsideImage(
int i,
int j,
int half,
int rows,
int cols)
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));
78 m_selectDisplay =
NONE;
122 m_selectDisplay =
NONE;
134void vpMeSite::init(
const double &ip,
const double &jp,
const double &alphap,
const double &convltp)
136 m_selectDisplay =
NONE;
138 m_i =
static_cast<int>(ip);
140 m_j =
static_cast<int>(jp);
148void vpMeSite::init(
const double &ip,
const double &jp,
const double &alphap,
const double &convltp,
const int &sign)
150 m_selectDisplay =
NONE;
152 m_i =
static_cast<int>(ip);
154 m_j =
static_cast<int>(jp);
162void vpMeSite::init(
const double &ip,
const double &jp,
const double &alphap,
const double &convltp,
const int &sign,
const double &contrastThreshold)
164 m_selectDisplay =
NONE;
166 m_i =
static_cast<int>(ip);
168 m_j =
static_cast<int>(jp);
188 m_selectDisplay = m.m_selectDisplay;
190 m_index_prev = m.m_index_prev;
196 unsigned int range_ =
static_cast<unsigned int>(range);
208 for (
int k = -range; k <= range; ++k) {
209 double ii =
m_ifloat + (k * salpha);
210 double jj =
m_jfloat + (k * calpha);
225 list_query_pixels[n] = pel;
229 return list_query_pixels;
239 double theta = alpha + (M_PI / 2);
245 while (theta > M_PI) {
251 const int flatAngle = 180;
252 if (abs(theta_deg) == flatAngle) {
255 unsigned int mask_index =
static_cast<unsigned int>(theta_deg /
static_cast<double>(me.
getAngleStep()));
262 int height_ =
static_cast<int>(I.getHeight());
263 int width_ =
static_cast<int>(I.getWidth());
267 half =
static_cast<int>((msize - 1) >> 1);
269 if (outsideImage(
m_i,
m_j, half + me->
getStrip(), height_, width_)) {
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);
281 unsigned int ihalf = i_ - half_;
282 unsigned int jhalf = j_ - half_;
284 for (
unsigned int a = 0; a < msize; ++a) {
285 unsigned int ihalfa = ihalf + a;
286 for (
unsigned int b = 0; b < msize; ++b) {
300 int height =
static_cast<int>(I.getHeight());
301 int width =
static_cast<int>(I.getWidth());
305 half =
static_cast<int>((msize - 1) >> 1);
307 if (outsideImage(
m_i,
m_j, half + me.
getStrip(), height, width)) {
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);
317 unsigned int ihalf = i_ - half_;
318 unsigned int jhalf = j_ - half_;
320 for (
unsigned int a = 0; a < msize; ++a) {
321 unsigned int ihalfa = ihalf + a;
322 for (
unsigned int b = 0; b < msize; ++b) {
333 double max_convolution = 0;
339 unsigned int range = me->
getRange();
340 const unsigned int normalSides = 2;
341 const unsigned int numQueries = range * normalSides + 1;
345 double contrast_max = 1 + me->
getMu2();
346 double contrast_min = 1 - me->
getMu1();
354 if (
vpMath::abs(
static_cast<int>(mask_index - m_index_prev)) > 120) {
357 for (
unsigned int n = 0; n < numQueries; ++n) {
360 double convolution_ = list_query_pixels[n].
convolution(I, *me, mask_index);
362 const double likelihood = convolution_ +
m_convlt;
364 if (likelihood > threshold) {
366 if ((contrast > contrast_min) && (contrast < contrast_max) && (fabs(1 - contrast) < diff)) {
367 diff = fabs(1 - contrast);
368 max_convolution = convolution_;
370 max_rank =
static_cast<int>(n);
376 for (
unsigned int n = 0; n < numQueries; ++n) {
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_;
383 max_rank =
static_cast<int>(n);
388 if (max_convolution < 0) {
389 max_convolution = -max_convolution;
398 ip.
set_i(list_query_pixels[max_rank].
m_i);
399 ip.
set_j(list_query_pixels[max_rank].
m_j);
404 list_query_pixels[max_rank].m_index_prev = mask_index;
405 list_query_pixels[max_rank].
m_convlt = max_convolution;
408 *
this = list_query_pixels[max_rank];
418 if (std::fabs(contrast) > std::numeric_limits<double>::epsilon()) {
426 delete[] list_query_pixels;
430 std::vector<vpMeSite> &outputHypotheses,
const unsigned numCandidates)
435 const unsigned int normalSides = 2;
436 const unsigned int numQueries = range * normalSides + 1;
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.");
450 std::multimap<double, vpMeSiteHypothesis> candidates;
452 const double contrast_max = 1 + me.
getMu2();
453 const double contrast_min = 1 - me.
getMu1();
461 if (
vpMath::abs(
static_cast<int>(mask_index - m_index_prev)) > 120) {
464 for (
unsigned int n = 0; n < numQueries; ++n) {
467 vpMeSite &query = list_query_pixels[n];
469 const double convolution_ = query.
convolution(I, me, mask_index);
471 const double likelihood = convolution_ +
m_convlt;
474 const double contrast = convolution_ /
m_convlt;
475 candidates.insert(std::pair<double, vpMeSiteHypothesis>(fabs(1.0 - contrast), vpMeSiteHypothesis(&query, likelihood, contrast)));
479 for (
unsigned int n = 0; n < numQueries; ++n) {
481 vpMeSite &query = list_query_pixels[n];
482 const double convolution_ = query.
convolution(I, &me);
483 const double likelihood = fabs(2 * convolution_);
485 candidates.insert(std::pair<double, vpMeSiteHypothesis>(-likelihood, vpMeSiteHypothesis(&query, likelihood, 0.0)));
490 outputHypotheses.resize(numCandidates);
492 std::multimap<double, vpMeSiteHypothesis>::iterator it = candidates.begin();
494 for (
unsigned int i = 0; i < numCandidates; ++i, ++it) {
495 outputHypotheses[i] = *(it->second.site);
497 const double likelihood = it->second.likelihood;
498 const double contrast = it->second.contrast;
500 if (likelihood > threshold) {
501 if (contrast <= contrast_min || contrast >= contrast_max) {
502 outputHypotheses[i].m_state =
CONTRAST;
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) {
526 const vpMeSite &bestMatch = outputHypotheses[0];
533 *
this = outputHypotheses[0];
542 delete[] list_query_pixels;
555 const unsigned int crossSize = 3;
584 const unsigned int cross_size = 3;
static const vpColor cyan
static const vpColor blue
static const vpColor purple
static const vpColor yellow
static const vpColor green
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.
@ badValue
Used to indicate that a value is not in the allowed range.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
static double sqr(double x)
static Type abs(const Type &x)
static int round(double x)
static double deg(double rad)
int m_mask_sign
Mask sign.
@ OUTSIDE_ROI_MASK
Point is outside the region of interest mask, but retained in the ME list.
@ THRESHOLD
Point not tracked due to the likelihood that is below the threshold, but retained in the ME list.
@ CONTRAST
Point not tracked due to a contrast problem, but retained in the ME list.
@ M_ESTIMATOR
Point detected as an outlier during virtual visual-servoing.
@ NO_SUPPRESSION
Point successfully tracked.
void setDisplay(vpMeSiteDisplayType select)
int operator!=(const vpMeSite &m)
friend VISP_EXPORT std::ostream & operator<<(std::ostream &os, vpMeSite &vpMeS)
double m_ifloat
Subpixel coordinates along i of a site.
vpMeSite * getQueryList(const vpImage< unsigned char > &I, const int &range) const
double m_normGradient
Convolution of Site in previous image.
unsigned int computeMaskIndex(const double alpha, const vpMe &me)
void display(const vpImage< unsigned char > &I) const
double convolution(const vpImage< unsigned char > &ima, const vpMe *me)
double m_convlt
Convolution of Site in previous image.
double m_alpha
Angle of tangent at site.
vpMeSite & operator=(const vpMeSite &m)
void trackMultipleHypotheses(const vpImage< unsigned char > &I, const vpMe &me, const bool &test_contrast, std::vector< vpMeSite > &outputHypotheses, const unsigned numCandidates)
double computeFinalThreshold(const vpMe &me) const
double m_contrastThreshold
Old likelihood ratio threshold (to be avoided) or easy-to-use normalized threshold: minimal contrast.
int m_j
Integer coordinates along j of a site.
int m_i
Integer coordinate along i of a site.
double m_jfloat
Subpixel coordinates along j of a site.
double m_weight
Uncertainty of point given as a probability between 0 and 1.
void track(const vpImage< unsigned char > &I, const vpMe *me, const bool &test_contrast=true)
unsigned int getAngleStep() const
vpMatrix * getMask() const
unsigned int getMaskSize() const
unsigned int getRange() const