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 std::list<vpImagePoint>::const_iterator ip_edges_list_end = ip_edges_list.end();
218 for (it = ip_edges_list.begin(); it != ip_edges_list_end; ++it) {
260 unsigned int i =
static_cast<unsigned int>(cog.
get_i());
261 unsigned int j =
static_cast<unsigned int>(cog.
get_j());
263 double Ip = pow(
static_cast<double>(I[i][j]) / 255, 1 / gamma);
265 if ((Ip - (1 - grayLevelPrecision)) < 0) {
269 gray_level_min =
static_cast<unsigned int>(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
270 if (gray_level_min > 255) {
271 gray_level_min = 255;
274 gray_level_max =
static_cast<unsigned int>(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
275 if (gray_level_max > 255) {
276 gray_level_max = 255;
316 unsigned int i =
static_cast<unsigned int>(cog.
get_i());
317 unsigned int j =
static_cast<unsigned int>(cog.
get_j());
319 double Ip = pow(
static_cast<double>(I[i][j]) / 255, 1 / gamma);
321 if ((Ip - (1 - grayLevelPrecision)) < 0) {
325 gray_level_min =
static_cast<unsigned int>(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
326 if (gray_level_min > 255) {
327 gray_level_min = 255;
330 gray_level_max =
static_cast<unsigned int>(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
331 if (gray_level_max > 255) {
332 gray_level_max = 255;
381 unsigned int gray_lvl_max,
unsigned int size)
385 this->gray_level_min = gray_lvl_min;
386 this->gray_level_max = gray_lvl_max;
456 bool found = computeParameters(I, cog.
get_u(), cog.
get_v());
460 found = isValid(I, wantedDot);
479 double searchWindowWidth = 0.0;
480 double searchWindowHeight = 0.0;
482 if ((std::fabs(
getWidth()) <= std::numeric_limits<double>::epsilon()) ||
483 (std::fabs(
getHeight()) <= std::numeric_limits<double>::epsilon())) {
484 searchWindowWidth = 80.;
485 searchWindowHeight = 80.;
487 else if (canMakeTheWindowGrow) {
496 std::list<vpDot2> candidates;
498 static_cast<int>(this->cog.get_v() - (searchWindowHeight / 2.0)),
499 static_cast<unsigned int>(searchWindowWidth),
500 static_cast<unsigned int>(searchWindowHeight), candidates);
504 if (candidates.empty()) {
510 vpDot2 movingDot = candidates.front();
526 bbox_u_min = movingDot.bbox_u_min;
527 bbox_u_max = movingDot.bbox_u_max;
528 bbox_v_min = movingDot.bbox_v_min;
529 bbox_v_max = movingDot.bbox_v_max;
536 "The center of gravity of the dot is not in the image"));
548 if ((Ip - (1 - grayLevelPrecision)) < 0) {
552 gray_level_min =
static_cast<unsigned int>(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
553 if (gray_level_min > 255) {
554 gray_level_min = 255;
557 gray_level_max =
static_cast<unsigned int>(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
558 if (gray_level_max > 255) {
559 gray_level_max = 255;
592 track(I, canMakeTheWindowGrow);
658 double diff_u = this->cog.
get_u() - cogDistantDot.
get_u();
659 double diff_v = this->cog.
get_v() - cogDistantDot.
get_v();
660 return sqrt((diff_u * diff_u) + (diff_v * diff_v));
719 double epsilon = 0.05;
720 if (grayLevelPrecision < epsilon) {
721 this->grayLevelPrecision = epsilon;
723 else if (grayLevelPrecision > 1) {
724 this->grayLevelPrecision = 1.0;
727 this->grayLevelPrecision = precision;
749 if (sizePrecision < 0) {
750 this->sizePrecision = 0;
752 else if (sizePrecision > 1) {
753 this->sizePrecision = 1.0;
756 this->sizePrecision = precision;
795 if (ellipsoidShapePrecision < 0) {
796 this->ellipsoidShapePrecision = 0;
798 else if (ellipsoidShapePrecision > 1) {
799 this->ellipsoidShapePrecision = 1.0;
802 this->ellipsoidShapePrecision = precision;
823 double epsilon = 0.05;
824 if (maxSizeSearchDistancePrecision < epsilon) {
825 this->maxSizeSearchDistancePrecision = epsilon;
827 else if (maxSizeSearchDistancePrecision > 1) {
828 this->maxSizeSearchDistancePrecision = 1.0;
831 this->maxSizeSearchDistancePrecision = precision;
859 unsigned int image_w = I.
getWidth();
866 else if (u >=
static_cast<int>(image_w)) {
867 u =
static_cast<int>(image_w) - 1;
872 else if (v >=
static_cast<int>(image_h)) {
873 v =
static_cast<int>(image_h) - 1;
876 if ((
static_cast<unsigned int>(u) + w) > image_w) {
877 w = image_w -
static_cast<unsigned int>(u) - 1;
879 if ((
static_cast<unsigned int>(v) + h) > image_h) {
880 h = image_h -
static_cast<unsigned int>(v) - 1;
976 unsigned int area_h, std::list<vpDot2> &niceDots)
984 setArea(I, area_u, area_v, area_w, area_h);
987 unsigned int gridWidth;
988 unsigned int gridHeight;
989 getGridSize(gridWidth, gridHeight);
1003 std::list<vpDot2> badDotsVector;
1004 std::list<vpDot2>::iterator itnice;
1005 std::list<vpDot2>::iterator itbad;
1007 vpDot2 *dotToTest =
nullptr;
1010 unsigned int area_u_min =
static_cast<unsigned int>(area.
getLeft());
1011 unsigned int area_u_max =
static_cast<unsigned int>(area.
getRight());
1012 unsigned int area_v_min =
static_cast<unsigned int>(area.
getTop());
1013 unsigned int area_v_max =
static_cast<unsigned int>(area.
getBottom());
1018 for (v = area_v_min; v < area_v_max; v = v + gridHeight) {
1019 for (u = area_u_min; u < area_u_max; u = u + gridWidth) {
1023 if (!hasGoodLevel(I, u, v)) {
1029 bool good_germ =
true;
1031 itnice = niceDots.begin();
1032 while ((itnice != niceDots.end()) && (good_germ ==
true)) {
1035 cogTmpDot = tmpDot.
getCog();
1036 double u0 = cogTmpDot.
get_u();
1037 double v0 = cogTmpDot.
get_v();
1038 double half_w = tmpDot.
getWidth() / 2.;
1039 double half_h = tmpDot.
getHeight() / 2.;
1041 if ((u >= (u0 - half_w)) && (u <= (u0 + half_w)) && (v >= (v0 - half_h)) && (v <= (v0 + half_h))) {
1053 unsigned int border_u;
1054 unsigned int border_v;
1055 if (findFirstBorder(I, u, v, border_u, border_v) ==
false) {
1064 itbad = badDotsVector.begin();
1065 #define vpBAD_DOT_VALUE (*itbad)
1068 while ((itbad != badDotsVector.end()) && (good_germ ==
true)) {
1069 if ((
static_cast<double>(u) >= vpBAD_DOT_VALUE.bbox_u_min) && (
static_cast<double>(u) <= vpBAD_DOT_VALUE.bbox_u_max) &&
1070 (
static_cast<double>(v) >= vpBAD_DOT_VALUE.bbox_v_min) && (
static_cast<double>(v) <= vpBAD_DOT_VALUE.bbox_v_max)) {
1071 std::list<vpImagePoint>::const_iterator it_edges = ip_edges_list.begin();
1072 while ((it_edges != ip_edges_list.end()) && (good_germ ==
true)) {
1076 cogBadDot = *it_edges;
1077 if ((std::fabs(border_u - cogBadDot.
get_u()) <=
1079 std::numeric_limits<double>::epsilon())) &&
1080 (std::fabs(v - cogBadDot.
get_v()) <=
1082 std::numeric_limits<double>::epsilon()))) {
1090 #undef vpBAD_DOT_VALUE
1100 vpTRACE(4,
"Try germ (%d, %d)", u, v);
1108 if (dotToTest !=
nullptr) {
1111 dotToTest = getInstance();
1127 if (dotToTest->computeParameters(I) ==
false) {
1135 if (dotToTest->isValid(I, *
this)) {
1142 double area_center_u = (area_u + (area_w / 2.0)) - 0.5;
1143 double area_center_v = (area_v + (area_h / 2.0)) - 0.5;
1145 double thisDiff_u = cogDotToTest.
get_u() - area_center_u;
1146 double thisDiff_v = cogDotToTest.
get_v() - area_center_v;
1147 double thisDist = sqrt((thisDiff_u * thisDiff_u) + (thisDiff_v * thisDiff_v));
1149 bool stopLoop =
false;
1150 itnice = niceDots.begin();
1152 while ((itnice != niceDots.end()) && (stopLoop ==
false)) {
1156 double epsilon = 3.0;
1159 cogTmpDot = tmpDot.
getCog();
1161 if ((fabs(cogTmpDot.
get_u() - cogDotToTest.
get_u()) < epsilon) &&
1162 (fabs(cogTmpDot.
get_v() - cogDotToTest.
get_v()) < epsilon)) {
1171 double otherDiff_u = cogTmpDot.
get_u() - area_center_u;
1172 double otherDiff_v = cogTmpDot.
get_v() - area_center_v;
1173 double otherDist = sqrt((otherDiff_u * otherDiff_u) + (otherDiff_v * otherDiff_v));
1178 if (otherDist > thisDist) {
1179 niceDots.insert(itnice, *dotToTest);
1190 vpTRACE(4,
"End while (%d, %d)", u, v);
1194 if ((itnice == niceDots.end()) && (stopLoop ==
false)) {
1195 niceDots.push_back(*dotToTest);
1200 badDotsVector.push_front(*dotToTest);
1204 if (dotToTest !=
nullptr) {
1241 if ((std::fabs(wantedDot.
getWidth()) > std::numeric_limits<double>::epsilon()) &&
1242 (std::fabs(wantedDot.
getHeight()) > std::numeric_limits<double>::epsilon()) &&
1243 (std::fabs(wantedDot.
getArea()) > std::numeric_limits<double>::epsilon())) {
1244 if (std::fabs(size_precision) > std::numeric_limits<double>::epsilon()) {
1245 double epsilon = 0.001;
1247 std::cout <<
"test size precision......................\n";
1248 std::cout <<
"wanted dot: "
1250 <<
" precision=" << size_precision <<
" epsilon=" << epsilon << std::endl;
1251 std::cout <<
"dot found: "
1255 if ((((wantedDot.
getWidth() * size_precision) - epsilon) <
getWidth()) ==
false) {
1258 printf(
"Bad width > for dot (%g, %g)\n", cog.
get_u(), cog.
get_v());
1263 if ((
getWidth() < (wantedDot.
getWidth() / (size_precision + epsilon))) ==
false) {
1266 printf(
"Bad width %g > %g for dot (%g, %g)\n",
getWidth(), wantedDot.
getWidth() / (size_precision + epsilon),
1275 printf(
"Bad height %g > %g for dot (%g, %g)\n", wantedDot.
getHeight() * size_precision - epsilon,
getHeight(),
1284 printf(
"Bad height %g > %g for dot (%g, %g)\n",
getHeight(), wantedDot.
getHeight() / (size_precision + epsilon),
1290 if ((((wantedDot.
getArea() * (size_precision * size_precision)) - epsilon) <
getArea()) ==
false) {
1293 printf(
"Bad surface %g > %g for dot (%g, %g)\n",
1299 if ((
getArea() < (wantedDot.
getArea() / ((size_precision * size_precision) + epsilon))) ==
false) {
1302 printf(
"Bad surface %g < %g for dot (%g, %g)\n",
getArea(),
1303 wantedDot.
getArea() / (size_precision * size_precision + epsilon), cog.
get_u(), cog.
get_v());
1314 int nb_point_to_test = 20;
1315 int nb_bad_points = 0;
1316 int nb_max_bad_points =
static_cast<int>(nb_point_to_test * allowedBadPointsPercentage_);
1317 double step_angle = (2 * M_PI) / nb_point_to_test;
1320 if ((std::fabs(ellipsoidShape_precision) > std::numeric_limits<double>::epsilon()) && compute_moment) {
1338 double Sqrt = sqrt((tmp1 * tmp1) + (4 * tmp2 * tmp2));
1348 double innerCoef = ellipsoidShape_precision;
1350 double cog_u = this->cog.
get_u();
1351 double cog_v = this->cog.
get_v();
1355 for (
double theta = 0.; theta < (2 * M_PI); theta += step_angle) {
1356 u =
static_cast<unsigned int>(cog_u + (innerCoef * ((a1 * cos(alpha) * cos(theta)) - (a2 * sin(alpha) * sin(theta)))));
1357 v =
static_cast<unsigned int>(cog_v + (innerCoef * ((a1 * sin(alpha) * cos(theta)) + (a2 * cos(alpha) * sin(theta)))));
1358 if (!this->hasGoodLevel(I, u, v)) {
1360 printf(
"Inner circle pixel (%u, %u) has bad level for dot (%g, %g): "
1361 "%d not in [%u, %u]\n",
1362 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1367 for (
unsigned int t = 0; t < thickness; ++t) {
1378 if (nb_bad_points > nb_max_bad_points) {
1380 printf(
"Inner ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1389 double outCoef = 2 - ellipsoidShape_precision;
1391 for (
double theta = 0.; theta < (2 * M_PI); theta += step_angle) {
1392 u =
static_cast<unsigned int>(cog_u + (outCoef * ((a1 * cos(alpha) * cos(theta)) - (a2 * sin(alpha) * sin(theta)))));
1393 v =
static_cast<unsigned int>(cog_v + (outCoef * ((a1 * sin(alpha) * cos(theta)) + (a2 * cos(alpha) * sin(theta)))));
1400 if ((
static_cast<double>(u) < area.
getLeft()) ||
1401 (
static_cast<double>(u) > area.
getRight()) ||
1402 (
static_cast<double>(v) < area.
getTop()) ||
1403 (
static_cast<double>(v) > area.
getBottom())) {
1407 if (!this->hasReverseLevel(I, u, v)) {
1409 printf(
"Outside circle pixel (%u, %u) has bad level for dot (%g, "
1410 "%g): %d not in [%u, %u]\n",
1411 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1416 for (
unsigned int t = 0; t < thickness; ++t) {
1426 if (nb_bad_points > nb_max_bad_points) {
1428 printf(
"Outside ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1454 bool vpDot2::hasGoodLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1456 if (!isInArea(u, v)) {
1460 if ((I[v][u] >= gray_level_min) && (I[v][u] <= gray_level_max)) {
1480 bool vpDot2::hasReverseLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1483 if (!isInArea(u, v)) {
1487 if ((I[v][u] < gray_level_min) || (I[v][u] > gray_level_max)) {
1561 direction_list.clear();
1562 ip_edges_list.clear();
1569 if (std::fabs(est_u + 1.0) <= (
vpMath::maximum(std::fabs(est_u), 1.) * std::numeric_limits<double>::epsilon())) {
1570 est_u = this->cog.
get_u();
1575 if (std::fabs(est_v + 1.0) <= (
vpMath::maximum(std::fabs(est_v), 1.) * std::numeric_limits<double>::epsilon())) {
1576 est_v = this->cog.
get_v();
1581 if (!isInArea(
static_cast<unsigned int>(est_u),
static_cast<unsigned int>(est_v))) {
1583 "Initial pixel coordinates (%d, %d) for dot tracking are "
1585 static_cast<int>(est_u),
static_cast<int>(est_v));
1589 bbox_u_min =
static_cast<int>(I.
getWidth());
1591 bbox_v_min =
static_cast<int>(I.
getHeight());
1596 if (!hasGoodLevel(I,
static_cast<unsigned int>(est_u),
static_cast<unsigned int>(est_v))) {
1597 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));
1603 if (!findFirstBorder(I,
static_cast<unsigned int>(est_u),
static_cast<unsigned int>(est_v), this->firstBorder_u, this->firstBorder_v)) {
1605 vpDEBUG_TRACE(3,
"Can't find first border (%d, %d) coordinates",
static_cast<int>(est_u),
static_cast<int>(est_v));
1609 unsigned int dir = 6;
1612 computeFreemanChainElement(I, this->firstBorder_u, this->firstBorder_v, dir);
1613 unsigned int firstDir = dir;
1616 if (!isInArea(this->firstBorder_u, this->firstBorder_v)) {
1617 vpDEBUG_TRACE(3,
"Border pixel coordinates (%d, %d) of the dot are not in the area", this->firstBorder_u,
1618 this->firstBorder_v);
1623 direction_list.push_back(dir);
1625 ip.
set_u(this->firstBorder_u);
1626 ip.
set_v(this->firstBorder_v);
1628 ip_edges_list.push_back(ip);
1630 int border_u =
static_cast<int>(this->firstBorder_u);
1631 int border_v =
static_cast<int>(this->firstBorder_v);
1633 float dS, dMu, dMv, dMuv, dMu2, dMv2;
1644 for (
int t = 0; t < static_cast<int>(thickness); ++t) {
1645 ip.
set_u(border_u + t);
1656 computeFreemanParameters(border_u, border_v, dir, du, dv,
1667 if (compute_moment) {
1673 if (!isInArea(
static_cast<unsigned int>(border_u),
static_cast<unsigned int>(border_v))) {
1675 vpDEBUG_TRACE(3,
"Dot (%d, %d) is not in the area", border_u, border_v);
1682 direction_list.push_back(dir);
1686 ip_edges_list.push_back(ip);
1689 if (border_v < bbox_v_min) {
1690 bbox_v_min = border_v;
1692 if (border_v > bbox_v_max) {
1693 bbox_v_max = border_v;
1695 if (border_u < bbox_u_min) {
1696 bbox_u_min = border_u;
1698 if (border_u > bbox_u_max) {
1699 bbox_u_max = border_u;
1703 if (computeFreemanChainElement(I,
static_cast<unsigned int>(border_u),
static_cast<unsigned int>(border_v), dir) ==
false) {
1704 vpDEBUG_TRACE(3,
"Can't compute Freeman chain for dot (%d, %d)", border_u, border_v);
1711 }
while (((getFirstBorder_u() !=
static_cast<unsigned int>(border_u)) || (getFirstBorder_v() !=
static_cast<unsigned int>(border_v)) ||
1712 (firstDir != dir)) &&
1713 isInArea(
static_cast<unsigned int>(border_u),
static_cast<unsigned int>(border_v)));
1716 #if VP_DEBUG_MODE == 3
1724 if ((std::fabs(
m00) <= std::numeric_limits<double>::epsilon()) ||
1725 (std::fabs(
m00 - 1.) <= (
vpMath::maximum(std::fabs(
m00), 1.) * std::numeric_limits<double>::epsilon()))) {
1726 vpDEBUG_TRACE(3,
"The center of gravity of the dot wasn't properly detected");
1732 double tmpCenter_u =
m10 /
m00;
1733 double tmpCenter_v =
m01 /
m00;
1736 if (compute_moment) {
1742 cog.
set_u(tmpCenter_u);
1743 cog.
set_v(tmpCenter_v);
1746 width = (bbox_u_max - bbox_u_min) + 1;
1747 height = (bbox_v_max - bbox_v_min) + 1;
1750 computeMeanGrayLevel(I);
1769 bool vpDot2::findFirstBorder(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1770 unsigned int &border_u,
unsigned int &border_v)
1780 double epsilon = 0.001;
1783 std::cout <<
"gray level: " << gray_level_min <<
" " << gray_level_max << std::endl;
1785 while (hasGoodLevel(I, border_u + 1, border_v) && (border_u < area.
getRight()) ) {
1791 "The found dot (%d, %d, %d) has a greater width than the "
1824 bool vpDot2::computeFreemanChainElement(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1825 unsigned int &element)
1828 if (hasGoodLevel(I, u, v)) {
1829 unsigned int v_u = u;
1830 unsigned int v_v = v;
1832 updateFreemanPosition(v_u, v_v, (element + 2) % 8);
1833 if (hasGoodLevel(I, v_u, v_v)) {
1834 element = (element + 2) % 8;
1837 unsigned int v_u1 = u;
1838 unsigned int v_v1 = v;
1839 updateFreemanPosition(v_u1, v_v1, (element + 1) % 8);
1841 if (hasGoodLevel(I, v_u1, v_v1)) {
1842 element = (element + 1) % 8;
1845 unsigned int v_u2 = u;
1846 unsigned int v_v2 = v;
1847 updateFreemanPosition(v_u2, v_v2, element);
1849 if (hasGoodLevel(I, v_u2, v_v2)) {
1853 unsigned int v_u3 = u;
1854 unsigned int v_v3 = v;
1855 updateFreemanPosition(v_u3, v_v3, (element + 7) % 8);
1857 if (hasGoodLevel(I, v_u3, v_v3)) {
1858 element = (element + 7) % 8;
1861 unsigned int v_u4 = u;
1862 unsigned int v_v4 = v;
1863 updateFreemanPosition(v_u4, v_v4, (element + 6) % 8);
1865 if (hasGoodLevel(I, v_u4, v_v4)) {
1866 element = (element + 6) % 8;
1869 unsigned int v_u5 = u;
1870 unsigned int v_v5 = v;
1871 updateFreemanPosition(v_u5, v_v5, (element + 5) % 8);
1873 if (hasGoodLevel(I, v_u5, v_v5)) {
1874 element = (element + 5) % 8;
1877 unsigned int v_u6 = u;
1878 unsigned int v_v6 = v;
1879 updateFreemanPosition(v_u6, v_v6, (element + 4) % 8);
1881 if (hasGoodLevel(I, v_u6, v_v6)) {
1882 element = (element + 4) % 8;
1885 unsigned int v_u7 = u;
1886 unsigned int v_v7 = v;
1887 updateFreemanPosition(v_u7, v_v7, (element + 3) % 8);
1889 if (hasGoodLevel(I, v_u7, v_v7)) {
1890 element = (element + 3) % 8;
1942 void vpDot2::computeFreemanParameters(
const int &u_p,
const int &v_p,
unsigned int &element,
int &du,
int &dv,
1943 float &dS,
float &dMu,
float &dMv,
float &dMuv,
float &dMu2,
float &dMv2)
1963 dS =
static_cast<float>(v_p);
1965 dMv =
static_cast<float>(0.5 * v_p * v_p);
1966 if (compute_moment) {
1967 dMuv =
static_cast<float>(0.25 * v_p * v_p * ((2 * u_p) + 1));
1969 dMv2 =
static_cast<float>((1.0 / 3.) * v_p * v_p * v_p);
1976 dS =
static_cast<float>(v_p + 0.5);
1977 dMu = -
static_cast<float>((0.5 * u_p * (u_p + 1)) + (1.0 / 6.0));
1978 dMv =
static_cast<float>((0.5 * v_p * (v_p + 1)) + (1.0 / 6.0));
1979 if (compute_moment) {
1980 float half_u_p =
static_cast<float>(0.5 * u_p);
1981 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);
1982 dMu2 =
static_cast<float>(((-1. / 3.) * u_p * ((u_p * u_p) + (1.5 * u_p) + 1.)) - (1. / 12.0));
1983 dMv2 =
static_cast<float>(((1. / 3.) * v_p * ((v_p * v_p) + (1.5 * v_p) + 1.)) + (1. / 12.0));
1990 dMu =
static_cast<float>(-0.5 * u_p * u_p);
1992 if (compute_moment) {
1994 dMu2 =
static_cast<float>((-1.0 / 3.) * u_p * u_p * u_p);
2002 dS =
static_cast<float>(-v_p - 0.5);
2003 dMu = -
static_cast<float>((0.5 * u_p * (u_p - 1)) + (1.0 / 6.0));
2004 dMv = -
static_cast<float>((0.5 * v_p * (v_p + 1)) + (1.0 / 6.0));
2005 if (compute_moment) {
2006 float half_u_p =
static_cast<float>(0.5 * u_p);
2007 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);
2008 dMu2 =
static_cast<float>(((-1. / 3.) * u_p * (((u_p * u_p) - (1.5 * u_p)) + 1.)) - (1. / 12.0));
2009 dMv2 =
static_cast<float>(((-1. / 3.) * v_p * ((v_p * v_p) + (1.5 * v_p) + 1.)) - (1. / 12.0));
2015 dS =
static_cast<float>(-v_p);
2016 dMv =
static_cast<float>(-0.5 * v_p * v_p);
2018 if (compute_moment) {
2019 dMuv =
static_cast<float>(-0.25 * v_p * v_p * ((2 * u_p) - 1));
2021 dMv2 =
static_cast<float>((-1.0 / 3.) * v_p * v_p * v_p);
2028 dS =
static_cast<float>(-v_p + 0.5);
2029 dMu =
static_cast<float>((0.5 * u_p * (u_p - 1)) + (1.0 / 6.0));
2030 dMv =
static_cast<float>(-((0.5 * v_p * (v_p - 1)) + (1.0 / 6.0)));
2031 if (compute_moment) {
2032 float half_u_p =
static_cast<float>(0.5 * u_p);
2033 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);
2034 dMu2 =
static_cast<float>(((1. / 3.) * u_p * (((u_p * u_p) - (1.5 * u_p)) + 1.)) - (1. / 12.0));
2035 dMv2 =
static_cast<float>(((-1. / 3.) * v_p * (((v_p * v_p) - (1.5 * v_p)) + 1.)) - (1. / 12.0));
2042 dMu =
static_cast<float>(0.5 * u_p * u_p);
2044 if (compute_moment) {
2046 dMu2 =
static_cast<float>((1.0 / 3.) * u_p * u_p * u_p);
2054 dS =
static_cast<float>(v_p - 0.5);
2055 dMu =
static_cast<float>((0.5 * u_p * (u_p + 1)) + (1.0 / 6.0));
2056 dMv =
static_cast<float>((0.5 * v_p * (v_p - 1)) + (1.0 / 6.0));
2057 if (compute_moment) {
2058 float half_u_p =
static_cast<float>(0.5 * u_p);
2059 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);
2060 dMu2 =
static_cast<float>(((1. / 3.) * u_p * ((u_p * u_p) + (1.5 * u_p) + 1.)) + (1. / 12.0));
2061 dMv2 =
static_cast<float>(((1. / 3.) * v_p * (((v_p * v_p) - (1.5 * v_p)) + 1.)) - (1. / 12.0));
2066 std::cout <<
"to complete the default" << std::endl;
2083 void vpDot2::updateFreemanPosition(
unsigned int &u,
unsigned int &v,
const unsigned int &dir)
2115 std::cout <<
"In vpDot2::updateFreemanPosition dir not identified" << std::endl;
2147 double u = ip.
get_u();
2148 double v = ip.
get_v();
2150 if ((u < 0) || (u >= w)) {
2153 if ((v < 0) || (v >= h)) {
2170 bool vpDot2::isInArea(
const unsigned int &u,
const unsigned int &v)
const
2172 unsigned int area_u_min =
static_cast<unsigned int>(area.
getLeft());
2173 unsigned int area_u_max =
static_cast<unsigned int>(area.
getRight());
2174 unsigned int area_v_min =
static_cast<unsigned int>(area.
getTop());
2175 unsigned int area_v_max =
static_cast<unsigned int>(area.
getBottom());
2177 if ((u < area_u_min) || (u > area_u_max)) {
2180 if ((v < area_v_min) || (v > area_v_max)) {
2197 void vpDot2::getGridSize(
unsigned int &gridWidth,
unsigned int &gridHeight)
2207 if (gridWidth == 0) {
2210 if (gridHeight == 0) {
2229 int cog_u =
static_cast<int>(cog.
get_u());
2230 int cog_v =
static_cast<int>(cog.
get_v());
2232 unsigned int sum_value = 0;
2233 unsigned int nb_pixels = 0;
2235 for (
unsigned int i =
static_cast<unsigned int>(this->bbox_u_min); i <= static_cast<unsigned int>(this->bbox_u_max); ++i) {
2236 unsigned int pixel_gray =
static_cast<unsigned int>(I[
static_cast<unsigned int>(cog_v)][i]);
2238 sum_value += pixel_gray;
2242 for (
unsigned int i =
static_cast<unsigned int>(this->bbox_v_min); i <= static_cast<unsigned int>(this->bbox_v_max); ++i) {
2243 unsigned char pixel_gray = I[i][
static_cast<unsigned int>(cog_u)];
2245 sum_value += pixel_gray;
2249 if (nb_pixels < 10) {
2252 if ((cog_u - bbox_u_min) >(cog_v - bbox_v_min)) {
2253 imin = cog_v - bbox_v_min;
2256 imin = cog_u - bbox_u_min;
2258 if ((bbox_u_max - cog_u) > (bbox_v_max - cog_v)) {
2259 imax = bbox_v_max - cog_v;
2262 imax = bbox_u_max - cog_u;
2264 for (
int i = -imin; i <= imax; ++i) {
2265 unsigned int pixel_gray =
static_cast<unsigned int>(I[
static_cast<unsigned int>(cog_v + i)][
static_cast<unsigned int>(cog_u + i)]);
2267 sum_value += pixel_gray;
2272 if ((cog_u - bbox_u_min) > (bbox_v_max - cog_v)) {
2273 imin = bbox_v_max - cog_v;
2276 imin = cog_u - bbox_u_min;
2278 if ((bbox_u_max - cog_u) > (cog_v - bbox_v_min)) {
2279 imax = cog_v - bbox_v_min;
2282 imax = bbox_u_max - cog_u;
2285 for (
int i = -imin; i <= imax; ++i) {
2286 unsigned char pixel_gray = I[
static_cast<unsigned int>(cog_v - i)][
static_cast<unsigned int>(cog_u + i)];
2288 sum_value += pixel_gray;
2294 if (nb_pixels == 0) {
2299 mean_gray_level = sum_value / nb_pixels;
2330 std::cout << Cogs.
getRows() <<
" dots loaded from file " << dotFile << std::endl;
2335 std::cout <<
"Dot file has a wrong number of dots : redefining them" << std::endl;
2342 for (i = 0; i < n; ++i) {
2343 cog.
set_uv(Cogs[i][0], Cogs[i][1]);
2354 std::cout <<
"Cannot track dots from file" << std::endl;
2360 for (i = 0; ((i < n) && fromFile); ++i) {
2362 for (
unsigned int j = 0; ((j < n) && fromFile); ++j) {
2366 std::cout <<
"Dots from file seem incoherent" << std::endl;
2377 std::cout <<
"Click on the " << n <<
" dots clockwise starting from upper/left dot..." << std::endl;
2378 for (i = 0; i < n; ++i) {
2388 Cogs[i][0] = cog.
get_u();
2389 Cogs[i][1] = cog.
get_v();
2395 if ((!fromFile) && (dotFile !=
"")) {
2397 std::cout << Cogs.
getRows() <<
" dots written to file " << dotFile << std::endl;
2401 for (i = 0; i < n; ++i) {
2425 std::vector<vpImagePoint> &cogs,
vpImagePoint *cogStar)
2429 for (i = 0; i < n; ++i) {
2431 cogs.push_back(dot[i].
getCog());
2434 unsigned int cogs_size = cogs.size();
2435 for (i = n; i < cogs_size; ++i) {
2439 for (i = 0; i < n; ++i) {
2443 if (cogStar !=
nullptr) {
2444 for (i = 0; i < n; ++i) {
2467 const std::list<vpImagePoint> &edges_list,
vpColor color,
unsigned int thickness)
2470 std::list<vpImagePoint>::const_iterator it;
2472 std::list<vpImagePoint>::const_iterator edges_list_end = edges_list.end();
2473 for (it = edges_list.begin(); it != edges_list_end; ++it) {
2493 vpColor color,
unsigned int thickness)
2496 std::list<vpImagePoint>::const_iterator it;
2497 std::list<vpImagePoint>::const_iterator edges_list_end = edges_list.end();
2498 for (it = edges_list.begin(); it != edges_list_end; ++it) {
2508 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)
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 setMaxSizeSearchDistPrecision(const double &maxSizeSearchDistancePrecision)
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 getMaxSizeSearchDistPrecision() 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.