42 #include <visp3/core/vpImageConvert.h>
43 #include <visp3/core/vpImageFilter.h>
44 #include <visp3/core/vpImagePoint.h>
45 #include <visp3/core/vpImageTools.h>
46 #include <visp3/core/vpMath.h>
47 #include <visp3/core/vpRect.h>
48 #include <visp3/core/vpRobust.h>
49 #include <visp3/core/vpTrackingException.h>
50 #include <visp3/me/vpMe.h>
51 #include <visp3/me/vpMeNurbs.h>
52 #include <visp3/me/vpMeSite.h>
53 #include <visp3/me/vpMeTracker.h>
54 #if defined(HAVE_OPENCV_IMGPROC)
55 #include <opencv2/imgproc/imgproc.hpp>
56 #if (VISP_HAVE_OPENCV_VERSION < 0x050000)
57 #include <opencv2/imgproc/imgproc_c.h>
62 double computeDelta(
double deltai,
double deltaj);
65 bool findCenterPoint(std::list<vpImagePoint> *ip_edges_list);
69 double computeDelta(
double deltai,
double deltaj)
72 delta = atan2(deltai, deltaj);
74 while (delta > M_PI) {
85 static bool outOfImage(
const vpImagePoint &iP,
int half,
int rows,
int cols)
87 return ((iP.
get_i() < half + 1) || (iP.
get_i() > (rows - half - 3)) || (iP.
get_j() < half + 1) ||
88 (iP.
get_j() > (cols - half - 3)));
101 for (
int i = 0; i < 180; i++) {
106 if (outOfImage(iP, (
int)half + me->
getStrip(), Iheight, Iwidth)) {
117 unsigned int ihalf = (
unsigned int)(iP.
get_i() - half);
118 unsigned int jhalf = (
unsigned int)(iP.
get_j() - half);
122 unsigned int ihalfa = ihalf + a;
124 conv += me->
getMask()[index_mask][a][b] * I(ihalfa, jhalf + b);
133 while (angle > M_PI) {
154 for (
unsigned int i = 0; i <= Isub.
getHeight(); i++) {
155 for (
unsigned int j = 0; j <= Isub.
getWidth(); j++) {
157 if (Isub(i, j) > 0) {
159 if (dist <= 16 && dist < dist_1) {
172 bool findCenterPoint(std::list<vpImagePoint> *ip_edges_list)
174 for (std::list<vpImagePoint>::const_iterator it = ip_edges_list->begin(); it != ip_edges_list->end(); ++it) {
187 : nurbs(), dist(0.), nbControlPoints(20), beginPtFound(0), endPtFound(0), enableCannyDetection(false), cannyTh1(100.),
192 :
vpMeTracker(menurbs), nurbs(menurbs.nurbs), dist(0.), nbControlPoints(20), beginPtFound(0), endPtFound(0),
193 enableCannyDetection(false), cannyTh1(100.f), cannyTh2(200.f)
196 nbControlPoints = menurbs.nbControlPoints;
197 beginPtFound = menurbs.beginPtFound;
198 endPtFound = menurbs.endPtFound;
199 enableCannyDetection = menurbs.enableCannyDetection;
200 cannyTh1 = menurbs.cannyTh1;
201 cannyTh2 = menurbs.cannyTh2;
206 std::list<vpImagePoint> ptList;
213 ptList.push_back(pt);
220 if (ptList.size() > 3)
253 double delta = computeDelta(pt[1].get_i(), pt[1].get_j());
259 pix.
init(pt[0].get_i(), pt[0].get_j(), delta);
273 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end();) {
289 std::list<vpMeSite>::iterator it =
m_meList.begin();
294 while (u < 1 && it !=
m_meList.end()) {
297 while (d <= d_1 && u < 1) {
311 s.
setAlpha(computeDelta(der[1].get_i(), der[1].get_j()));
337 if (d > threshold ) {
341 P.
init(begin[0].get_i(), begin[0].get_j(), (
m_meList.front()).getAlpha(), 0, (
m_meList.front()).m_mask_sign);
349 bool beginPtAdded =
false;
351 double angle = atan2(begin[1].get_i(), begin[1].get_j());
356 for (
int i = 0; i < 3; i++) {
371 if (vpDEBUG_ENABLE(3)) {
376 if (vpDEBUG_ENABLE(3)) {
386 P.
init(end[0].get_i(), end[0].get_j(), (
m_meList.back()).getAlpha(), 0, (
m_meList.back()).m_mask_sign);
389 bool endPtAdded =
false;
390 angle = atan2(end[1].get_i(), end[1].get_j());
395 for (
int i = 0; i < 3; i++) {
409 if (vpDEBUG_ENABLE(3)) {
414 if (vpDEBUG_ENABLE(3)) {
437 if (beginPtFound >= 3 && farFromImageEdge(I, firstPoint)) {
441 vpImagePoint topLeft(begin[0].get_i() - 15, begin[0].get_j() - 15);
442 vpRect rect(topLeft, 32, 32);
450 double step = 0.0001;
453 while (inRectangle(lastPtInSubIm, rect) && u < 1) {
466 firstBorder = findFirstBorder(Isub, lastPtInSubIm - topLeft);
468 std::list<vpImagePoint> ip_edges_list;
471 double fi =
static_cast<double>(firstBorder.
get_i());
472 double fj =
static_cast<double>(firstBorder.
get_j());
476 if (std::fabs(fi) <= std::numeric_limits<double>::epsilon())
479 else if (std::fabs(fi - h) <= std::fabs(
vpMath::maximum(fi, h)) * std::numeric_limits<double>::epsilon())
482 else if (std::fabs(fj) <= std::numeric_limits<double>::epsilon())
485 else if (std::fabs(fj - w) <= std::fabs(
vpMath::maximum(fj, w)) * std::numeric_limits<double>::epsilon())
487 computeFreemanChainElement(Isub, firstBorder, dir);
488 unsigned int firstDir = dir;
489 ip_edges_list.push_back(firstBorder);
493 computeFreemanParameters(dir, dBorder);
494 border = border + dBorder;
497 ip_edges_list.push_back(border);
499 computeFreemanChainElement(Isub, border, dir);
500 }
while ((border != firstBorder || dir != firstDir) && isInImage(Isub, border));
503 if (findCenterPoint(&ip_edges_list)) {
504 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end();
508 if (inRectangle(iP, rect))
514 std::list<vpMeSite>::iterator itList =
m_meList.begin();
517 unsigned int nbr = 0;
518 std::list<vpMeSite> addedPt;
519 for (std::list<vpImagePoint>::const_iterator itEdges = ip_edges_list.begin(); itEdges != ip_edges_list.end();
528 for (std::list<vpMeSite>::const_iterator itAdd = addedPt.begin(); itAdd != addedPt.end(); ++itAdd) {
534 findAngle(I, iPtemp,
m_me, delta, convlt);
540 addedPt.push_front(pix);
548 std::list<vpMeSite>::iterator itList2 =
m_meList.begin();
549 for (
unsigned int j = 0; j < nbr; j++) {
562 if (endPtFound >= 3 && farFromImageEdge(I, lastPoint)) {
567 vpImagePoint topLeft(end[0].get_i() - 15, end[0].get_j() - 15);
568 vpRect rect(topLeft, 32, 32);
576 double step = 0.0001;
579 while (inRectangle(lastPtInSubIm, rect) && u > 0) {
592 firstBorder = findFirstBorder(Isub, lastPtInSubIm - topLeft);
594 std::list<vpImagePoint> ip_edges_list;
597 double fi = firstBorder.
get_i();
598 double fj = firstBorder.
get_j();
602 if (std::fabs(fi) <= std::numeric_limits<double>::epsilon())
605 else if (std::fabs(fi - h) <= std::fabs(
vpMath::maximum(fi, h)) * std::numeric_limits<double>::epsilon())
608 else if (std::fabs(fj) <= std::numeric_limits<double>::epsilon())
611 else if (std::fabs(fj - w) <= std::fabs(
vpMath::maximum(fj, w)) * std::numeric_limits<double>::epsilon())
614 computeFreemanChainElement(Isub, firstBorder, dir);
615 unsigned int firstDir = dir;
616 ip_edges_list.push_back(firstBorder);
620 computeFreemanParameters(dir, dBorder);
621 border = border + dBorder;
624 ip_edges_list.push_back(border);
626 computeFreemanChainElement(Isub, border, dir);
627 }
while ((border != firstBorder || dir != firstDir) && isInImage(Isub, border));
630 if (findCenterPoint(&ip_edges_list)) {
633 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it!=
m_meList.end(); ++it) {
636 if (inRectangle(iP, rect)) {
643 std::list<vpMeSite>::iterator itList =
m_meList.end();
647 unsigned int nbr = 0;
648 std::list<vpMeSite> addedPt;
649 for (std::list<vpImagePoint>::const_iterator itEdges = ip_edges_list.begin(); itEdges != ip_edges_list.end();
658 for (std::list<vpMeSite>::const_iterator itAdd = addedPt.begin(); itAdd != addedPt.end(); ++itAdd) {
664 findAngle(I, iPtemp,
m_me, delta, convlt);
668 addedPt.push_back(pix);
676 std::list<vpMeSite>::iterator itList2 =
m_meList.end();
678 for (
unsigned int j = 0; j < nbr; j++) {
697 if ((
double)n < 0.7 * nbPt) {
711 std::list<vpMeSite>::iterator it =
m_meList.begin();
712 std::list<vpMeSite>::iterator itNext =
m_meList.begin();
731 double dmin1_1 = 1e6;
732 double dmin2_1 = 1e6;
738 if (dmin1 < dmin1_1) {
743 if (dmin2 < dmin2_1) {
751 if ((std::fabs(u - 1.0) > std::fabs(
vpMath::maximum(u, 1.0)) * std::numeric_limits<double>::epsilon()) ||
752 (std::fabs(uend - 1.0) > std::fabs(
vpMath::maximum(uend, 1.0)) * std::numeric_limits<double>::epsilon())) {
764 double delta = computeDelta(iP[1].get_i(), iP[1].get_j());
766 pix.
init(iP[0].get_i(), iP[0].get_j(), delta);
789 std::list<vpMeSite>::const_iterator it =
m_meList.begin();
790 std::list<vpMeSite>::iterator itNext =
m_meList.begin();
836 if (enableCannyDetection)
849 if (std::fabs(u) > std::numeric_limits<double>::epsilon())
885 if (hasGoodLevel(I, iP)) {
887 computeFreemanParameters((element + 2) % 8, diP);
889 if (hasGoodLevel(I, iPtemp)) {
890 element = (element + 2) % 8;
893 computeFreemanParameters((element + 1) % 8, diP);
896 if (hasGoodLevel(I, iPtemp)) {
897 element = (element + 1) % 8;
900 computeFreemanParameters(element, diP);
903 if (hasGoodLevel(I, iPtemp)) {
907 computeFreemanParameters((element + 7) % 8, diP);
910 if (hasGoodLevel(I, iPtemp)) {
911 element = (element + 7) % 8;
914 computeFreemanParameters((element + 6) % 8, diP);
917 if (hasGoodLevel(I, iPtemp)) {
918 element = (element + 6) % 8;
921 computeFreemanParameters((element + 5) % 8, diP);
924 if (hasGoodLevel(I, iPtemp)) {
925 element = (element + 5) % 8;
928 computeFreemanParameters((element + 4) % 8, diP);
931 if (hasGoodLevel(I, iPtemp)) {
932 element = (element + 4) % 8;
935 computeFreemanParameters((element + 3) % 8, diP);
938 if (hasGoodLevel(I, iPtemp)) {
939 element = (element + 3) % 8;
974 if (!isInImage(I, iP))
1017 void vpMeNurbs::computeFreemanParameters(
unsigned int element,
vpImagePoint &diP)
1076 return (iP.
get_i() < height - 20 && iP.
get_j() < width - 20 && iP.
get_i() > 20 && iP.
get_j() > 20);
Class to define RGB colors available for display functionalities.
static const vpColor orange
static const vpColor blue
static const vpColor green
static bool getClick(const vpImage< unsigned char > &I, bool blocking=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 displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
static void displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
error that can be emitted by ViSP classes.
@ notInitialized
Used to indicate that a parameter is not initialized.
@ divideByZeroError
Division by zero.
static void canny(const vpImage< unsigned char > &I, vpImage< unsigned char > &Ic, const unsigned int &gaussianFilterSize, const float &thresholdCanny, const unsigned int &apertureSobel)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_ij(double ii, double jj)
static double sqrDistance(const vpImagePoint &iP1, const vpImagePoint &iP2)
unsigned int getWidth() const
unsigned int getHeight() const
static double rad(double deg)
static Type maximum(const Type &a, const Type &b)
static double sqr(double x)
static Type abs(const Type &x)
static int round(double x)
static int sign(double x)
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.
@ NO_SUPPRESSION
Point successfully tracked.
void setDisplay(vpMeSiteDisplayType select)
double m_ifloat
Subpixel coordinates along i of a site.
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.
static double sqrDistance(const vpMeSite &S1, const vpMeSite &S2)
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)
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.
bool outOfImage(int i, int j, int border, int nrows, int ncols)
std::list< vpMeSite > m_meList
void setRange(const unsigned int &range)
unsigned int getAngleStep() const
int getPointsToTrack() const
unsigned int getMaskSize() const
vpMatrix * getMask() const
double getSampleStep() const
unsigned int getRange() const
Class that provides tools to compute and manipulate a Non Uniform Rational B-Spline curve.
static void globalCurveInterp(std::vector< vpImagePoint > &l_crossingPoints, unsigned int l_p, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
static vpImagePoint computeCurvePoint(double l_u, unsigned int l_i, unsigned int l_p, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
static vpImagePoint * computeCurveDersPoint(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
static void globalCurveApprox(std::vector< vpImagePoint > &l_crossingPoints, unsigned int l_p, unsigned int l_n, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
Defines a rectangle in the plane.
Error that can be emitted by the vpTracker class and its derivatives.
@ notEnoughPointError
Not enough point to track.