43 #include <visp3/core/vpDebug.h>
44 #include <visp3/core/vpImagePoint.h>
45 #include <visp3/core/vpMath.h>
46 #include <visp3/core/vpRobust.h>
47 #include <visp3/core/vpTrackingException.h>
48 #include <visp3/core/vpMatrixException.h>
49 #include <visp3/me/vpMe.h>
50 #include <visp3/me/vpMeLine.h>
51 #include <visp3/me/vpMeSite.h>
52 #include <visp3/me/vpMeTracker.h>
61 while (delta > M_PI) {
64 while (delta < -M_PI) {
72 double B = (double)(i1 - i2);
73 double A = (double)(j1 - j2);
92 double norm = a*a + b*b;
93 double cross = b*i - a*j;
94 ip = (b*cross - a*c)/norm;
95 jp = (-a*cross - b*c)/norm;
102 : m_rho(0.), m_theta(0.), m_delta(0.), m_delta_1(0.), m_angle(0.), m_angle_1(90), m_sign(1),
103 m_useIntensityForRho(true), m_a(0.), m_b(0.), m_c(0.)
107 :
vpMeTracker(meline), m_rho(0.), m_theta(0.), m_delta(0.), m_delta_1(0.), m_angle(0.), m_angle_1(90), m_sign(1),
108 m_useIntensityForRho(true), m_a(0.), m_b(0.), m_c(0.)
135 vpDERROR_TRACE(2,
"Tracking error: Moving edges not initialized");
140 if (sampleStep <= std::numeric_limits<double>::epsilon()) {
141 vpERROR_TRACE(
"function called with sample step = 0");
150 if (length_p < (2.0 * sampleStep)) {
154 double n_sample = length_p / sampleStep;
156 double stepi = diffsi / n_sample;
157 double stepj = diffsj / n_sample;
167 int nbrows =
static_cast<int>(I.
getHeight());
168 int nbcols =
static_cast<int>(I.
getWidth());
175 unsigned int is_uint =
static_cast<unsigned int>(is);
176 unsigned int js_uint =
static_cast<unsigned int>(js);
183 double contrastThreshold = fabs(convolution) * marginRatio;
186 if (vpDEBUG_ENABLE(3)) {
213 std::cout <<
"Click on the line first point..." << std::endl;
218 std::cout <<
"Click on the line second point..." << std::endl;
231 if (
m_meList.size() <= 2 || nos <= 2) {
236 const double nbc = I.
getWidth() / 2.;
249 std::list<vpMeSite>::const_iterator end =
m_meList.end();
251 for (std::list<vpMeSite>::const_iterator it =
m_meList.begin(); it != end; ++it) {
255 double u = (p_me.
m_ifloat - nbr) / nbr;
256 double v = (p_me.
m_jfloat - nbc) / nbc;
267 const unsigned int minRequiredNbMe = 2;
268 if (k < minRequiredNbMe) {
276 unsigned int iter = 0;
287 const unsigned int maxNbIter = 4;
288 const unsigned int widthDA = DA.
getCols();
289 while ((iter < maxNbIter) && (var > 0.1)) {
290 for (
unsigned int i = 0; i < k; ++i) {
291 for (
unsigned int j = 0; j < widthDA; ++j) {
292 DA[i][j] = w[i] * A[i][j];
295 unsigned int dim = DA.
nullSpace(KerDA, 1);
300 for (
unsigned int i = 0; i < 3; ++i) {
308 c = x[2] - x[0] - x[1];
316 var = (x - x_prev).frobeniusNorm();
320 for (
unsigned int i = 0; i < k; ++i) {
321 residu[i] = x[0] * xp[i] + x[1] * yp[i] + x[2];
334 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it != end;) {
361 double id1, jd1, id2, jd2;
393 if (std::fabs(
m_me->
getSampleStep()) <= std::numeric_limits<double>::epsilon()) {
397 int nbrows =
static_cast<int>(I.
getHeight());
398 int nbcols =
static_cast<int>(I.
getWidth());
405 unsigned int nb_added_points = 0;
407 std::list<vpMeSite>::iterator meList =
m_meList.begin();
408 std::list<vpMeSite>::const_iterator end =
m_meList.end();
418 double stepi = diffsi * sampleStep / length;
419 double stepj = diffsj * sampleStep / length;
424 while (meList != end) {
430 const unsigned int n_sample =
static_cast<unsigned int>(floor(dist / sampleStep));
432 double is = ip1.
get_i();
433 double js = ip1.
get_j();
434 for (
unsigned int i = 0; i<n_sample; ++i) {
438 unsigned int is_uint =
static_cast<unsigned int>(is);
439 unsigned int js_uint =
static_cast<unsigned int>(js);
446 double contrastThreshold = fabs(convolution) * marginRatio;
453 if (vpDEBUG_ENABLE(3)) {
468 return(nb_added_points);
473 int nbrows =
static_cast<int>(I.
getHeight());
474 int nbcols =
static_cast<int>(I.
getWidth());
479 double id1 = ip1.
get_i();
480 double jd1 = ip1.
get_j();
481 double id2 = ip2.
get_i();
482 double jd2 = ip2.
get_j();
485 double diffsi = id2 - id1;
486 double diffsj = jd2 - jd1;
491 double di = diffsi * sample_step / s;
492 double dj = diffsj * sample_step / s;
503 unsigned int nb_added_points = 0;
507 for (
int i = 0; i < 3; i++) {
515 unsigned int is_uint =
static_cast<unsigned int>(id1);
516 unsigned int js_uint =
static_cast<unsigned int>(jd1);
523 P.
m_i =
static_cast<int>(id1);
525 P.
m_j =
static_cast<int>(jd1);
527 double contrastThreshold = fabs(convolution) * marginRatio;
534 if (vpDEBUG_ENABLE(3)) {
539 if (vpDEBUG_ENABLE(3)) {
553 for (
int i = 0; i < 3; i++) {
563 unsigned int is_uint =
static_cast<unsigned int>(id2);
564 unsigned int js_uint =
static_cast<unsigned int>(jd2);
568 P.
m_i =
static_cast<int>(id2);
570 P.
m_j =
static_cast<int>(jd2);
572 double contrastThreshold = fabs(convolution) * marginRatio;
579 if (vpDEBUG_ENABLE(3)) {
584 if (vpDEBUG_ENABLE(3)) {
593 return(nb_added_points);
603 const unsigned int minNbGoodPoints = 4;
604 if (
m_meList.size() <= minNbGoodPoints) {
637 if (vpDEBUG_ENABLE(2)) {
651 double angle_ =
m_delta + M_PI / 2;
657 while (angle_ > M_PI)
662 int angle_int = (int)angle_;
663 if (angle_int == 180) angle_ = 179.0;
673 std::list<vpMeSite>::const_iterator end =
m_meList.end();
674 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it != end; ++it) {
685 vpCDEBUG(1) <<
"begin vpMeLine::track()" << std::endl;
709 if (vpDEBUG_ENABLE(2)) {
718 void vpMeLine::update_indices(
double theta,
int i,
int j,
int incr,
int &i1,
int &i2,
int &j1,
int &j2)
720 i1 = (int)(i + cos(theta) * incr);
721 j1 = (int)(j + sin(theta) * incr);
723 i2 = (int)(i - cos(theta) * incr);
724 j2 = (int)(j - sin(theta) * incr);
747 int i1 = 0, i2 = 0, j1 = 0, j2 = 0;
748 unsigned char v1 = 0, v2 = 0;
752 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
754 if (i1 < 0 || i1 >= height_ || i2 < 0 || i2 >= height_ || j1 < 0 || j1 >= width_ || j2 < 0 || j2 >= width_) {
755 double rho_lim1 = fabs((
double)i / cos(
m_theta));
756 double rho_lim2 = fabs((
double)j / sin(
m_theta));
758 double co_rho_lim1 = fabs(((
double)(height_ - i)) / cos(
m_theta));
759 double co_rho_lim2 = fabs(((
double)(width_ - j)) / sin(
m_theta));
761 double rho_lim = std::min<double>(rho_lim1, rho_lim2);
762 double co_rho_lim = std::min<double>(co_rho_lim1, co_rho_lim2);
763 incr = (int)std::floor(std::min<double>(rho_lim, co_rho_lim));
764 if (incr < INCR_MIN) {
765 vpERROR_TRACE(
"increment is too small");
768 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
773 unsigned int i1_ =
static_cast<unsigned int>(i1);
774 unsigned int j1_ =
static_cast<unsigned int>(j1);
775 unsigned int i2_ =
static_cast<unsigned int>(i2);
776 unsigned int j2_ =
static_cast<unsigned int>(j2);
779 if (abs(v1 - v2) < 1) {
784 "there is no grey level difference between both "
785 "sides of the line"));
788 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
815 if (vpDEBUG_ENABLE(2)) {
844 double a1 = line1.
m_a;
845 double b1 = line1.
m_b;
846 double c1 = line1.
m_c;
847 double a2 = line2.
m_a;
848 double b2 = line2.
m_b;
849 double c2 = line2.
m_c;
851 double det = a1*b2 - a2*b1;
853 if (std::fabs(det) <= std::numeric_limits<double>::epsilon()) {
854 std::cout <<
"!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
857 double i = (c2*b1 - c1*b2)/det;
858 double j = (a2*c1 - a1*c2)/det;
865 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
881 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
901 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
922 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
923 const vpColor &color,
unsigned int thickness)
944 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
945 const vpColor &color,
unsigned int thickness)
954 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
958 if (fabs(A) < fabs(B)) {
959 double i1, j1, i2, j2;
961 j1 = (-A * i1 - C) / B;
963 j2 = (-A * i2 - C) / B;
972 double i1, j1, i2, j2;
974 i1 = -(B * j1 + C) / A;
976 i2 = -(B * j2 + C) / A;
993 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
997 if (fabs(A) < fabs(B)) {
998 double i1, j1, i2, j2;
1000 j1 = (-A * i1 - C) / B;
1002 j2 = (-A * i2 - C) / B;
1011 double i1, j1, i2, j2;
1013 i1 = -(B * j1 + C) / A;
1015 i2 = -(B * j2 + C) / A;
1031 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1032 const vpColor &color,
unsigned int thickness)
1035 std::list<vpMeSite>::const_iterator end = site_list.end();
1037 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != end; ++it) {
1050 if (fabs(A) < fabs(B)) {
1051 double i1, j1, i2, j2;
1053 j1 = (-A * i1 - C) / B;
1055 j2 = (-A * i2 - C) / B;
1064 double i1, j1, i2, j2;
1066 i1 = -(B * j1 + C) / A;
1068 i2 = -(B * j2 + C) / A;
1084 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1085 const vpColor &color,
unsigned int thickness)
1088 std::list<vpMeSite>::const_iterator end = site_list.end();
1090 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != end; ++it) {
1103 if (fabs(A) < fabs(B)) {
1104 double i1, j1, i2, j2;
1106 j1 = (-A * i1 - C) / B;
1108 j2 = (-A * i2 - C) / B;
1117 double i1, j1, i2, j2;
1119 i1 = -(B * j1 + C) / A;
1121 i2 = -(B * j2 + C) / A;
unsigned int getCols() const
Implementation of column vector and the associated operations.
Class to define RGB colors available for display functionalities.
static const vpColor blue
static const vpColor green
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
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)
error that can be emitted by ViSP classes.
@ dimensionError
Bad dimension.
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)
unsigned int getWidth() const
unsigned int getHeight() const
static double sqr(double x)
static int round(double x)
error that can be emitted by the vpMatrix class and its derivatives
@ rankDeficient
Rank deficient.
Implementation of a matrix and operations on matrices.
unsigned int nullSpace(vpMatrix &kerA, double svThreshold=1e-6) const
Class that tracks in an image a line moving edges.
double m_angle
Angle in deg between the extremities.
double m_angle_1
Angle in deg between the extremities.
double m_theta
theta parameter of the line
void normalizeAngle(double &delta)
double m_delta_1
Angle in rad between the extremities.
unsigned int plugHoles(const vpImage< unsigned char > &I)
static void project(double a, double b, double c, const vpMeSite &P, vpImagePoint &iP)
void computeRhoTheta(const vpImage< unsigned char > &I)
void display(const vpImage< unsigned char > &I, const vpColor &color, unsigned int thickness=1)
void reSample(const vpImage< unsigned char > &I)
double m_c
Parameter c of the line equation a*i + b*j + c = 0.
void computeDelta(double &delta, double i1, double j1, double i2, double j2)
bool m_useIntensityForRho
double m_delta
Angle in rad between the extremities.
double m_rho
rho parameter of the line
void track(const vpImage< unsigned char > &I)
void getExtremities(vpImagePoint &ip1, vpImagePoint &ip2) const
static void displayLine(const vpImage< unsigned char > &I, const vpMeSite &PExt1, const vpMeSite &PExt2, const double &A, const double &B, const double &C, const vpColor &color=vpColor::green, unsigned int thickness=1)
double m_a
Parameter a of the line equation a*i + b*j + c = 0.
virtual void sample(const vpImage< unsigned char > &I, bool doNotTrack=false) VP_OVERRIDE
void leastSquare(const vpImage< unsigned char > &I)
double m_b
Parameter b of the line equation a*i + b*j + c = 0.
void initTracking(const vpImage< unsigned char > &I)
static bool intersection(const vpMeLine &line1, const vpMeLine &line2, vpImagePoint &iP)
virtual ~vpMeLine() VP_OVERRIDE
virtual unsigned int seekExtremities(const vpImage< unsigned char > &I)
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'....
int m_mask_sign
Mask sign.
@ M_ESTIMATOR
Point detected as an outlier during virtual visual-servoing.
@ 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)
void setAlpha(const double &a)
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 setState(const vpMeSiteState &flag)
Contains abstract elements for a Distance to Feature type feature.
void initTracking(const vpImage< unsigned char > &I)
const vpImage< bool > * m_mask
Mask used to disable tracking on a part of image.
unsigned int numberOfSignal()
vpMeSite::vpMeSiteDisplayType m_selectDisplay
Moving-edges display type.
void track(const vpImage< unsigned char > &I)
vpMe * m_me
Moving edges initialisation parameters.
static bool inRoiMask(const vpImage< bool > *mask, unsigned int i, unsigned int j)
void display(const vpImage< unsigned char > &I)
bool outOfImage(int i, int j, int border, int nrows, int ncols)
const vpImage< bool > * m_maskCandidates
Mask used to determine candidate points for initialization in an image.
std::list< vpMeSite > m_meList
static bool inMeMaskCandidates(const vpImage< bool > *meMaskCandidates, unsigned int i, unsigned int j)
void setRange(const unsigned int &range)
double getThresholdMarginRatio() const
double getSampleStep() const
unsigned int getRange() const
Contains an M-estimator and various influence function.
@ TUKEY
Tukey influence function.
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
void setMinMedianAbsoluteDeviation(double mad_min)
Error that can be emitted by the vpTracker class and its derivatives.
@ notEnoughPointError
Not enough point to track.
@ initializationError
Tracker initialization error.
@ fatalError
Tracker fatal error.