44 #include <visp3/core/vpDisplay.h>
47 #include <visp3/core/vpIoTools.h>
48 #include <visp3/core/vpMath.h>
49 #include <visp3/core/vpTrackingException.h>
55 #include <visp3/blob/vpDot2.h>
78 grayLevelPrecision = 0.80;
82 ellipsoidShapePrecision = 0.65;
83 maxSizeSearchDistancePrecision = 0.65;
103 compute_moment =
false;
112 : m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(), width(0), height(0),
113 surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0), grayLevelPrecision(0.8), gamma(1.5),
114 sizePrecision(0.65), ellipsoidShapePrecision(0.65), maxSizeSearchDistancePrecision(0.65),
115 allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(), compute_moment(false), graphics(false),
116 thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0), firstBorder_u(0), firstBorder_v()
128 : m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(ip), width(0), height(0),
129 surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0), grayLevelPrecision(0.8), gamma(1.5),
130 sizePrecision(0.65), ellipsoidShapePrecision(0.65), maxSizeSearchDistancePrecision(0.65),
131 allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(), compute_moment(false), graphics(false),
132 thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0), firstBorder_u(0), firstBorder_v()
139 :
vpTracker(twinDot), m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(),
140 width(0), height(0), surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0),
141 grayLevelPrecision(0.8), gamma(1.5), sizePrecision(0.65), ellipsoidShapePrecision(0.65),
142 maxSizeSearchDistancePrecision(0.65), allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(),
143 compute_moment(false), graphics(false), thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0),
144 firstBorder_u(0), firstBorder_v()
156 width = twinDot.width;
157 height = twinDot.height;
158 surface = twinDot.surface;
159 gray_level_min = twinDot.gray_level_min;
160 gray_level_max = twinDot.gray_level_max;
161 mean_gray_level = twinDot.mean_gray_level;
162 grayLevelPrecision = twinDot.grayLevelPrecision;
163 gamma = twinDot.gamma;
165 sizePrecision = twinDot.sizePrecision;
166 ellipsoidShapePrecision = twinDot.ellipsoidShapePrecision;
167 maxSizeSearchDistancePrecision = twinDot.maxSizeSearchDistancePrecision;
168 allowedBadPointsPercentage_ = twinDot.allowedBadPointsPercentage_;
171 direction_list = twinDot.direction_list;
172 ip_edges_list = twinDot.ip_edges_list;
174 compute_moment = twinDot.compute_moment;
175 graphics = twinDot.graphics;
176 thickness = twinDot.thickness;
178 bbox_u_min = twinDot.bbox_u_min;
179 bbox_u_max = twinDot.bbox_u_max;
180 bbox_v_min = twinDot.bbox_v_min;
181 bbox_v_max = twinDot.bbox_v_max;
183 firstBorder_u = twinDot.firstBorder_u;
184 firstBorder_v = twinDot.firstBorder_v;
215 std::list<vpImagePoint>::const_iterator it;
217 for (it = ip_edges_list.begin(); it != ip_edges_list.end(); ++it) {
258 unsigned int i =
static_cast<unsigned int>(cog.
get_i());
259 unsigned int j =
static_cast<unsigned int>(cog.
get_j());
261 double Ip = pow(
static_cast<double>(I[i][j]) / 255, 1 / gamma);
263 if ((Ip - (1 - grayLevelPrecision)) < 0) {
267 gray_level_min =
static_cast<unsigned int>(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
268 if (gray_level_min > 255) {
269 gray_level_min = 255;
272 gray_level_max =
static_cast<unsigned int>(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
273 if (gray_level_max > 255) {
274 gray_level_max = 255;
314 unsigned int i =
static_cast<unsigned int>(cog.
get_i());
315 unsigned int j =
static_cast<unsigned int>(cog.
get_j());
317 double Ip = pow(
static_cast<double>(I[i][j]) / 255, 1 / gamma);
319 if ((Ip - (1 - grayLevelPrecision)) < 0) {
323 gray_level_min =
static_cast<unsigned int>(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
324 if (gray_level_min > 255) {
325 gray_level_min = 255;
328 gray_level_max =
static_cast<unsigned int>(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
329 if (gray_level_max > 255) {
330 gray_level_max = 255;
379 unsigned int gray_lvl_max,
unsigned int size)
383 this->gray_level_min = gray_lvl_min;
384 this->gray_level_max = gray_lvl_max;
454 bool found = computeParameters(I, cog.
get_u(), cog.
get_v());
458 found = isValid(I, wantedDot);
477 double searchWindowWidth = 0.0;
478 double searchWindowHeight = 0.0;
480 if ((std::fabs(
getWidth()) <= std::numeric_limits<double>::epsilon()) ||
481 (std::fabs(
getHeight()) <= std::numeric_limits<double>::epsilon())) {
482 searchWindowWidth = 80.;
483 searchWindowHeight = 80.;
485 else if (canMakeTheWindowGrow) {
494 std::list<vpDot2> candidates;
496 static_cast<int>(this->cog.get_v() - (searchWindowHeight / 2.0)),
497 static_cast<unsigned int>(searchWindowWidth),
498 static_cast<unsigned int>(searchWindowHeight), candidates);
502 if (candidates.empty()) {
508 vpDot2 movingDot = candidates.front();
524 bbox_u_min = movingDot.bbox_u_min;
525 bbox_u_max = movingDot.bbox_u_max;
526 bbox_v_min = movingDot.bbox_v_min;
527 bbox_v_max = movingDot.bbox_v_max;
534 "The center of gravity of the dot is not in the image"));
546 if ((Ip - (1 - grayLevelPrecision)) < 0) {
550 gray_level_min =
static_cast<unsigned int>(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
551 if (gray_level_min > 255) {
552 gray_level_min = 255;
555 gray_level_max =
static_cast<unsigned int>(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
556 if (gray_level_max > 255) {
557 gray_level_max = 255;
590 track(I, canMakeTheWindowGrow);
656 double diff_u = this->cog.
get_u() - cogDistantDot.
get_u();
657 double diff_v = this->cog.
get_v() - cogDistantDot.
get_v();
658 return sqrt((diff_u * diff_u) + (diff_v * diff_v));
717 double epsilon = 0.05;
718 if (grayLevelPrecision < epsilon) {
719 this->grayLevelPrecision = epsilon;
721 else if (grayLevelPrecision > 1) {
722 this->grayLevelPrecision = 1.0;
725 this->grayLevelPrecision = precision;
747 if (sizePrecision < 0) {
748 this->sizePrecision = 0;
750 else if (sizePrecision > 1) {
751 this->sizePrecision = 1.0;
754 this->sizePrecision = precision;
793 if (ellipsoidShapePrecision < 0) {
794 this->ellipsoidShapePrecision = 0;
796 else if (ellipsoidShapePrecision > 1) {
797 this->ellipsoidShapePrecision = 1.0;
800 this->ellipsoidShapePrecision = precision;
821 double epsilon = 0.05;
822 if (maxSizeSearchDistancePrecision < epsilon) {
823 this->maxSizeSearchDistancePrecision = epsilon;
825 else if (maxSizeSearchDistancePrecision > 1) {
826 this->maxSizeSearchDistancePrecision = 1.0;
829 this->maxSizeSearchDistancePrecision = precision;
857 unsigned int image_w = I.
getWidth();
864 else if (u >=
static_cast<int>(image_w)) {
865 u =
static_cast<int>(image_w) - 1;
870 else if (v >=
static_cast<int>(image_h)) {
871 v =
static_cast<int>(image_h) - 1;
874 if ((
static_cast<unsigned int>(u) + w) > image_w) {
875 w = image_w -
static_cast<unsigned int>(u) - 1;
877 if ((
static_cast<unsigned int>(v) + h) > image_h) {
878 h = image_h -
static_cast<unsigned int>(v) - 1;
974 unsigned int area_h, std::list<vpDot2> &niceDots)
982 setArea(I, area_u, area_v, area_w, area_h);
985 unsigned int gridWidth;
986 unsigned int gridHeight;
987 getGridSize(gridWidth, gridHeight);
1001 std::list<vpDot2> badDotsVector;
1002 std::list<vpDot2>::iterator itnice;
1003 std::list<vpDot2>::iterator itbad;
1005 vpDot2 *dotToTest =
nullptr;
1008 unsigned int area_u_min =
static_cast<unsigned int>(area.
getLeft());
1009 unsigned int area_u_max =
static_cast<unsigned int>(area.
getRight());
1010 unsigned int area_v_min =
static_cast<unsigned int>(area.
getTop());
1011 unsigned int area_v_max =
static_cast<unsigned int>(area.
getBottom());
1016 for (v = area_v_min; v < area_v_max; v = v + gridHeight) {
1017 for (u = area_u_min; u < area_u_max; u = u + gridWidth) {
1021 if (!hasGoodLevel(I, u, v)) {
1027 bool good_germ =
true;
1029 itnice = niceDots.begin();
1030 while ((itnice != niceDots.end()) && (good_germ ==
true)) {
1033 cogTmpDot = tmpDot.
getCog();
1034 double u0 = cogTmpDot.
get_u();
1035 double v0 = cogTmpDot.
get_v();
1036 double half_w = tmpDot.
getWidth() / 2.;
1037 double half_h = tmpDot.
getHeight() / 2.;
1039 if ((u >= (u0 - half_w)) && (u <= (u0 + half_w)) && (v >= (v0 - half_h)) && (v <= (v0 + half_h))) {
1051 unsigned int border_u;
1052 unsigned int border_v;
1053 if (findFirstBorder(I, u, v, border_u, border_v) ==
false) {
1062 itbad = badDotsVector.begin();
1063 #define vpBAD_DOT_VALUE (*itbad)
1066 while ((itbad != badDotsVector.end()) && (good_germ ==
true)) {
1067 if ((
static_cast<double>(u) >= vpBAD_DOT_VALUE.bbox_u_min) && (
static_cast<double>(u) <= vpBAD_DOT_VALUE.bbox_u_max) &&
1068 (
static_cast<double>(v) >= vpBAD_DOT_VALUE.bbox_v_min) && (
static_cast<double>(v) <= vpBAD_DOT_VALUE.bbox_v_max)) {
1069 std::list<vpImagePoint>::const_iterator it_edges = ip_edges_list.begin();
1070 while ((it_edges != ip_edges_list.end()) && (good_germ ==
true)) {
1074 cogBadDot = *it_edges;
1075 if ((std::fabs(border_u - cogBadDot.
get_u()) <=
1077 std::numeric_limits<double>::epsilon()) &&
1078 (std::fabs(v - cogBadDot.
get_v()) <=
1080 std::numeric_limits<double>::epsilon())) {
1088 #undef vpBAD_DOT_VALUE
1098 vpTRACE(4,
"Try germ (%d, %d)", u, v);
1106 if (dotToTest !=
nullptr) {
1109 dotToTest = getInstance();
1125 if (dotToTest->computeParameters(I) ==
false) {
1133 if (dotToTest->isValid(I, *
this)) {
1140 double area_center_u = (area_u + (area_w / 2.0)) - 0.5;
1141 double area_center_v = (area_v + (area_h / 2.0)) - 0.5;
1143 double thisDiff_u = cogDotToTest.
get_u() - area_center_u;
1144 double thisDiff_v = cogDotToTest.
get_v() - area_center_v;
1145 double thisDist = sqrt((thisDiff_u * thisDiff_u) + (thisDiff_v * thisDiff_v));
1147 bool stopLoop =
false;
1148 itnice = niceDots.begin();
1150 while ((itnice != niceDots.end()) && (stopLoop ==
false)) {
1154 double epsilon = 3.0;
1157 cogTmpDot = tmpDot.
getCog();
1159 if ((fabs(cogTmpDot.
get_u() - cogDotToTest.
get_u()) < epsilon) &&
1160 (fabs(cogTmpDot.
get_v() - cogDotToTest.
get_v()) < epsilon)) {
1169 double otherDiff_u = cogTmpDot.
get_u() - area_center_u;
1170 double otherDiff_v = cogTmpDot.
get_v() - area_center_v;
1171 double otherDist = sqrt((otherDiff_u * otherDiff_u) + (otherDiff_v * otherDiff_v));
1176 if (otherDist > thisDist) {
1177 niceDots.insert(itnice, *dotToTest);
1188 vpTRACE(4,
"End while (%d, %d)", u, v);
1192 if ((itnice == niceDots.end()) && (stopLoop ==
false)) {
1193 niceDots.push_back(*dotToTest);
1198 badDotsVector.push_front(*dotToTest);
1202 if (dotToTest !=
nullptr) {
1239 if ((std::fabs(wantedDot.
getWidth()) > std::numeric_limits<double>::epsilon()) &&
1240 (std::fabs(wantedDot.
getHeight()) > std::numeric_limits<double>::epsilon()) &&
1241 (std::fabs(wantedDot.
getArea()) > std::numeric_limits<double>::epsilon())) {
1242 if (std::fabs(size_precision) > std::numeric_limits<double>::epsilon()) {
1243 double epsilon = 0.001;
1245 std::cout <<
"test size precision......................\n";
1246 std::cout <<
"wanted dot: "
1248 <<
" precision=" << size_precision <<
" epsilon=" << epsilon << std::endl;
1249 std::cout <<
"dot found: "
1253 if ((((wantedDot.
getWidth() * size_precision) - epsilon) <
getWidth()) ==
false) {
1256 printf(
"Bad width > for dot (%g, %g)\n", cog.
get_u(), cog.
get_v());
1261 if ((
getWidth() < (wantedDot.
getWidth() / (size_precision + epsilon))) ==
false) {
1264 printf(
"Bad width %g > %g for dot (%g, %g)\n",
getWidth(), wantedDot.
getWidth() / (size_precision + epsilon),
1273 printf(
"Bad height %g > %g for dot (%g, %g)\n", wantedDot.
getHeight() * size_precision - epsilon,
getHeight(),
1282 printf(
"Bad height %g > %g for dot (%g, %g)\n",
getHeight(), wantedDot.
getHeight() / (size_precision + epsilon),
1288 if ((((wantedDot.
getArea() * (size_precision * size_precision)) - epsilon) <
getArea()) ==
false) {
1291 printf(
"Bad surface %g > %g for dot (%g, %g)\n",
1297 if ((
getArea() < (wantedDot.
getArea() / ((size_precision * size_precision) + epsilon))) ==
false) {
1300 printf(
"Bad surface %g < %g for dot (%g, %g)\n",
getArea(),
1301 wantedDot.
getArea() / (size_precision * size_precision + epsilon), cog.
get_u(), cog.
get_v());
1312 int nb_point_to_test = 20;
1313 int nb_bad_points = 0;
1314 int nb_max_bad_points =
static_cast<int>(nb_point_to_test * allowedBadPointsPercentage_);
1315 double step_angle = (2 * M_PI) / nb_point_to_test;
1318 if ((std::fabs(ellipsoidShape_precision) > std::numeric_limits<double>::epsilon()) && compute_moment) {
1335 double Sqrt = sqrt((tmp1 * tmp1) + (4 * tmp2 * tmp2));
1345 double innerCoef = ellipsoidShape_precision;
1347 double cog_u = this->cog.
get_u();
1348 double cog_v = this->cog.
get_v();
1352 for (
double theta = 0.; theta < (2 * M_PI); theta += step_angle) {
1353 u =
static_cast<unsigned int>(cog_u + (innerCoef * ((a1 * cos(alpha) * cos(theta)) - (a2 * sin(alpha) * sin(theta)))));
1354 v =
static_cast<unsigned int>(cog_v + (innerCoef * ((a1 * sin(alpha) * cos(theta)) + (a2 * cos(alpha) * sin(theta)))));
1355 if (!this->hasGoodLevel(I, u, v)) {
1357 printf(
"Inner circle pixel (%u, %u) has bad level for dot (%g, %g): "
1358 "%d not in [%u, %u]\n",
1359 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1364 for (
unsigned int t = 0; t < thickness; ++t) {
1375 if (nb_bad_points > nb_max_bad_points) {
1377 printf(
"Inner ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1386 double outCoef = 2 - ellipsoidShape_precision;
1388 for (
double theta = 0.; theta < (2 * M_PI); theta += step_angle) {
1389 u =
static_cast<unsigned int>(cog_u + (outCoef * ((a1 * cos(alpha) * cos(theta)) - (a2 * sin(alpha) * sin(theta)))));
1390 v =
static_cast<unsigned int>(cog_v + (outCoef * ((a1 * sin(alpha) * cos(theta)) + (a2 * cos(alpha) * sin(theta)))));
1397 if ((
static_cast<double>(u) < area.
getLeft()) ||
1398 (
static_cast<double>(u) > area.
getRight()) ||
1399 (
static_cast<double>(v) < area.
getTop()) ||
1400 (
static_cast<double>(v) > area.
getBottom())) {
1403 if (!this->hasReverseLevel(I, u, v)) {
1405 printf(
"Outside circle pixel (%u, %u) has bad level for dot (%g, "
1406 "%g): %d not in [%u, %u]\n",
1407 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1412 for (
unsigned int t = 0; t < thickness; ++t) {
1421 if (nb_bad_points > nb_max_bad_points) {
1423 printf(
"Outside ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1449 bool vpDot2::hasGoodLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1451 if (!isInArea(u, v)) {
1455 if ((I[v][u] >= gray_level_min) && (I[v][u] <= gray_level_max)) {
1475 bool vpDot2::hasReverseLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1478 if (!isInArea(u, v)) {
1482 if ((I[v][u] < gray_level_min) || (I[v][u] > gray_level_max)) {
1556 direction_list.clear();
1557 ip_edges_list.clear();
1564 if (std::fabs(est_u + 1.0) <= (
vpMath::maximum(std::fabs(est_u), 1.) * std::numeric_limits<double>::epsilon())) {
1565 est_u = this->cog.
get_u();
1570 if (std::fabs(est_v + 1.0) <= (
vpMath::maximum(std::fabs(est_v), 1.) * std::numeric_limits<double>::epsilon())) {
1571 est_v = this->cog.
get_v();
1576 if (!isInArea(
static_cast<unsigned int>(est_u),
static_cast<unsigned int>(est_v))) {
1578 "Initial pixel coordinates (%d, %d) for dot tracking are "
1580 static_cast<int>(est_u),
static_cast<int>(est_v));
1584 bbox_u_min =
static_cast<int>(I.
getWidth());
1586 bbox_v_min =
static_cast<int>(I.
getHeight());
1591 if (!hasGoodLevel(I,
static_cast<unsigned int>(est_u),
static_cast<unsigned int>(est_v))) {
1592 vpDEBUG_TRACE(3,
"Can't find a dot from pixel (%d, %d) coordinates",
static_cast<unsigned int>(est_u),
static_cast<unsigned int>(est_v));
1598 if (!findFirstBorder(I,
static_cast<unsigned int>(est_u),
static_cast<unsigned int>(est_v), this->firstBorder_u, this->firstBorder_v)) {
1600 vpDEBUG_TRACE(3,
"Can't find first border (%d, %d) coordinates",
static_cast<int>(est_u),
static_cast<int>(est_v));
1604 unsigned int dir = 6;
1607 computeFreemanChainElement(I, this->firstBorder_u, this->firstBorder_v, dir);
1608 unsigned int firstDir = dir;
1611 if (!isInArea(this->firstBorder_u, this->firstBorder_v)) {
1612 vpDEBUG_TRACE(3,
"Border pixel coordinates (%d, %d) of the dot are not in the area", this->firstBorder_u,
1613 this->firstBorder_v);
1618 direction_list.push_back(dir);
1620 ip.
set_u(this->firstBorder_u);
1621 ip.
set_v(this->firstBorder_v);
1623 ip_edges_list.push_back(ip);
1625 int border_u =
static_cast<int>(this->firstBorder_u);
1626 int border_v =
static_cast<int>(this->firstBorder_v);
1628 float dS, dMu, dMv, dMuv, dMu2, dMv2;
1639 for (
int t = 0; t < static_cast<int>(thickness); ++t) {
1640 ip.
set_u(border_u + t);
1651 computeFreemanParameters(border_u, border_v, dir, du, dv,
1662 if (compute_moment) {
1668 if (!isInArea(
static_cast<unsigned int>(border_u),
static_cast<unsigned int>(border_v))) {
1670 vpDEBUG_TRACE(3,
"Dot (%d, %d) is not in the area", border_u, border_v);
1677 direction_list.push_back(dir);
1681 ip_edges_list.push_back(ip);
1684 if (border_v < bbox_v_min) {
1685 bbox_v_min = border_v;
1687 if (border_v > bbox_v_max) {
1688 bbox_v_max = border_v;
1690 if (border_u < bbox_u_min) {
1691 bbox_u_min = border_u;
1693 if (border_u > bbox_u_max) {
1694 bbox_u_max = border_u;
1698 if (computeFreemanChainElement(I,
static_cast<unsigned int>(border_u),
static_cast<unsigned int>(border_v), dir) ==
false) {
1699 vpDEBUG_TRACE(3,
"Can't compute Freeman chain for dot (%d, %d)", border_u, border_v);
1706 }
while (((getFirstBorder_u() !=
static_cast<unsigned int>(border_u)) || (getFirstBorder_v() !=
static_cast<unsigned int>(border_v)) ||
1707 (firstDir != dir)) &&
1708 isInArea(
static_cast<unsigned int>(border_u),
static_cast<unsigned int>(border_v)));
1711 #if VP_DEBUG_MODE == 3
1719 if ((std::fabs(
m00) <= std::numeric_limits<double>::epsilon()) ||
1720 (std::fabs(
m00 - 1.) <= (
vpMath::maximum(std::fabs(
m00), 1.) * std::numeric_limits<double>::epsilon()))) {
1721 vpDEBUG_TRACE(3,
"The center of gravity of the dot wasn't properly detected");
1727 double tmpCenter_u =
m10 /
m00;
1728 double tmpCenter_v =
m01 /
m00;
1731 if (compute_moment) {
1737 cog.
set_u(tmpCenter_u);
1738 cog.
set_v(tmpCenter_v);
1741 width = (bbox_u_max - bbox_u_min) + 1;
1742 height = (bbox_v_max - bbox_v_min) + 1;
1745 computeMeanGrayLevel(I);
1764 bool vpDot2::findFirstBorder(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1765 unsigned int &border_u,
unsigned int &border_v)
1775 double epsilon = 0.001;
1778 std::cout <<
"gray level: " << gray_level_min <<
" " << gray_level_max << std::endl;
1780 while (hasGoodLevel(I, border_u + 1, border_v) && (border_u < area.
getRight()) ) {
1786 "The found dot (%d, %d, %d) has a greater width than the "
1819 bool vpDot2::computeFreemanChainElement(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1820 unsigned int &element)
1823 if (hasGoodLevel(I, u, v)) {
1824 unsigned int v_u = u;
1825 unsigned int v_v = v;
1827 updateFreemanPosition(v_u, v_v, (element + 2) % 8);
1828 if (hasGoodLevel(I, v_u, v_v)) {
1829 element = (element + 2) % 8;
1832 unsigned int v_u1 = u;
1833 unsigned int v_v1 = v;
1834 updateFreemanPosition(v_u1, v_v1, (element + 1) % 8);
1836 if (hasGoodLevel(I, v_u1, v_v1)) {
1837 element = (element + 1) % 8;
1840 unsigned int v_u2 = u;
1841 unsigned int v_v2 = v;
1842 updateFreemanPosition(v_u2, v_v2, element);
1844 if (hasGoodLevel(I, v_u2, v_v2)) {
1848 unsigned int v_u3 = u;
1849 unsigned int v_v3 = v;
1850 updateFreemanPosition(v_u3, v_v3, (element + 7) % 8);
1852 if (hasGoodLevel(I, v_u3, v_v3)) {
1853 element = (element + 7) % 8;
1856 unsigned int v_u4 = u;
1857 unsigned int v_v4 = v;
1858 updateFreemanPosition(v_u4, v_v4, (element + 6) % 8);
1860 if (hasGoodLevel(I, v_u4, v_v4)) {
1861 element = (element + 6) % 8;
1864 unsigned int v_u5 = u;
1865 unsigned int v_v5 = v;
1866 updateFreemanPosition(v_u5, v_v5, (element + 5) % 8);
1868 if (hasGoodLevel(I, v_u5, v_v5)) {
1869 element = (element + 5) % 8;
1872 unsigned int v_u6 = u;
1873 unsigned int v_v6 = v;
1874 updateFreemanPosition(v_u6, v_v6, (element + 4) % 8);
1876 if (hasGoodLevel(I, v_u6, v_v6)) {
1877 element = (element + 4) % 8;
1880 unsigned int v_u7 = u;
1881 unsigned int v_v7 = v;
1882 updateFreemanPosition(v_u7, v_v7, (element + 3) % 8);
1884 if (hasGoodLevel(I, v_u7, v_v7)) {
1885 element = (element + 3) % 8;
1937 void vpDot2::computeFreemanParameters(
const int &u_p,
const int &v_p,
unsigned int &element,
int &du,
int &dv,
1938 float &dS,
float &dMu,
float &dMv,
float &dMuv,
float &dMu2,
float &dMv2)
1958 dS =
static_cast<float>(v_p);
1960 dMv =
static_cast<float>(0.5 * v_p * v_p);
1961 if (compute_moment) {
1962 dMuv =
static_cast<float>(0.25 * v_p * v_p * ((2 * u_p) + 1));
1964 dMv2 =
static_cast<float>((1.0 / 3.) * v_p * v_p * v_p);
1971 dS =
static_cast<float>(v_p + 0.5);
1972 dMu = -
static_cast<float>((0.5 * u_p * (u_p + 1)) + (1.0 / 6.0));
1973 dMv =
static_cast<float>((0.5 * v_p * (v_p + 1)) + (1.0 / 6.0));
1974 if (compute_moment) {
1975 float half_u_p =
static_cast<float>(0.5 * u_p);
1976 dMuv =
static_cast<float>((v_p * v_p * (0.25 + half_u_p)) + (v_p * ((1. / 3.) + half_u_p)) + ((1. / 6.) * u_p) + 0.125);
1977 dMu2 =
static_cast<float>(((-1. / 3.) * u_p * ((u_p * u_p) + (1.5 * u_p) + 1.)) - (1. / 12.0));
1978 dMv2 =
static_cast<float>(((1. / 3.) * v_p * ((v_p * v_p) + (1.5 * v_p) + 1.)) + (1. / 12.0));
1985 dMu =
static_cast<float>(-0.5 * u_p * u_p);
1987 if (compute_moment) {
1989 dMu2 =
static_cast<float>((-1.0 / 3.) * u_p * u_p * u_p);
1997 dS =
static_cast<float>(-v_p - 0.5);
1998 dMu = -
static_cast<float>((0.5 * u_p * (u_p - 1)) + (1.0 / 6.0));
1999 dMv = -
static_cast<float>((0.5 * v_p * (v_p + 1)) + (1.0 / 6.0));
2000 if (compute_moment) {
2001 float half_u_p =
static_cast<float>(0.5 * u_p);
2002 dMuv =
static_cast<float>((((v_p * v_p * (0.25 - half_u_p)) + (v_p * ((1. / 3.) - half_u_p))) - ((1. / 6.) * u_p)) + 0.125);
2003 dMu2 =
static_cast<float>(((-1. / 3.) * u_p * (((u_p * u_p) - (1.5 * u_p)) + 1.)) - (1. / 12.0));
2004 dMv2 =
static_cast<float>(((-1. / 3.) * v_p * ((v_p * v_p) + (1.5 * v_p) + 1.)) - (1. / 12.0));
2010 dS =
static_cast<float>(-v_p);
2011 dMv =
static_cast<float>(-0.5 * v_p * v_p);
2013 if (compute_moment) {
2014 dMuv =
static_cast<float>(-0.25 * v_p * v_p * ((2 * u_p) - 1));
2016 dMv2 =
static_cast<float>((-1.0 / 3.) * v_p * v_p * v_p);
2023 dS =
static_cast<float>(-v_p + 0.5);
2024 dMu =
static_cast<float>((0.5 * u_p * (u_p - 1)) + (1.0 / 6.0));
2025 dMv =
static_cast<float>(-((0.5 * v_p * (v_p - 1)) + (1.0 / 6.0)));
2026 if (compute_moment) {
2027 float half_u_p =
static_cast<float>(0.5 * u_p);
2028 dMuv =
static_cast<float>((((v_p * v_p * (0.25 - half_u_p)) - (v_p * ((1. / 3.) - half_u_p))) - ((1. / 6.) * u_p)) + 0.125);
2029 dMu2 =
static_cast<float>(((1. / 3.) * u_p * (((u_p * u_p) - (1.5 * u_p)) + 1.)) - (1. / 12.0));
2030 dMv2 =
static_cast<float>(((-1. / 3.) * v_p * (((v_p * v_p) - (1.5 * v_p)) + 1.)) - (1. / 12.0));
2037 dMu =
static_cast<float>(0.5 * u_p * u_p);
2039 if (compute_moment) {
2041 dMu2 =
static_cast<float>((1.0 / 3.) * u_p * u_p * u_p);
2049 dS =
static_cast<float>(v_p - 0.5);
2050 dMu =
static_cast<float>((0.5 * u_p * (u_p + 1)) + (1.0 / 6.0));
2051 dMv =
static_cast<float>((0.5 * v_p * (v_p - 1)) + (1.0 / 6.0));
2052 if (compute_moment) {
2053 float half_u_p =
static_cast<float>(0.5 * u_p);
2054 dMuv =
static_cast<float>(((v_p * v_p * (0.25 + half_u_p)) - (v_p * ((1. / 3.) + half_u_p))) + ((1. / 6.) * u_p) + 0.125);
2055 dMu2 =
static_cast<float>(((1. / 3.) * u_p * ((u_p * u_p) + (1.5 * u_p) + 1.)) + (1. / 12.0));
2056 dMv2 =
static_cast<float>(((1. / 3.) * v_p * (((v_p * v_p) - (1.5 * v_p)) + 1.)) - (1. / 12.0));
2061 std::cout <<
"to complete the default" << std::endl;
2078 void vpDot2::updateFreemanPosition(
unsigned int &u,
unsigned int &v,
const unsigned int &dir)
2110 std::cout <<
"In vpDot2::updateFreemanPosition dir not identified" << std::endl;
2142 double u = ip.
get_u();
2143 double v = ip.
get_v();
2145 if ((u < 0) || (u >= w)) {
2148 if ((v < 0) || (v >= h)) {
2165 bool vpDot2::isInArea(
const unsigned int &u,
const unsigned int &v)
const
2167 unsigned int area_u_min =
static_cast<unsigned int>(area.
getLeft());
2168 unsigned int area_u_max =
static_cast<unsigned int>(area.
getRight());
2169 unsigned int area_v_min =
static_cast<unsigned int>(area.
getTop());
2170 unsigned int area_v_max =
static_cast<unsigned int>(area.
getBottom());
2172 if ((u < area_u_min) || (u > area_u_max)) {
2175 if ((v < area_v_min) || (v > area_v_max)) {
2192 void vpDot2::getGridSize(
unsigned int &gridWidth,
unsigned int &gridHeight)
2202 if (gridWidth == 0) {
2205 if (gridHeight == 0) {
2224 int cog_u =
static_cast<int>(cog.
get_u());
2225 int cog_v =
static_cast<int>(cog.
get_v());
2227 unsigned int sum_value = 0;
2228 unsigned int nb_pixels = 0;
2230 for (
unsigned int i =
static_cast<unsigned int>(this->bbox_u_min); i <= static_cast<unsigned int>(this->bbox_u_max); ++i) {
2231 unsigned int pixel_gray =
static_cast<unsigned int>(I[
static_cast<unsigned int>(cog_v)][i]);
2233 sum_value += pixel_gray;
2237 for (
unsigned int i =
static_cast<unsigned int>(this->bbox_v_min); i <= static_cast<unsigned int>(this->bbox_v_max); ++i) {
2238 unsigned char pixel_gray = I[i][
static_cast<unsigned int>(cog_u)];
2240 sum_value += pixel_gray;
2244 if (nb_pixels < 10) {
2247 if ((cog_u - bbox_u_min) >(cog_v - bbox_v_min)) {
2248 imin = cog_v - bbox_v_min;
2251 imin = cog_u - bbox_u_min;
2253 if ((bbox_u_max - cog_u) > (bbox_v_max - cog_v)) {
2254 imax = bbox_v_max - cog_v;
2257 imax = bbox_u_max - cog_u;
2259 for (
int i = -imin; i <= imax; ++i) {
2260 unsigned int pixel_gray =
static_cast<unsigned int>(I[
static_cast<unsigned int>(cog_v + i)][
static_cast<unsigned int>(cog_u + i)]);
2262 sum_value += pixel_gray;
2267 if ((cog_u - bbox_u_min) > (bbox_v_max - cog_v)) {
2268 imin = bbox_v_max - cog_v;
2271 imin = cog_u - bbox_u_min;
2273 if ((bbox_u_max - cog_u) > (cog_v - bbox_v_min)) {
2274 imax = cog_v - bbox_v_min;
2277 imax = bbox_u_max - cog_u;
2280 for (
int i = -imin; i <= imax; ++i) {
2281 unsigned char pixel_gray = I[
static_cast<unsigned int>(cog_v - i)][
static_cast<unsigned int>(cog_u + i)];
2283 sum_value += pixel_gray;
2289 if (nb_pixels == 0) {
2294 mean_gray_level = sum_value / nb_pixels;
2325 std::cout << Cogs.
getRows() <<
" dots loaded from file " << dotFile << std::endl;
2330 std::cout <<
"Dot file has a wrong number of dots : redefining them" << std::endl;
2337 for (i = 0; i < n; ++i) {
2338 cog.
set_uv(Cogs[i][0], Cogs[i][1]);
2349 std::cout <<
"Cannot track dots from file" << std::endl;
2355 for (i = 0; ((i < n) && fromFile); ++i) {
2357 for (
unsigned int j = 0; ((j < n) && fromFile); ++j) {
2361 std::cout <<
"Dots from file seem incoherent" << std::endl;
2372 std::cout <<
"Click on the " << n <<
" dots clockwise starting from upper/left dot..." << std::endl;
2373 for (i = 0; i < n; ++i) {
2383 Cogs[i][0] = cog.
get_u();
2384 Cogs[i][1] = cog.
get_v();
2390 if ((!fromFile) && (dotFile !=
"")) {
2392 std::cout << Cogs.
getRows() <<
" dots written to file " << dotFile << std::endl;
2396 for (i = 0; i < n; ++i) {
2420 std::vector<vpImagePoint> &cogs,
vpImagePoint *cogStar)
2424 for (i = 0; i < n; ++i) {
2426 cogs.push_back(dot[i].
getCog());
2429 unsigned int cogs_size = cogs.size();
2430 for (i = n; i < cogs_size; ++i) {
2434 for (i = 0; i < n; ++i) {
2438 if (cogStar !=
nullptr) {
2439 for (i = 0; i < n; ++i) {
2462 const std::list<vpImagePoint> &edges_list,
vpColor color,
unsigned int thickness)
2465 std::list<vpImagePoint>::const_iterator it;
2467 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2487 vpColor color,
unsigned int thickness)
2490 std::list<vpImagePoint>::const_iterator it;
2492 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2502 VISP_EXPORT std::ostream &
operator<<(std::ostream &os,
vpDot2 &d) {
return (os <<
"(" << d.getCog() <<
")"); }
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
unsigned int getRows() const
Class to define RGB colors available for display functionalities.
static const vpColor blue
static const vpColor purple
static const vpColor green
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayCircle(const vpImage< unsigned char > &I, const vpImageCircle &circle, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void display(const vpImage< unsigned char > &I)
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 displayDotLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, 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)
This tracker is meant to track a blob (connex pixels with same gray level) on a vpImage.
unsigned int getGrayLevelMin() const
unsigned int getGrayLevelMax() const
void track(const vpImage< unsigned char > &I, bool canMakeTheWindowGrow=true)
void setGraphics(bool activate)
void setMaxSizeSearchDistancePrecision(const double &maxSizeSearchDistancePrecision)
vpDot2 & operator=(const vpDot2 &twinDot)
static void trackAndDisplay(vpDot2 dot[], const unsigned int &n, vpImage< unsigned char > &I, std::vector< vpImagePoint > &cogs, vpImagePoint *cogStar=nullptr)
void setGraphicsThickness(unsigned int t)
double getEllipsoidShapePrecision() const
void searchDotsInArea(const vpImage< unsigned char > &I, int area_u, int area_v, unsigned int area_w, unsigned int area_h, std::list< vpDot2 > &niceDots)
void display(const vpImage< unsigned char > &I, vpColor color=vpColor::red, unsigned int thickness=1) const
void setGrayLevelMax(const unsigned int &max)
void setSizePrecision(const double &sizePrecision)
void setGrayLevelPrecision(const double &grayLevelPrecision)
void setGrayLevelMin(const unsigned int &min)
void getFreemanChain(std::list< unsigned int > &freeman_chain) const
void setHeight(const double &height)
double getMaxSizeSearchDistancePrecision() const
void setCog(const vpImagePoint &ip)
vpImagePoint getCog() const
double getSizePrecision() const
double getGrayLevelPrecision() const
void setEllipsoidBadPointsPercentage(const double &percentage=0.0)
double getDistance(const vpDot2 &distantDot) const
void setWidth(const double &width)
void setEllipsoidShapePrecision(const double &ellipsoidShapePrecision)
double getMeanGrayLevel() const
void setArea(const double &area)
void setComputeMoments(bool activate)
void initTracking(const vpImage< unsigned char > &I, unsigned int size=0)
static vpMatrix defineDots(vpDot2 dot[], const unsigned int &n, const std::string &dotFile, vpImage< unsigned char > &I, vpColor col=vpColor::blue, bool trackDot=true)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_uv(double u, double v)
unsigned int getWidth() const
unsigned int getHeight() const
static Type maximum(const Type &a, const Type &b)
static double sqr(double x)
Implementation of a matrix and operations on matrices.
static bool loadMatrix(const std::string &filename, vpArray2D< double > &M, bool binary=false, char *header=nullptr)
static bool saveMatrix(const std::string &filename, const vpArray2D< double > &M, bool binary=false, const char *header="")
Defines a rectangle in the plane.
void setRect(double l, double t, double w, double h)
Class that defines what is a feature generic tracker.
Error that can be emitted by the vpTracker class and its derivatives.
@ featureLostError
Tracker lost feature.
@ notEnoughPointError
Not enough point to track.