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()) {
135 vpERROR_TRACE(
"function called with sample step = 0");
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;
180 if (vpDEBUG_ENABLE(3)) {
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;
220 vpERROR_TRACE(
"Error caught");
240 unsigned int iter = 0;
241 unsigned int nos_1 = 0;
242 double distance = 100;
246 vpCDEBUG(1) <<
"Not enough point";
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);
420 vpERROR_TRACE(
"Error caught");
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()) {
501 vpERROR_TRACE(
"function called with sample step = 0");
511 double di = diffsi / sqrt(s);
512 double dj = diffsj / sqrt(s);
526 double contrastThreshold = fabs(convolution) * marginRatio;
532 for (
int i = 0; i < 3; i++) {
544 unsigned int is_uint =
static_cast<unsigned int>(P.
m_ifloat);
545 unsigned int js_uint =
static_cast<unsigned int>(P.
m_jfloat);
550 if (vpDEBUG_ENABLE(3)) {
555 if (vpDEBUG_ENABLE(3)) {
565 contrastThreshold = fabs(convolution) * marginRatio;
568 for (
int i = 0; i < 3; i++) {
580 unsigned int is_uint =
static_cast<unsigned int>(P.
m_ifloat);
581 unsigned int js_uint =
static_cast<unsigned int>(P.
m_jfloat);
586 if (vpDEBUG_ENABLE(3)) {
591 if (vpDEBUG_ENABLE(3)) {
601 vpCDEBUG(1) <<
"end vpMeLine::sample() : ";
602 vpCDEBUG(1) << n_sample <<
" point inserted in the list " << std::endl;
607 double i1, j1, i2, j2;
610 vpDERROR_TRACE(2,
"Tracking error: Moving edges not initialized");
628 if ((
double)n < 0.9 * expecteddensity) {
642 double angle_ =
m_delta + M_PI / 2;
647 while (angle_ > M_PI)
653 if (std::fabs(std::fabs(angle_) - 180) <= std::numeric_limits<double>::epsilon()) {
664 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end(); ++it) {
675 vpCDEBUG(1) <<
"begin vpMeLine::track()" << std::endl;
690 vpERROR_TRACE(
"Error caught");
703 vpERROR_TRACE(
"Error caught");
719 if (vpDEBUG_ENABLE(2)) {
728 vpCDEBUG(1) <<
"end vpMeLine::track()" << std::endl;
731 void vpMeLine::update_indices(
double theta,
int i,
int j,
int incr,
int &i1,
int &i2,
int &j1,
int &j2)
733 i1 = (int)(i + cos(theta) * incr);
734 j1 = (int)(j + sin(theta) * incr);
736 i2 = (int)(i - cos(theta) * incr);
737 j2 = (int)(j - sin(theta) * incr);
759 int i1 = 0, i2 = 0, j1 = 0, j2 = 0;
760 unsigned char v1 = 0, v2 = 0;
764 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
766 if (i1 < 0 || i1 >= height_ || i2 < 0 || i2 >= height_ || j1 < 0 || j1 >= width_ || j2 < 0 || j2 >= width_) {
767 double rho_lim1 = fabs((
double)i / cos(
m_theta));
768 double rho_lim2 = fabs((
double)j / sin(
m_theta));
770 double co_rho_lim1 = fabs(((
double)(height_ - i)) / cos(
m_theta));
771 double co_rho_lim2 = fabs(((
double)(width_ - j)) / sin(
m_theta));
773 double rho_lim = std::min<double>(rho_lim1, rho_lim2);
774 double co_rho_lim = std::min<double>(co_rho_lim1, co_rho_lim2);
775 incr = (int)std::floor(std::min<double>(rho_lim, co_rho_lim));
776 if (incr < INCR_MIN) {
777 vpERROR_TRACE(
"increment is too small");
780 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
785 unsigned int i1_ =
static_cast<unsigned int>(i1);
786 unsigned int j1_ =
static_cast<unsigned int>(j1);
787 unsigned int i2_ =
static_cast<unsigned int>(i2);
788 unsigned int j2_ =
static_cast<unsigned int>(j2);
791 if (abs(v1 - v2) < 1) {
796 "there is no gray level difference between both "
797 "sides of the line"));
800 update_indices(
m_theta, i, j, incr, i1, i2, j1, j2);
827 if (vpDEBUG_ENABLE(2)) {
858 double a1 = line1.
m_a;
859 double b1 = line1.
m_b;
860 double c1 = line1.
m_c;
861 double a2 = line2.
m_a;
862 double b2 = line2.
m_b;
863 double c2 = line2.
m_c;
870 denom = (-(a2 / a1) * b1 + b2);
873 if (std::fabs(denom) <= std::numeric_limits<double>::epsilon()) {
874 std::cout <<
"!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
879 if (std::fabs(denom) > std::numeric_limits<double>::epsilon()) {
880 j = ((a2 / a1) * c1 - c2) / denom;
881 i = (-b1 * j - c1) / a1;
886 denom = (-(b2 / b1) * a1 + a2);
889 if (std::fabs(denom) <= std::numeric_limits<double>::epsilon()) {
890 std::cout <<
"!!!!!!!!!!!!! Problem : Lines are parallel !!!!!!!!!!!!!" << std::endl;
895 if (std::fabs(denom) > std::numeric_limits<double>::epsilon()) {
896 i = ((b2 / b1) * c1 - c2) / denom;
897 j = (-a1 * i - c1) / b1;
910 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
933 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
960 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
989 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
990 const vpColor &color,
unsigned int thickness)
1019 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1020 const vpColor &color,
unsigned int thickness)
1028 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
1032 if (fabs(A) < fabs(B)) {
1033 double i1, j1, i2, j2;
1035 j1 = (-A * i1 - C) / B;
1037 j2 = (-A * i2 - C) / B;
1046 double i1, j1, i2, j2;
1048 i1 = -(B * j1 + C) / A;
1050 i2 = -(B * j2 + C) / A;
1069 const double &B,
const double &C,
const vpColor &color,
unsigned int thickness)
1073 if (fabs(A) < fabs(B)) {
1074 double i1, j1, i2, j2;
1076 j1 = (-A * i1 - C) / B;
1078 j2 = (-A * i2 - C) / B;
1087 double i1, j1, i2, j2;
1089 i1 = -(B * j1 + C) / A;
1091 i2 = -(B * j2 + C) / A;
1110 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1111 const vpColor &color,
unsigned int thickness)
1115 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != site_list.end(); ++it) {
1128 if (fabs(A) < fabs(B)) {
1129 double i1, j1, i2, j2;
1131 j1 = (-A * i1 - C) / B;
1133 j2 = (-A * i2 - C) / B;
1142 double i1, j1, i2, j2;
1144 i1 = -(B * j1 + C) / A;
1146 i2 = -(B * j2 + C) / A;
1165 const std::list<vpMeSite> &site_list,
const double &A,
const double &B,
const double &C,
1166 const vpColor &color,
unsigned int thickness)
1170 for (std::list<vpMeSite>::const_iterator it = site_list.begin(); it != site_list.end(); ++it) {
1183 if (fabs(A) < fabs(B)) {
1184 double i1, j1, i2, j2;
1186 j1 = (-A * i1 - C) / B;
1188 j2 = (-A * i2 - C) / B;
1197 double i1, j1, i2, j2;
1199 i1 = -(B * j1 + C) / A;
1201 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.