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 #include <opencv2/imgproc/imgproc_c.h>
60 double computeDelta(
double deltai,
double deltaj);
63 bool findCenterPoint(std::list<vpImagePoint> *ip_edges_list);
67 double computeDelta(
double deltai,
double deltaj)
70 delta = atan2(deltai, deltaj);
72 while (delta > M_PI) {
83 static bool outOfImage(
const vpImagePoint &iP,
int half,
int rows,
int cols)
85 return ((iP.
get_i() < half + 1) || (iP.
get_i() > (rows - half - 3)) || (iP.
get_j() < half + 1) ||
86 (iP.
get_j() > (cols - half - 3)));
99 for (
int i = 0; i < 180; i++) {
104 if (outOfImage(iP, (
int)half + me->
getStrip(), Iheight, Iwidth)) {
115 unsigned int ihalf = (
unsigned int)(iP.
get_i() - half);
116 unsigned int jhalf = (
unsigned int)(iP.
get_j() - half);
120 unsigned int ihalfa = ihalf + a;
122 conv += me->
getMask()[index_mask][a][b] * I(ihalfa, jhalf + b);
131 while (angle > M_PI) {
152 for (
unsigned int i = 0; i <= Isub.
getHeight(); i++) {
153 for (
unsigned int j = 0; j <= Isub.
getWidth(); j++) {
155 if (Isub(i, j) > 0) {
157 if (dist <= 16 && dist < dist_1) {
170 bool findCenterPoint(std::list<vpImagePoint> *ip_edges_list)
172 for (std::list<vpImagePoint>::const_iterator it = ip_edges_list->begin(); it != ip_edges_list->end(); ++it) {
185 : nurbs(), dist(0.), nbControlPoints(20), beginPtFound(0), endPtFound(0), enableCannyDetection(false), cannyTh1(100.),
190 :
vpMeTracker(menurbs), nurbs(menurbs.nurbs), dist(0.), nbControlPoints(20), beginPtFound(0), endPtFound(0),
191 enableCannyDetection(false), cannyTh1(100.f), cannyTh2(200.f)
194 nbControlPoints = menurbs.nbControlPoints;
195 beginPtFound = menurbs.beginPtFound;
196 endPtFound = menurbs.endPtFound;
197 enableCannyDetection = menurbs.enableCannyDetection;
198 cannyTh1 = menurbs.cannyTh1;
199 cannyTh2 = menurbs.cannyTh2;
204 std::list<vpImagePoint> ptList;
211 ptList.push_back(pt);
218 if (ptList.size() > 3)
251 double delta = computeDelta(pt[1].get_i(), pt[1].get_j());
257 pix.
init(pt[0].get_i(), pt[0].get_j(), delta);
271 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end();) {
287 std::list<vpMeSite>::iterator it =
m_meList.begin();
292 while (u < 1 && it !=
m_meList.end()) {
295 while (d <= d_1 && u < 1) {
309 s.
setAlpha(computeDelta(der[1].get_i(), der[1].get_j()));
335 if (d > threshold ) {
339 P.
init(begin[0].get_i(), begin[0].get_j(), (
m_meList.front()).getAlpha(), 0, (
m_meList.front()).m_mask_sign);
347 bool beginPtAdded =
false;
349 double angle = atan2(begin[1].get_i(), begin[1].get_j());
354 for (
int i = 0; i < 3; i++) {
369 if (vpDEBUG_ENABLE(3)) {
374 if (vpDEBUG_ENABLE(3)) {
384 P.
init(end[0].get_i(), end[0].get_j(), (
m_meList.back()).getAlpha(), 0, (
m_meList.back()).m_mask_sign);
387 bool endPtAdded =
false;
388 angle = atan2(end[1].get_i(), end[1].get_j());
393 for (
int i = 0; i < 3; i++) {
407 if (vpDEBUG_ENABLE(3)) {
412 if (vpDEBUG_ENABLE(3)) {
435 if (beginPtFound >= 3 && farFromImageEdge(I, firstPoint)) {
439 vpImagePoint topLeft(begin[0].get_i() - 15, begin[0].get_j() - 15);
440 vpRect rect(topLeft, 32, 32);
448 double step = 0.0001;
451 while (inRectangle(lastPtInSubIm, rect) && u < 1) {
464 firstBorder = findFirstBorder(Isub, lastPtInSubIm - topLeft);
466 std::list<vpImagePoint> ip_edges_list;
469 double fi =
static_cast<double>(firstBorder.
get_i());
470 double fj =
static_cast<double>(firstBorder.
get_j());
474 if (std::fabs(fi) <= std::numeric_limits<double>::epsilon())
477 else if (std::fabs(fi - h) <= std::fabs(
vpMath::maximum(fi, h)) * std::numeric_limits<double>::epsilon())
480 else if (std::fabs(fj) <= std::numeric_limits<double>::epsilon())
483 else if (std::fabs(fj - w) <= std::fabs(
vpMath::maximum(fj, w)) * std::numeric_limits<double>::epsilon())
485 computeFreemanChainElement(Isub, firstBorder, dir);
486 unsigned int firstDir = dir;
487 ip_edges_list.push_back(firstBorder);
491 computeFreemanParameters(dir, dBorder);
492 border = border + dBorder;
495 ip_edges_list.push_back(border);
497 computeFreemanChainElement(Isub, border, dir);
498 }
while ((border != firstBorder || dir != firstDir) && isInImage(Isub, border));
501 if (findCenterPoint(&ip_edges_list)) {
502 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it !=
m_meList.end();
506 if (inRectangle(iP, rect))
512 std::list<vpMeSite>::iterator itList =
m_meList.begin();
515 unsigned int nbr = 0;
516 std::list<vpMeSite> addedPt;
517 for (std::list<vpImagePoint>::const_iterator itEdges = ip_edges_list.begin(); itEdges != ip_edges_list.end();
526 for (std::list<vpMeSite>::const_iterator itAdd = addedPt.begin(); itAdd != addedPt.end(); ++itAdd) {
532 findAngle(I, iPtemp,
m_me, delta, convlt);
538 addedPt.push_front(pix);
546 std::list<vpMeSite>::iterator itList2 =
m_meList.begin();
547 for (
unsigned int j = 0; j < nbr; j++) {
560 if (endPtFound >= 3 && farFromImageEdge(I, lastPoint)) {
565 vpImagePoint topLeft(end[0].get_i() - 15, end[0].get_j() - 15);
566 vpRect rect(topLeft, 32, 32);
574 double step = 0.0001;
577 while (inRectangle(lastPtInSubIm, rect) && u > 0) {
590 firstBorder = findFirstBorder(Isub, lastPtInSubIm - topLeft);
592 std::list<vpImagePoint> ip_edges_list;
595 double fi = firstBorder.
get_i();
596 double fj = firstBorder.
get_j();
600 if (std::fabs(fi) <= std::numeric_limits<double>::epsilon())
603 else if (std::fabs(fi - h) <= std::fabs(
vpMath::maximum(fi, h)) * std::numeric_limits<double>::epsilon())
606 else if (std::fabs(fj) <= std::numeric_limits<double>::epsilon())
609 else if (std::fabs(fj - w) <= std::fabs(
vpMath::maximum(fj, w)) * std::numeric_limits<double>::epsilon())
612 computeFreemanChainElement(Isub, firstBorder, dir);
613 unsigned int firstDir = dir;
614 ip_edges_list.push_back(firstBorder);
618 computeFreemanParameters(dir, dBorder);
619 border = border + dBorder;
622 ip_edges_list.push_back(border);
624 computeFreemanChainElement(Isub, border, dir);
625 }
while ((border != firstBorder || dir != firstDir) && isInImage(Isub, border));
628 if (findCenterPoint(&ip_edges_list)) {
631 for (std::list<vpMeSite>::iterator it =
m_meList.begin(); it!=
m_meList.end(); ++it) {
634 if (inRectangle(iP, rect)) {
641 std::list<vpMeSite>::iterator itList =
m_meList.end();
645 unsigned int nbr = 0;
646 std::list<vpMeSite> addedPt;
647 for (std::list<vpImagePoint>::const_iterator itEdges = ip_edges_list.begin(); itEdges != ip_edges_list.end();
656 for (std::list<vpMeSite>::const_iterator itAdd = addedPt.begin(); itAdd != addedPt.end(); ++itAdd) {
662 findAngle(I, iPtemp,
m_me, delta, convlt);
666 addedPt.push_back(pix);
674 std::list<vpMeSite>::iterator itList2 =
m_meList.end();
676 for (
unsigned int j = 0; j < nbr; j++) {
695 if ((
double)n < 0.7 * nbPt) {
709 std::list<vpMeSite>::iterator it =
m_meList.begin();
710 std::list<vpMeSite>::iterator itNext =
m_meList.begin();
729 double dmin1_1 = 1e6;
730 double dmin2_1 = 1e6;
736 if (dmin1 < dmin1_1) {
741 if (dmin2 < dmin2_1) {
749 if ((std::fabs(u - 1.0) > std::fabs(
vpMath::maximum(u, 1.0)) * std::numeric_limits<double>::epsilon()) ||
750 (std::fabs(uend - 1.0) > std::fabs(
vpMath::maximum(uend, 1.0)) * std::numeric_limits<double>::epsilon())) {
762 double delta = computeDelta(iP[1].get_i(), iP[1].get_j());
764 pix.
init(iP[0].get_i(), iP[0].get_j(), delta);
787 std::list<vpMeSite>::const_iterator it =
m_meList.begin();
788 std::list<vpMeSite>::iterator itNext =
m_meList.begin();
834 if (enableCannyDetection)
847 if (std::fabs(u) > std::numeric_limits<double>::epsilon())
883 if (hasGoodLevel(I, iP)) {
885 computeFreemanParameters((element + 2) % 8, diP);
887 if (hasGoodLevel(I, iPtemp)) {
888 element = (element + 2) % 8;
891 computeFreemanParameters((element + 1) % 8, diP);
894 if (hasGoodLevel(I, iPtemp)) {
895 element = (element + 1) % 8;
898 computeFreemanParameters(element, diP);
901 if (hasGoodLevel(I, iPtemp)) {
905 computeFreemanParameters((element + 7) % 8, diP);
908 if (hasGoodLevel(I, iPtemp)) {
909 element = (element + 7) % 8;
912 computeFreemanParameters((element + 6) % 8, diP);
915 if (hasGoodLevel(I, iPtemp)) {
916 element = (element + 6) % 8;
919 computeFreemanParameters((element + 5) % 8, diP);
922 if (hasGoodLevel(I, iPtemp)) {
923 element = (element + 5) % 8;
926 computeFreemanParameters((element + 4) % 8, diP);
929 if (hasGoodLevel(I, iPtemp)) {
930 element = (element + 4) % 8;
933 computeFreemanParameters((element + 3) % 8, diP);
936 if (hasGoodLevel(I, iPtemp)) {
937 element = (element + 3) % 8;
972 if (!isInImage(I, iP))
1015 void vpMeNurbs::computeFreemanParameters(
unsigned int element,
vpImagePoint &diP)
1074 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.