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>
72 double norm = a*a + b*b;
73 double cross = b*i - a*j;
74 ip = (b*cross - a*c)/norm;
75 jp = (-a*cross - b*c)/norm;
116 vpDERROR_TRACE(2,
"Tracking error: Moving edges not initialized");
120 double sampleStep = fabs(
m_me->getSampleStep());
121 if (sampleStep <= std::numeric_limits<double>::epsilon()) {
127 double diffsi =
m_PExt[1].m_ifloat -
m_PExt[0].m_ifloat;
128 double diffsj =
m_PExt[1].m_jfloat -
m_PExt[0].m_jfloat;
131 if (length_p < (2.0 * sampleStep)) {
135 double n_sample = length_p / sampleStep;
137 double stepi = diffsi / n_sample;
138 double stepj = diffsj / n_sample;
141 double is =
m_PExt[0].m_ifloat;
142 double js =
m_PExt[0].m_jfloat;
148 int nbrows =
static_cast<int>(I.getHeight());
149 int nbcols =
static_cast<int>(I.getWidth());
150 const double marginRatio =
m_me->getThresholdMarginRatio();
156 unsigned int is_uint =
static_cast<unsigned int>(is);
157 unsigned int js_uint =
static_cast<unsigned int>(js);
164 double contrastThreshold = fabs(convolution) * marginRatio;
193 std::cout <<
"Click on the line first point..." << std::endl;
198 std::cout <<
"Click on the line second point..." << std::endl;
211 if (
m_meList.size() <= 2 || nos <= 2) {
215 const double nbr = I.getHeight() / 2.;
216 const double nbc = I.getWidth() / 2.;
229 std::list<vpMeSite>::const_iterator end =
m_meList.end();
231 for (std::list<vpMeSite>::const_iterator it =
m_meList.begin(); it != end; ++it) {
235 double u = (p_me.
m_ifloat - nbr) / nbr;
236 double v = (p_me.
m_jfloat - nbc) / nbc;
247 const unsigned int minRequiredNbMe = 2;
248 if (k < minRequiredNbMe) {
254 r.setMinMedianAbsoluteDeviation(1.0);
256 unsigned int iter = 0;
267 const unsigned int maxNbIter = 4;
268 const unsigned int widthDA = DA.
getCols();
269 while ((iter < maxNbIter) && (var > 0.1)) {
270 for (
unsigned int i = 0; i < k; ++i) {
271 for (
unsigned int j = 0; j < widthDA; ++j) {
272 DA[i][j] = w[i] * A[i][j];
275 unsigned int dim = DA.
nullSpace(KerDA, 1);
280 for (
unsigned int i = 0; i < 3; ++i) {
288 c = x[2] - x[0] - x[1];
296 var = (x - x_prev).frobeniusNorm();
300 for (
unsigned int i = 0; i < k; ++i) {
301 residu[i] = x[0] * xp[i] + x[1] * yp[i] + x[2];
314 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it != end;) {
336 double id1, jd1, id2, jd2;
347 m_delta = atan2((jd2 - jd1), (id1 - id2));
367 if (std::fabs(
m_me->getSampleStep()) <= std::numeric_limits<double>::epsilon()) {
371 int nbrows =
static_cast<int>(I.getHeight());
372 int nbcols =
static_cast<int>(I.getWidth());
374 unsigned int memory_range =
m_me->getRange();
377 const double marginRatio =
m_me->getThresholdMarginRatio();
379 unsigned int nb_added_points = 0;
381 std::list<vpMeSite>::iterator meList =
m_meList.begin();
382 std::list<vpMeSite>::const_iterator end =
m_meList.end();
388 const double sampleStep = fabs(
m_me->getSampleStep());
389 double diffsi =
m_PExt[1].m_ifloat -
m_PExt[0].m_ifloat;
390 double diffsj =
m_PExt[1].m_jfloat -
m_PExt[0].m_jfloat;
392 double stepi = diffsi * sampleStep / length;
393 double stepj = diffsj * sampleStep / length;
398 while (meList != end) {
404 const unsigned int n_sample =
static_cast<unsigned int>(floor(dist / sampleStep));
406 double is = ip1.
get_i();
407 double js = ip1.
get_j();
408 for (
unsigned int i = 0; i<n_sample; ++i) {
412 unsigned int is_uint =
static_cast<unsigned int>(is);
413 unsigned int js_uint =
static_cast<unsigned int>(js);
420 double contrastThreshold = fabs(convolution) * marginRatio;
440 m_me->setRange(memory_range);
442 return(nb_added_points);
447 int nbrows =
static_cast<int>(I.getHeight());
448 int nbcols =
static_cast<int>(I.getWidth());
453 double id1 = ip1.
get_i();
454 double jd1 = ip1.
get_j();
455 double id2 = ip2.
get_i();
456 double jd2 = ip2.
get_j();
459 double diffsi = id2 - id1;
460 double diffsj = jd2 - jd1;
463 double sample_step =
static_cast<double>(
m_me->getSampleStep());
465 double di = diffsi * sample_step / s;
466 double dj = diffsj * sample_step / s;
471 const double marginRatio =
m_me->getThresholdMarginRatio();
473 unsigned int memory_range =
m_me->getRange();
476 unsigned int nb_added_points = 0;
480 for (
int i = 0; i < 3; i++) {
488 unsigned int is_uint =
static_cast<unsigned int>(id1);
489 unsigned int js_uint =
static_cast<unsigned int>(jd1);
496 P.
m_i =
static_cast<int>(id1);
498 P.
m_j =
static_cast<int>(jd1);
500 double contrastThreshold = fabs(convolution) * marginRatio;
520 for (
int i = 0; i < 3; i++) {
530 unsigned int is_uint =
static_cast<unsigned int>(id2);
531 unsigned int js_uint =
static_cast<unsigned int>(jd2);
534 P.
m_i =
static_cast<int>(id2);
536 P.
m_j =
static_cast<int>(jd2);
538 double contrastThreshold = fabs(convolution) * marginRatio;
557 m_me->setRange(memory_range);
558 return(nb_added_points);
568 const unsigned int minNbGoodPoints = 4;
569 if (
m_meList.size() <= minNbGoodPoints) {
571 double id1, jd1, id2, jd2;
577 m_delta = atan2((jd2 - jd1), (id1 - id2));
599 std::list<vpMeSite>::const_iterator end =
m_meList.end();
600 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it != end; ++it) {
609 vpCDEBUG(1) <<
"begin vpMeLine::track()" << std::endl;
641void vpMeLine::update_indices(
double theta,
int i,
int j,
int incr,
int &i1,
int &i2,
int &j1,
int &j2)
643 i1 =
static_cast<int>(i + cos(theta) * incr);
644 j1 =
static_cast<int>(j + sin(theta) * incr);
646 i2 =
static_cast<int>(i - cos(theta) * incr);
647 j2 =
static_cast<int>(j - sin(theta) * incr);
656 unsigned int nb_pos = 0;
657 unsigned int nb_neg = 0;
659 std::list<vpMeSite>::const_iterator it =
m_meList.begin();
660 std::list<vpMeSite>::const_iterator end =
m_meList.end();
662 for (; it != end; ++it) {
681 if (nb_neg > nb_pos) {
685 double Mx = -cos(ang);
686 double My = sin(ang);
691 double d1 = (Px-Mx)*(Px-Mx) + (Py-My)*(Py-My);
692 double d2 = (-Px-Mx)*(-Px-Mx) + (-Py-My)*(-Py-My);
716 double a1 = line1.
m_a;
717 double b1 = line1.
m_b;
718 double c1 = line1.
m_c;
719 double a2 = line2.
m_a;
720 double b2 = line2.
m_b;
721 double c2 = line2.
m_c;
723 double det = a1*b2 - a2*b1;
725 if (std::fabs(det) <= std::numeric_limits<double>::epsilon()) {
726 std::cout <<
"!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
729 double i = (c2*b1 - c1*b2)/det;
730 double j = (a2*c1 - a1*c2)/det;
737#ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
753 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
773 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
794 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
795 const vpColor &color,
unsigned int thickness)
816 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
817 const vpColor &color,
unsigned int thickness)
826 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
830 if (fabs(A) < fabs(B)) {
831 double i1, j1, i2, j2;
833 j1 = (-A * i1 - C) / B;
834 i2 = I.getHeight() - 1.0;
835 j2 = (-A * i2 - C) / B;
844 double i1, j1, i2, j2;
846 i1 = -(B * j1 + C) / A;
847 j2 = I.getWidth() - 1.0;
848 i2 = -(B * j2 + C) / A;
865 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
869 if (fabs(A) < fabs(B)) {
870 double i1, j1, i2, j2;
872 j1 = (-A * i1 - C) / B;
873 i2 = I.getHeight() - 1.0;
874 j2 = (-A * i2 - C) / B;
883 double i1, j1, i2, j2;
885 i1 = -(B * j1 + C) / A;
886 j2 = I.getWidth() - 1.0;
887 i2 = -(B * j2 + C) / A;
903 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
904 const vpColor &color,
unsigned int thickness)
907 std::list<vpMeSite>::const_iterator end = site_list.end();
909 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != end; ++it) {
922 if (fabs(A) < fabs(B)) {
923 double i1, j1, i2, j2;
925 j1 = (-A * i1 - C) / B;
926 i2 = I.getHeight() - 1.0;
927 j2 = (-A * i2 - C) / B;
936 double i1, j1, i2, j2;
938 i1 = -(B * j1 + C) / A;
939 j2 = I.getWidth() - 1.0;
940 i2 = -(B * j2 + C) / A;
956 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
957 const vpColor &color,
unsigned int thickness)
960 std::list<vpMeSite>::const_iterator end = site_list.end();
962 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != end; ++it) {
975 if (fabs(A) < fabs(B)) {
976 double i1, j1, i2, j2;
978 j1 = (-A * i1 - C) / B;
979 i2 = I.getHeight() - 1.0;
980 j2 = (-A * i2 - C) / B;
989 double i1, j1, i2, j2;
991 i1 = -(B * j1 + C) / A;
992 j2 = I.getWidth() - 1.0;
993 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)
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)
Definition of the vpImage class member functions.
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
static double rad(double deg)
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
double m_theta
theta parameter of the line
unsigned int plugHoles(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.
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 project(double a, double b, double c, const vpMeSite &P, vpImagePoint &iP)
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)
vpMeLine & operator=(const vpMeLine &meline)
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)
unsigned int getIndex() const
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)
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)
Contains an M-estimator and various influence function.
@ TUKEY
Tukey influence function.
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.
#define vpDEBUG_ENABLE(level)