34#include <visp3/core/vpConfig.h>
35#ifndef DOXYGEN_SHOULD_SKIP_THIS
45#include <visp3/core/vpDebug.h>
46#include <visp3/core/vpRobust.h>
47#include <visp3/core/vpTrackingException.h>
48#include <visp3/mbt/vpMbtMeLine.h>
55vpMbtMeLine::vpMbtMeLine()
56 :
vpMeLine(), imin(0), imax(0), jmin(0), jmax(0), expecteddensity(0.)
62vpMbtMeLine::vpMbtMeLine(
const vpMbtMeLine &meline)
68vpMbtMeLine &vpMbtMeLine::operator=(
const vpMbtMeLine &meline)
74 expecteddensity = meline.expecteddensity;
95 double rho,
double theta,
bool doNoTrack)
99 double id1, jd1, id2, jd2;
105 m_PExt[0].m_ifloat = id1;
106 m_PExt[0].m_jfloat = jd1;
107 m_PExt[1].m_ifloat = id2;
108 m_PExt[1].m_jfloat = jd2;
117 m_delta = atan2((jd2 - jd1), (id1 - id2));
119 sample(I, doNoTrack);
124 expecteddensity =
static_cast<double>(m_meList.size());
139 int nbrows =
static_cast<int>(I.getHeight());
140 int nbcols =
static_cast<int>(I.getWidth());
144 getExtremities(ip1, ip2);
145 double id1 = ip1.
get_i();
146 double jd1 = ip1.
get_j();
147 double id2 = ip2.
get_i();
148 double jd2 = ip2.
get_j();
151 double diffsi = id2 - id1;
152 double diffsj = jd2 - jd1;
155 double sample_step =
static_cast<double>(m_me->getSampleStep());
157 double di = diffsi * sample_step /
s;
158 double dj = diffsj * sample_step /
s;
162 P.
init(
static_cast<int>(id1),
static_cast<int>(jd1), m_delta, 0, m_sign);
164 const double marginRatio = m_me->getThresholdMarginRatio();
166 unsigned int memory_range = m_me->getRange();
169 unsigned int nb_added_points = 0;
173 for (
int i = 0;
i < 3; ++
i) {
179 if ((id1 < imin) || (id1 > imax) || (jd1 < jmin) || (jd1 > jmax)) {
186 else if (!outOfImage(iP, 5, nbrows, nbcols)) {
187 unsigned int is_uint =
static_cast<unsigned int>(id1);
188 unsigned int js_uint =
static_cast<unsigned int>(jd1);
189 if (inRoiMask(m_mask, is_uint, js_uint) && inMeMaskCandidates(m_maskCandidates, is_uint, js_uint)) {
192 P.
m_i =
static_cast<int>(id1);
194 P.
m_j =
static_cast<int>(jd1);
196 double contrastThreshold = fabs(convolution) * marginRatio;
199 P.
track(I, m_me,
false);
201 m_meList.push_front(P);
219 for (
int i = 0;
i < 3; ++
i) {
227 if ((id2 < imin) || (id2 > imax) || (jd2 < jmin) || (jd2 > jmax)) {
234 else if (!outOfImage(iP, 5, nbrows, nbcols)) {
235 unsigned int is_uint =
static_cast<unsigned int>(id2);
236 unsigned int js_uint =
static_cast<unsigned int>(jd2);
237 if (inRoiMask(m_mask, is_uint, js_uint) && inMeMaskCandidates(m_maskCandidates, is_uint, js_uint)) {
240 P.
m_i =
static_cast<int>(id2);
242 P.
m_j =
static_cast<int>(jd2);
244 double contrastThreshold = fabs(convolution) * marginRatio;
247 P.
track(I, m_me,
false);
249 m_meList.push_back(P);
264 m_me->setRange(memory_range);
265 return(nb_added_points);
275 for (std::list<vpMeSite>::iterator it = m_meList.begin(); it != m_meList.end();) {
279 if (fabs(sin(m_theta)) > 0.9) {
280 if ((
s.m_i < imin) || (
s.m_i > imax)) {
285 else if (fabs(cos(m_theta)) > 0.9) {
286 if ((
s.m_j < jmin) || (
s.m_j > jmax)) {
291 if ((
s.m_i < imin) || (
s.m_i > imax) || (
s.m_j < jmin) || (
s.m_j > jmax)) {
295 if (outOfImage(
s.m_i,
s.m_j,
static_cast<int>(m_me->getRange() + m_me->getMaskSize() + 1),
static_cast<int>(I.getHeight()),
static_cast<int>(I.getWidth()))) {
300 it = m_meList.erase(it);
324 bool display,
unsigned int length,
unsigned int thickness)
328 double deltaNormalized = m_theta;
329 unsigned int iter = 0;
331 while (deltaNormalized < 0) {
332 deltaNormalized += M_PI;
334 while (deltaNormalized > M_PI) {
335 deltaNormalized -= M_PI;
339 vecLine[0] = cos(deltaNormalized);
340 vecLine[1] = sin(deltaNormalized);
343 double offset = std::floor(SobelX.
getRows() / 2.0);
345 for (std::list<vpMeSite>::const_iterator it = m_meList.begin(); it != m_meList.end(); ++it) {
346 if (iter != 0 && iter + 1 != m_meList.size()) {
347 double gradientX = 0;
348 double gradientY = 0;
350 double iSite = it->m_ifloat;
351 double jSite = it->m_jfloat;
353 for (
unsigned int i = 0;
i < SobelX.
getRows(); ++
i) {
354 double iImg = iSite + (
i - offset);
355 for (
unsigned int j = 0;
j < SobelX.
getCols(); ++
j) {
356 double jImg = jSite + (
j - offset);
365 if (iImg > I.getHeight() - 1) {
366 iImg = I.getHeight() - 1;
368 if (jImg > I.getWidth() - 1) {
369 jImg = I.getWidth() - 1;
372 gradientX += SobelX[
i][
j] * I(
static_cast<unsigned int>(iImg),
static_cast<unsigned int>(jImg));
376 for (
unsigned int i = 0;
i < SobelY.
getRows(); ++
i) {
377 double iImg = iSite + (
i - offset);
378 for (
unsigned int j = 0;
j < SobelY.
getCols(); ++
j) {
379 double jImg = jSite + (
j - offset);
386 if (iImg > I.getHeight() - 1)
387 iImg = I.getHeight() - 1;
388 if (jImg > I.getWidth() - 1)
389 jImg = I.getWidth() - 1;
391 gradientY += SobelY[
i][
j] * I(
static_cast<unsigned int>(iImg),
static_cast<unsigned int>(jImg));
395 double angle = atan2(gradientX, gradientY);
399 while (angle > M_PI) {
404 vecGrad[0] = cos(angle);
405 vecGrad[1] = sin(angle);
408 double angle1 = acos(vecLine * vecGrad);
409 double angle2 = acos(vecLine * (-vecGrad));
412 vpDisplay::displayArrow(I, it->get_i(), it->get_j(),
static_cast<int>(it->get_i() + length * cos(deltaNormalized)),
413 static_cast<int>(it->get_j() + length * sin(deltaNormalized)),
vpColor::blue,
414 length >= 20 ? length / 5 : 4, length >= 20 ? length / 10 : 2, thickness);
415 if (angle1 < angle2) {
417 static_cast<int>(it->get_j() + length * sin(angle)),
vpColor::red, length >= 20 ? length / 5 : 4,
418 length >= 20 ? length / 10 : 2, thickness);
421 vpDisplay::displayArrow(I, it->get_i(), it->get_j(),
static_cast<int>(it->get_i() + length * cos(angle + M_PI)),
422 static_cast<int>(it->get_j() + length * sin(angle + M_PI)),
vpColor::red,
423 length >= 20 ? length / 5 : 4, length >= 20 ? length / 10 : 2, thickness);
427 sumErrorRad += std::min<double>(angle1, angle2);
449 m_PExt[0].m_ifloat =
static_cast<double>(ip1.
get_i());
450 m_PExt[0].m_jfloat =
static_cast<double>(ip1.
get_j());
451 m_PExt[1].m_ifloat =
static_cast<double>(ip2.
get_i());
452 m_PExt[1].m_jfloat =
static_cast<double>(ip2.
get_j());
464 if (m_mask !=
nullptr) {
466 expecteddensity =
static_cast<double>(m_meList.size());
508 double rho,
double theta)
520 reSample(I, ip1, ip2);
unsigned int getCols() const
unsigned int getRows() const
Implementation of column vector and the associated operations.
static const vpColor cyan
static const vpColor blue
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 flush(const vpImage< unsigned char > &I)
static void displayArrow(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_ij(double ii, double jj)
Definition of the vpImage class member functions.
static double sqr(double x)
Implementation of a matrix and operations on matrices.
Class that tracks in an image a line moving edges.
void reSample(const vpImage< unsigned char > &I)
void track(const vpImage< unsigned char > &I)
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'....
@ TOO_NEAR
Point not tracked anymore, since too near from its neighbor.
@ CONTRAST
Point not tracked due to a contrast problem, but retained in the ME list.
@ NO_SUPPRESSION
Point successfully tracked.
void setDisplay(vpMeSiteDisplayType select)
double m_ifloat
Subpixel coordinates along i of a site.
double convolution(const vpImage< unsigned char > &ima, const vpMe *me)
vpMeSiteState getState() const
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.
void setContrastThreshold(const double &thresh, const vpMe &me)
void track(const vpImage< unsigned char > &I, const vpMe *me, const bool &test_contrast=true)
void initTracking(const vpImage< unsigned char > &I)
void track(const vpImage< unsigned char > &I)
#define vpDEBUG_ENABLE(level)