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>
62double computeDelta(
double deltai,
double deltaj);
65bool findCenterPoint(std::list<vpImagePoint> *ip_edges_list);
69double computeDelta(
double deltai,
double deltaj)
72 delta = atan2(deltai, deltaj);
74 while (delta > M_PI) {
85static 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)));
97 int Iheight =
static_cast<int>(I.getHeight());
98 int Iwidth =
static_cast<int>(I.getWidth());
101 for (
int i = 0;
i < 180;
i++) {
106 if (outOfImage(iP,
static_cast<int>(half) + me->
getStrip(), Iheight, Iwidth)) {
113 index_mask =
static_cast<int>(
i /
static_cast<double>(me->
getAngleStep()));
117 unsigned int ihalf =
static_cast<unsigned int>(iP.
get_i() - half);
118 unsigned int jhalf =
static_cast<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) {
172bool 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)
228 nurbs.globalCurveInterp(ptList);
239 int rows =
static_cast<int>(I.getHeight());
240 int cols =
static_cast<int>(I.getWidth());
241 double step = 1.0 /
static_cast<double>(
m_me->getPointsToTrack());
252 pt =
nurbs.computeCurveDersPoint(u, 1);
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) {
298 Cu =
nurbs.computeCurvePoint(u);
307 der =
nurbs.computeCurveDersPoint(u, 1);
311 s.setAlpha(computeDelta(der[1].get_i(), der[1].get_j()));
323 int rows =
static_cast<int>(I.getHeight());
324 int cols =
static_cast<int>(I.getWidth());
329 begin =
nurbs.computeCurveDersPoint(0.0, 1);
330 end =
nurbs.computeCurveDersPoint(1.0, 1);
334 double threshold = 3 *
m_me->getSampleStep();
335 double sample_step =
m_me->getSampleStep();
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);
345 unsigned int memory_range =
m_me->getRange();
349 bool beginPtAdded =
false;
351 double angle = atan2(begin[1].get_i(), begin[1].get_j());
356 for (
int i = 0; i < 3; i++) {
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++) {
422 m_me->setRange(memory_range);
437 if (beginPtFound >= 3 && farFromImageEdge(I, firstPoint)) {
439 begin =
nurbs.computeCurveDersPoint(0.0, 1);
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) {
455 lastPtInSubIm =
nurbs.computeCurvePoint(u);
460 lastPtInSubIm =
nurbs.computeCurvePoint(u);
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);
546 unsigned int memory_range =
m_me->getRange();
548 std::list<vpMeSite>::iterator itList2 =
m_meList.begin();
549 for (
unsigned int j = 0; j < nbr; j++) {
551 s.track(I,
m_me,
false);
555 m_me->setRange(memory_range);
562 if (endPtFound >= 3 && farFromImageEdge(I, lastPoint)) {
564 end =
nurbs.computeCurveDersPoint(1.0, 1);
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) {
581 lastPtInSubIm =
nurbs.computeCurvePoint(u);
586 lastPtInSubIm =
nurbs.computeCurvePoint(u);
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);
674 unsigned int memory_range =
m_me->getRange();
676 std::list<vpMeSite>::iterator itList2 =
m_meList.end();
678 for (
unsigned int j = 0; j < nbr; j++) {
684 m_me->setRange(memory_range);
695 double nbPt = floor(dist /
m_me->getSampleStep());
697 if (
static_cast<double>(n) < 0.7 * nbPt) {
705 int rows =
static_cast<int>(I.getHeight());
706 int cols =
static_cast<int>(I.getWidth());
711 std::list<vpMeSite>::iterator it =
m_meList.begin();
712 std::list<vpMeSite>::iterator itNext =
m_meList.begin();
715 unsigned int range_tmp =
m_me->getRange();
718 while (itNext !=
m_meList.end() && n <= m_me->getPointsToTrack()) {
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())) {
753 iP =
nurbs.computeCurveDersPoint(u, 1);
761 iP =
nurbs.computeCurveDersPoint(u, 1);
764 double delta = computeDelta(iP[1].get_i(), iP[1].get_j());
766 pix.
init(iP[0].get_i(), iP[0].get_j(), delta);
784 m_me->setRange(range_tmp);
789 std::list<vpMeSite>::const_iterator it =
m_meList.begin();
790 std::list<vpMeSite>::iterator itNext =
m_meList.begin();
836 if (enableCannyDetection)
847 pt =
nurbs.computeCurvePoint(u);
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))
1017void 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)
Definition of the vpImage class member functions.
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.
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)
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
unsigned int getAngleStep() const
vpMatrix * getMask() const
unsigned int getMaskSize() const
Class that provides tools to compute and manipulate a Non Uniform Rational B-Spline curve.
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)
Defines a rectangle in the plane.
Error that can be emitted by the vpTracker class and its derivatives.
@ notEnoughPointError
Not enough point to track.
#define vpDEBUG_ENABLE(level)