44 #include <visp3/core/vpTrackingException.h>
45 #include <visp3/me/vpMe.h>
46 #include <visp3/me/vpMeSite.h>
50 #ifndef DOXYGEN_SHOULD_SKIP_THIS
52 struct vpMeSiteHypothesis
54 vpMeSiteHypothesis(
vpMeSite *site,
double l,
double c) : site(site), likelihood(l), contrast(c)
62 static 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;
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)
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)
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)
122 m_selectDisplay =
NONE;
134 void 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);
148 void 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);
162 void 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((
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((
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;
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
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 ...
unsigned int getWidth() const
unsigned int getHeight() const
static double sqr(double x)
static Type abs(const Type &x)
static int round(double x)
static double deg(double rad)
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'....
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)
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
unsigned int getMaskSize() const
vpMatrix * getMask() const
unsigned int getRange() const