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 horsImage(
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;
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)
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)
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)
120 m_selectDisplay =
NONE;
131 void vpMeSite::init(
const double &ip,
const double &jp,
const double &alphap,
const double &convltp)
133 m_selectDisplay =
NONE;
135 m_i =
static_cast<int>(ip);
137 m_j =
static_cast<int>(jp);
144 void vpMeSite::init(
const double &ip,
const double &jp,
const double &alphap,
const double &convltp,
const int &sign)
146 m_selectDisplay =
NONE;
148 m_i =
static_cast<int>(ip);
150 m_j =
static_cast<int>(jp);
157 void vpMeSite::init(
const double &ip,
const double &jp,
const double &alphap,
const double &convltp,
const int &sign,
const double &contrastThreshold)
159 m_selectDisplay =
NONE;
161 m_i =
static_cast<int>(ip);
163 m_j =
static_cast<int>(jp);
182 m_selectDisplay = m.m_selectDisplay;
190 unsigned int range_ =
static_cast<unsigned int>(range);
202 for (
int k = -range; k <= range; ++k) {
203 double ii =
m_ifloat + (k * salpha);
204 double jj =
m_jfloat + (k * calpha);
219 list_query_pixels[n] = pel;
223 return list_query_pixels;
230 int height_ =
static_cast<int>(I.
getHeight());
231 int width_ =
static_cast<int>(I.
getWidth());
235 half =
static_cast<int>((msize - 1) >> 1);
237 if (horsImage(
m_i,
m_j, half + me->
getStrip(), height_, width_)) {
244 double theta =
m_alpha + (M_PI / 2);
250 while (theta > M_PI) {
257 const int flatAngle = 180;
258 if (abs(thetadeg) == flatAngle) {
262 unsigned int index_mask =
static_cast<unsigned int>(thetadeg /
static_cast<double>(me->
getAngleStep()));
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);
268 unsigned int ihalf = i_ - half_;
269 unsigned int jhalf = j_ - half_;
271 for (
unsigned int a = 0; a < msize; ++a) {
272 unsigned int ihalfa = ihalf + a;
273 for (
unsigned int b = 0; b < msize; ++b) {
285 double max_convolution = 0;
291 unsigned int range = me->
getRange();
292 const unsigned int normalSides = 2;
293 const unsigned int numQueries = range * normalSides + 1;
297 double contrast_max = 1 + me->
getMu2();
298 double contrast_min = 1 - me->
getMu1();
304 for (
unsigned int n = 0; n < numQueries; ++n) {
307 double convolution_ = list_query_pixels[n].
convolution(I, me);
311 const double likelihood = fabs(convolution_ +
m_convlt);
313 if (likelihood > threshold) {
315 if ((contrast > contrast_min) && (contrast < contrast_max) && (fabs(1 - contrast) < diff)) {
316 diff = fabs(1 - contrast);
317 max_convolution = convolution_;
319 max_rank =
static_cast<int>(n);
325 for (
unsigned int n = 0; n < numQueries; ++n) {
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_;
333 max_rank =
static_cast<int>(n);
342 ip.
set_i(list_query_pixels[max_rank].
m_i);
343 ip.
set_j(list_query_pixels[max_rank].
m_j);
347 *
this = list_query_pixels[max_rank];
361 if (std::fabs(contrast) > std::numeric_limits<double>::epsilon()) {
369 delete[] list_query_pixels;
373 std::vector<vpMeSite> &outputHypotheses,
const unsigned numCandidates)
379 const unsigned int numQueries = range * 2 + 1;
381 if (numCandidates > numQueries) {
392 std::multimap<double, vpMeSiteHypothesis> candidates;
394 const double contrast_max = 1 + me.
getMu2();
395 const double contrast_min = 1 - me.
getMu1();
401 for (
unsigned int n = 0; n < numQueries; ++n) {
402 vpMeSite &query = list_query_pixels[n];
404 const double convolution_ = query.
convolution(I, &me);
408 const double likelihood = fabs(convolution_ +
m_convlt);
411 const double contrast = convolution_ /
m_convlt;
412 candidates.insert(std::pair<double, vpMeSiteHypothesis>(fabs(1.0 - contrast), vpMeSiteHypothesis(&query, likelihood, contrast)));
416 for (
unsigned int n = 0; n < numQueries; ++n) {
418 vpMeSite &query = list_query_pixels[n];
419 const double convolution_ = query.
convolution(I, &me);
420 const double likelihood = fabs(2 * convolution_);
422 candidates.insert(std::pair<double, vpMeSiteHypothesis>(-likelihood, vpMeSiteHypothesis(&query, likelihood, 0.0)));
427 outputHypotheses.resize(numCandidates);
429 std::multimap<double, vpMeSiteHypothesis>::iterator it = candidates.begin();
431 for (
unsigned int i = 0; i < numCandidates; ++i, ++it) {
432 outputHypotheses[i] = *(it->second.site);
434 const double likelihood = it->second.likelihood;
435 const double contrast = it->second.contrast;
437 if (likelihood > threshold) {
438 if (contrast <= contrast_min || contrast >= contrast_max) {
439 outputHypotheses[i].m_state =
CONTRAST;
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) {
463 const vpMeSite &bestMatch = outputHypotheses[0];
471 *
this = outputHypotheses[0];
480 delete[] list_query_pixels;
494 const unsigned int crossSize = 3;
523 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 int round(double x)
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.
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