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/me/vpMe.h>
49 #include <visp3/me/vpMeLine.h>
50 #include <visp3/me/vpMeSite.h>
51 #include <visp3/me/vpMeTracker.h>
56 void computeDelta(
double &delta,
int i1,
int j1,
int i2,
int j2);
58 static void normalizeAngle(
double &delta)
60 while (delta > M_PI) {
63 while (delta < -M_PI) {
68 void computeDelta(
double &delta,
int i1,
int j1,
int i2,
int j2)
71 double B = double(i1 - i2);
72 double A = double(j1 - j2);
76 normalizeAngle(delta);
79 static void project(
double a,
double b,
double c,
double i,
double j,
double &ip,
double &jp)
81 if (fabs(a) > fabs(b)) {
83 ip = (-c - b * jp) / a;
87 jp = (-c - a * ip) / b;
92 : m_rho(0.), m_theta(0.), m_delta(0.), m_delta_1(0.), m_angle(0.), m_angle_1(90), m_sign(1),
93 m_useIntensityForRho(true), m_a(0.), m_b(0.), m_c(0.)
97 :
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),
98 m_useIntensityForRho(true), m_a(0.), m_b(0.), m_c(0.)
126 vpDERROR_TRACE(2,
"Tracking error: Moving edges not initialized");
130 int nbrows =
static_cast<int>(I.
getHeight());
131 int nbcols =
static_cast<int>(I.
getWidth());
134 if (std::fabs(
m_me->
getSampleStep()) <= std::numeric_limits<double>::epsilon()) {
144 if (std::fabs(length_p) <= std::numeric_limits<double>::epsilon())
149 double stepi = diffsi / (double)n_sample;
150 double stepj = diffsj / (double)n_sample;
166 unsigned int is_uint =
static_cast<unsigned int>(is);
167 unsigned int js_uint =
static_cast<unsigned int>(js);
177 double contrastThreshold = fabs(convolution) * marginRatio;
190 vpCDEBUG(1) <<
"end vpMeLine::sample() : ";
191 vpCDEBUG(1) << n_sample <<
" point inserted in the list " << std::endl;
205 std::cout <<
"Click on the line first point..." << std::endl;
210 std::cout <<
"Click on the line second point..." << std::endl;
240 unsigned int iter = 0;
241 unsigned int nos_1 = 0;
242 double distance = 100;
250 if ((fabs(
m_b) >= 0.9))
256 for (std::list<vpMeSite>::const_iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
266 while (iter < 4 && distance > 0.05) {
267 for (
unsigned int i = 0; i < k; i++) {
268 for (
unsigned int j = 0; j < 2; j++) {
269 DA[i][j] = w[i] * A[i][j];
280 for (
unsigned int i = 0; i < nos_1; i++) {
285 distance = fabs(x[0] - x_1[0]) + fabs(x[1] - x_1[1]);
290 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
319 for (std::list<vpMeSite>::const_iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
329 while (iter < 4 && distance > 0.05) {
338 for (
unsigned int i = 0; i < nos_1; i++) {
343 distance = fabs(x[0] - x_1[0]) + fabs(x[1] - x_1[1]);
348 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
377 vpCDEBUG(1) <<
" begin vpMeLine::initTracking()" << std::endl;
379 int i1s, j1s, i2s, j2s;
396 double angle_ = atan2((
double)(i1s - i2s), (
double)(j1s - j2s));
403 computeDelta(
m_delta, i1s, j1s, i2s, j2s);
423 vpCDEBUG(1) <<
" end vpMeLine::initTracking()" << std::endl;
429 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end();) {
447 for (std::list<vpMeSite>::const_iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
465 if (fabs(imin - imax) < 25) {
466 for (std::list<vpMeSite>::const_iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
487 vpCDEBUG(1) <<
"begin vpMeLine::sample() : " << std::endl;
490 vpDERROR_TRACE(2,
"Tracking error: Moving edges not initialized");
494 int nbrows =
static_cast<int>(I.
getHeight());
495 int nbcols =
static_cast<int>(I.
getWidth());
499 if (std::fabs(
m_me->
getSampleStep()) <= std::numeric_limits<double>::epsilon()) {
511 double di = diffsi / sqrt(s);
512 double dj = diffsj / sqrt(s);
528 for (
int i = 0; i < 3; i++) {
538 unsigned int is_uint =
static_cast<unsigned int>(P.
m_ifloat);
539 unsigned int js_uint =
static_cast<unsigned int>(P.
m_jfloat);
560 for (
int i = 0; i < 3; i++) {
570 unsigned int is_uint =
static_cast<unsigned int>(P.
m_ifloat);
571 unsigned int js_uint =
static_cast<unsigned int>(P.
m_jfloat);
592 vpCDEBUG(1) <<
"end vpMeLine::sample() : ";
593 vpCDEBUG(1) << n_sample <<
" point inserted in the list " << std::endl;
598 double i1, j1, i2, j2;
601 vpDERROR_TRACE(2,
"Tracking error: Moving edges not initialized");
619 if ((
double)n < 0.9 * expecteddensity) {
633 double angle_ =
m_delta + M_PI / 2;
638 while (angle_ > M_PI)
644 if (std::fabs(std::fabs(angle_) - 180) <= std::numeric_limits<double>::epsilon()) {
655 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
666 vpCDEBUG(1) <<
"begin vpMeLine::track()" << std::endl;
719 vpCDEBUG(1) <<
"end vpMeLine::track()" << std::endl;
722 void vpMeLine::update_indices(
double theta,
int i,
int j,
int incr,
int &i1,
int &i2,
int &j1,
int &j2)
724 i1 = (int)(i + cos(theta) * incr);
725 j1 = (int)(j + sin(theta) * incr);
727 i2 = (int)(i - cos(theta) * incr);
728 j2 = (int)(j - sin(theta) * incr);
750 int i1 = 0, i2 = 0, j1 = 0, j2 = 0;
751 unsigned char v1 = 0, v2 = 0;
755 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
757 if (i1 < 0 || i1 >= height_ || i2 < 0 || i2 >= height_ || j1 < 0 || j1 >= width_ || j2 < 0 || j2 >= width_) {
758 double rho_lim1 = fabs((
double)i / cos(
m_theta));
759 double rho_lim2 = fabs((
double)j / sin(
m_theta));
761 double co_rho_lim1 = fabs(((
double)(height_ - i)) / cos(
m_theta));
762 double co_rho_lim2 = fabs(((
double)(width_ - j)) / sin(
m_theta));
764 double rho_lim = std::min<double>(rho_lim1, rho_lim2);
765 double co_rho_lim = std::min<double>(co_rho_lim1, co_rho_lim2);
766 incr = (int)std::floor(std::min<double>(rho_lim, co_rho_lim));
767 if (incr < INCR_MIN) {
771 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
776 unsigned int i1_ =
static_cast<unsigned int>(i1);
777 unsigned int j1_ =
static_cast<unsigned int>(j1);
778 unsigned int i2_ =
static_cast<unsigned int>(i2);
779 unsigned int j2_ =
static_cast<unsigned int>(j2);
782 if (abs(v1 - v2) < 1) {
787 "there is no gray level difference between both "
788 "sides of the line"));
791 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
849 double a1 = line1.
m_a;
850 double b1 = line1.
m_b;
851 double c1 = line1.
m_c;
852 double a2 = line2.
m_a;
853 double b2 = line2.
m_b;
854 double c2 = line2.
m_c;
861 denom = (-(a2 / a1) * b1 + b2);
864 if (std::fabs(denom) <= std::numeric_limits<double>::epsilon()) {
865 std::cout <<
"!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
870 if (std::fabs(denom) > std::numeric_limits<double>::epsilon()) {
871 j = ((a2 / a1) * c1 - c2) / denom;
872 i = (-b1 * j - c1) / a1;
877 denom = (-(b2 / b1) * a1 + a2);
880 if (std::fabs(denom) <= std::numeric_limits<double>::epsilon()) {
881 std::cout <<
"!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
886 if (std::fabs(denom) > std::numeric_limits<double>::epsilon()) {
887 i = ((b2 / b1) * c1 - c2) / denom;
888 j = (-a1 * i - c1) / b1;
901 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
924 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
951 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
980 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
981 const vpColor &color,
unsigned int thickness)
1010 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1011 const vpColor &color,
unsigned int thickness)
1019 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
1023 if (fabs(A) < fabs(B)) {
1024 double i1, j1, i2, j2;
1026 j1 = (-A * i1 - C) / B;
1028 j2 = (-A * i2 - C) / B;
1037 double i1, j1, i2, j2;
1039 i1 = -(B * j1 + C) / A;
1041 i2 = -(B * j2 + C) / A;
1060 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
1064 if (fabs(A) < fabs(B)) {
1065 double i1, j1, i2, j2;
1067 j1 = (-A * i1 - C) / B;
1069 j2 = (-A * i2 - C) / B;
1078 double i1, j1, i2, j2;
1080 i1 = -(B * j1 + C) / A;
1082 i2 = -(B * j2 + C) / A;
1101 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1102 const vpColor &color,
unsigned int thickness)
1106 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != site_list.end(); ++it) {
1119 if (fabs(A) < fabs(B)) {
1120 double i1, j1, i2, j2;
1122 j1 = (-A * i1 - C) / B;
1124 j2 = (-A * i2 - C) / B;
1133 double i1, j1, i2, j2;
1135 i1 = -(B * j1 + C) / A;
1137 i2 = -(B * j2 + C) / A;
1156 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1157 const vpColor &color,
unsigned int thickness)
1161 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != site_list.end(); ++it) {
1174 if (fabs(A) < fabs(B)) {
1175 double i1, j1, i2, j2;
1177 j1 = (-A * i1 - C) / B;
1179 j2 = (-A * i2 - C) / B;
1188 double i1, j1, i2, j2;
1190 i1 = -(B * j1 + C) / A;
1192 i2 = -(B * j2 + C) / A;
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.
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)
Implementation of a matrix and operations on matrices.
vpMatrix pseudoInverse(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
double m_delta_1
Angle in rad between the extremities.
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.
bool m_useIntensityForRho
double m_delta
Angle in rad between the extremities.
double m_rho
rho parameter of the line
void seekExtremities(const vpImage< unsigned char > &I)
void track(const vpImage< unsigned char > &I)
static bool intersection(const vpMeLine &line1, const vpMeLine &line2, vpImagePoint &ip)
void getExtremities(vpImagePoint &ip1, vpImagePoint &ip2)
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
double m_b
Parameter b of the line equation a*i + b*j + c = 0.
vpMeSite m_PExt[2]
Line extremities.
void initTracking(const vpImage< unsigned char > &I)
virtual ~vpMeLine() VP_OVERRIDE
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.
#define vpDEBUG_ENABLE(level)