44 #include <visp3/core/vpImageConvert.h>
45 #include <visp3/core/vpImageFilter.h>
46 #include <visp3/core/vpImagePoint.h>
47 #include <visp3/core/vpImageTools.h>
48 #include <visp3/core/vpMath.h>
49 #include <visp3/core/vpRect.h>
50 #include <visp3/core/vpRobust.h>
51 #include <visp3/core/vpTrackingException.h>
52 #include <visp3/me/vpMe.h>
53 #include <visp3/me/vpMeNurbs.h>
54 #include <visp3/me/vpMeSite.h>
55 #include <visp3/me/vpMeTracker.h>
56 #ifdef VISP_HAVE_OPENCV
57 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
59 #include <opencv2/imgproc/imgproc_c.h>
65 double computeDelta(
double deltai,
double deltaj);
68 bool findCenterPoint(std::list<vpImagePoint> *ip_edges_list);
69 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
75 double computeDelta(
double deltai,
double deltaj)
78 delta = atan2(deltai, deltaj);
80 while (delta > M_PI) {
91 static bool outOfImage(
const vpImagePoint &iP,
int half,
int rows,
int cols)
93 return ((iP.
get_i() < half + 1) || (iP.
get_i() > (rows - half - 3)) || (iP.
get_j() < half + 1) ||
94 (iP.
get_j() > (cols - half - 3)));
107 for (
int i = 0; i < 180; i++) {
112 if (outOfImage(iP, (
int)half + me->
getStrip(), Iheight, Iwidth)) {
122 unsigned int ihalf = (
unsigned int)(iP.
get_i() - half);
123 unsigned int jhalf = (
unsigned int)(iP.
get_j() - half);
127 unsigned int ihalfa = ihalf + a;
129 conv += me->
getMask()[index_mask][a][b] * I(ihalfa, jhalf + b);
138 while (angle > M_PI) {
159 for (
unsigned int i = 0; i <= Isub.
getHeight(); i++) {
160 for (
unsigned int j = 0; j <= Isub.
getWidth(); j++) {
162 if (Isub(i, j) > 0) {
164 if (dist <= 16 && dist < dist_1) {
175 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
180 ip_edges_list->
front();
181 while (!ip_edges_list->
outside()) {
187 ip_edges_list->
next();
195 bool findCenterPoint(std::list<vpImagePoint> *ip_edges_list)
197 for (std::list<vpImagePoint>::const_iterator it = ip_edges_list->begin(); it != ip_edges_list->end(); ++it) {
213 : nurbs(), dist(0.), nbControlPoints(20), beginPtFound(0), endPtFound(0), enableCannyDetection(false), cannyTh1(100.),
222 :
vpMeTracker(menurbs), nurbs(menurbs.nurbs), dist(0.), nbControlPoints(20), beginPtFound(0), endPtFound(0),
223 enableCannyDetection(false), cannyTh1(100.), cannyTh2(200.)
226 nbControlPoints = menurbs.nbControlPoints;
227 beginPtFound = menurbs.beginPtFound;
228 endPtFound = menurbs.endPtFound;
229 enableCannyDetection = menurbs.enableCannyDetection;
230 cannyTh1 = menurbs.cannyTh1;
231 cannyTh2 = menurbs.cannyTh2;
247 std::list<vpImagePoint> ptList;
254 ptList.push_back(pt);
261 if (ptList.size() > 3)
308 double delta = computeDelta(pt[1].get_i(), pt[1].get_j());
314 pix.
init(pt[0].get_i(), pt[0].get_j(), delta);
334 for (std::list<vpMeSite>::iterator it =
list.begin(); it !=
list.end();) {
353 std::list<vpMeSite>::iterator it =
list.begin();
358 while (u < 1 && it !=
list.end()) {
361 while (d <= d_1 && u < 1) {
375 s.
alpha = computeDelta(der[1].get_i(), der[1].get_j());
408 if (d > threshold ) {
412 P.
init(begin[0].get_i(), begin[0].get_j(), (
list.front()).alpha, 0, (
list.front()).mask_sign);
420 bool beginPtAdded =
false;
422 double angle = atan2(begin[1].get_i(), begin[1].get_j());
427 for (
int i = 0; i < 3; i++) {
456 P.
init(end[0].get_i(), end[0].get_j(), (
list.back()).alpha, 0, (
list.back()).mask_sign);
459 bool endPtAdded =
false;
460 angle = atan2(end[1].get_i(), end[1].get_j());
465 for (
int i = 0; i < 3; i++) {
510 #if (defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION < 0x030000))
516 #if (defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION < 0x030000))
521 if (beginPtFound >= 3 && farFromImageEdge(I, firstPoint)) {
523 begin = nurbs.computeCurveDersPoint(0.0, 1);
525 vpImagePoint topLeft(begin[0].get_i() - 15, begin[0].get_j() - 15);
526 vpRect rect(topLeft, 32, 32);
534 double step = 0.0001;
537 while (inRectangle(lastPtInSubIm, rect) && u < 1) {
539 lastPtInSubIm = nurbs.computeCurvePoint(u);
544 lastPtInSubIm = nurbs.computeCurvePoint(u);
546 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
552 IplImage *dst = cvCreateImage(cvSize((
int)Isub.
getWidth(), (
int)Isub.
getHeight()), 8, 1);
553 cvCanny(Ip, dst, cannyTh1, cannyTh2, 3);
560 firstBorder = findFirstBorder(Isub, lastPtInSubIm - topLeft);
562 std::list<vpImagePoint> ip_edges_list;
565 double fi = firstBorder.
get_i();
566 double fj = firstBorder.
get_j();
570 if (std::fabs(fi) <= std::numeric_limits<double>::epsilon())
573 else if (std::fabs(fi - h) <= std::fabs(
vpMath::maximum(fi, h)) * std::numeric_limits<double>::epsilon())
576 else if (std::fabs(fj) <= std::numeric_limits<double>::epsilon())
579 else if (std::fabs(fj - w) <= std::fabs(
vpMath::maximum(fj, w)) * std::numeric_limits<double>::epsilon())
581 computeFreemanChainElement(Isub, firstBorder, dir);
582 unsigned int firstDir = dir;
583 ip_edges_list.push_back(firstBorder);
587 computeFreemanParameters(dir, dBorder);
588 border = border + dBorder;
591 ip_edges_list.push_back(border);
593 computeFreemanChainElement(Isub, border, dir);
594 }
while ((border != firstBorder || dir != firstDir) && isInImage(Isub, border));
597 if (findCenterPoint(&ip_edges_list)) {
598 for (std::list<vpMeSite>::iterator it = list.begin(); it != list.end();
602 if (inRectangle(iP, rect))
608 std::list<vpMeSite>::iterator itList = list.begin();
612 std::list<vpMeSite> addedPt;
613 for (std::list<vpImagePoint>::const_iterator itEdges = ip_edges_list.begin(); itEdges != ip_edges_list.end();
622 for (std::list<vpMeSite>::const_iterator itAdd = addedPt.begin(); itAdd != addedPt.end(); ++itAdd) {
628 findAngle(I, iPtemp, me, delta, convlt);
632 list.insert(itList, pix);
634 addedPt.push_front(pix);
640 unsigned int memory_range = me->
getRange();
642 std::list<vpMeSite>::iterator itList2 = list.begin();
643 for (
int j = 0; j < nbr; j++) {
645 s.
track(I, me,
false);
656 if (endPtFound >= 3 && farFromImageEdge(I, lastPoint)) {
658 end = nurbs.computeCurveDersPoint(1.0, 1);
661 vpImagePoint topLeft(end[0].get_i() - 15, end[0].get_j() - 15);
662 vpRect rect(topLeft, 32, 32);
670 double step = 0.0001;
673 while (inRectangle(lastPtInSubIm, rect) && u > 0) {
675 lastPtInSubIm = nurbs.computeCurvePoint(u);
680 lastPtInSubIm = nurbs.computeCurvePoint(u);
682 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
688 IplImage *dst = cvCreateImage(cvSize((
int)Isub.
getWidth(), (
int)Isub.
getHeight()), 8, 1);
689 cvCanny(Ip, dst, cannyTh1, cannyTh2, 3);
696 firstBorder = findFirstBorder(Isub, lastPtInSubIm - topLeft);
698 std::list<vpImagePoint> ip_edges_list;
701 double fi = firstBorder.
get_i();
702 double fj = firstBorder.
get_j();
706 if (std::fabs(fi) <= std::numeric_limits<double>::epsilon())
709 else if (std::fabs(fi - h) <= std::fabs(
vpMath::maximum(fi, h)) * std::numeric_limits<double>::epsilon())
712 else if (std::fabs(fj) <= std::numeric_limits<double>::epsilon())
715 else if (std::fabs(fj - w) <= std::fabs(
vpMath::maximum(fj, w)) * std::numeric_limits<double>::epsilon())
718 computeFreemanChainElement(Isub, firstBorder, dir);
719 unsigned int firstDir = dir;
720 ip_edges_list.push_back(firstBorder);
724 computeFreemanParameters(dir, dBorder);
725 border = border + dBorder;
728 ip_edges_list.push_back(border);
730 computeFreemanChainElement(Isub, border, dir);
731 }
while ((border != firstBorder || dir != firstDir) && isInImage(Isub, border));
734 if (findCenterPoint(&ip_edges_list)) {
741 if (inRectangle(iP, rect)) {
742 list.erase(list.end());
748 std::list<vpMeSite>::iterator itList = list.end();
753 std::list<vpMeSite> addedPt;
754 for (std::list<vpImagePoint>::const_iterator itEdges = ip_edges_list.begin(); itEdges != ip_edges_list.end();
763 for (std::list<vpMeSite>::const_iterator itAdd = addedPt.begin(); itAdd != addedPt.end(); ++itAdd) {
769 findAngle(I, iPtemp, me, delta, convlt);
773 addedPt.push_back(pix);
779 unsigned int memory_range = me->
getRange();
781 std::list<vpMeSite>::iterator itList2 = list.end();
783 for (
int j = 0; j < nbr; j++) {
785 me_s.
track(I, me,
false);
796 vpTRACE(
"To use the canny detection, OpenCV has to be installed.");
815 if ((
double)n < 0.7 * nbPt) {
837 std::list<vpMeSite>::iterator it =
list.begin();
838 std::list<vpMeSite>::iterator itNext =
list.begin();
857 double dmin1_1 = 1e6;
858 double dmin2_1 = 1e6;
864 if (dmin1 < dmin1_1) {
869 if (dmin2 < dmin2_1) {
877 if ((std::fabs(u - 1.0) > std::fabs(
vpMath::maximum(u, 1.0)) * std::numeric_limits<double>::epsilon()) ||
878 (std::fabs(uend - 1.0) > std::fabs(
vpMath::maximum(uend, 1.0)) * std::numeric_limits<double>::epsilon())) {
890 double delta = computeDelta(iP[1].get_i(), iP[1].get_j());
892 pix.
init(iP[0].get_i(), iP[0].get_j(), delta);
896 list.insert(it, pix);
923 while(!
list.nextOutside())
934 if (!
list.nextOutside())
list.next();
940 std::list<vpMeSite>::const_iterator it =
list.begin();
941 std::list<vpMeSite>::iterator itNext =
list.begin();
943 for (; itNext !=
list.end();) {
953 if (itNext !=
list.end()) {
980 if (
list.size() == 1)
991 if (enableCannyDetection)
1004 if (std::fabs(u) > std::numeric_limits<double>::epsilon())
1051 if (hasGoodLevel(I, iP)) {
1053 computeFreemanParameters((element + 2) % 8, diP);
1055 if (hasGoodLevel(I, iPtemp)) {
1056 element = (element + 2) % 8;
1058 computeFreemanParameters((element + 1) % 8, diP);
1061 if (hasGoodLevel(I, iPtemp)) {
1062 element = (element + 1) % 8;
1064 computeFreemanParameters(element, diP);
1067 if (hasGoodLevel(I, iPtemp)) {
1070 computeFreemanParameters((element + 7) % 8, diP);
1073 if (hasGoodLevel(I, iPtemp)) {
1074 element = (element + 7) % 8;
1076 computeFreemanParameters((element + 6) % 8, diP);
1079 if (hasGoodLevel(I, iPtemp)) {
1080 element = (element + 6) % 8;
1082 computeFreemanParameters((element + 5) % 8, diP);
1085 if (hasGoodLevel(I, iPtemp)) {
1086 element = (element + 5) % 8;
1088 computeFreemanParameters((element + 4) % 8, diP);
1091 if (hasGoodLevel(I, iPtemp)) {
1092 element = (element + 4) % 8;
1094 computeFreemanParameters((element + 3) % 8, diP);
1097 if (hasGoodLevel(I, iPtemp)) {
1098 element = (element + 3) % 8;
1131 if (!isInImage(I, iP))
1173 void vpMeNurbs::computeFreemanParameters(
unsigned int element,
vpImagePoint &diP)
1232 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 functionnalities.
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 emited by ViSP classes.
@ notInitialized
Used to indicate that a parameter is not initialized.
@ divideByZeroError
Division by zero.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void canny(const vpImage< unsigned char > &I, vpImage< unsigned char > &Ic, unsigned int gaussianFilterSize, double thresholdCanny, 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
Provide simple list management.
void next(void)
position the current element on the next one
void front(void)
Position the current element on the first element of the list.
bool outside(void) const
Test if the current element is outside the list (on the virtual element)
type & value(void)
return the value of the current element
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 removed because too near image borders.
@ NO_SUPPRESSION
Point used by the tracker.
void setDisplay(vpMeSiteDisplayType select)
vpMeSiteState getState() const
static double sqrDistance(const vpMeSite &S1, const vpMeSite &S2)
void track(const vpImage< unsigned char > &im, const vpMe *me, 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 selectDisplay
int outOfImage(int i, int j, int half, int row, int cols)
void track(const vpImage< unsigned char > &I)
Track sampled pixels.
std::list< vpMeSite > list
vpMe * me
Moving edges initialisation parameters.
void setRange(const unsigned int &r)
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 emited by the vpTracker class and its derivates.
#define vpDEBUG_ENABLE(level)