47 #include <visp3/core/vpDisplay.h>
50 #include <visp3/core/vpIoTools.h>
51 #include <visp3/core/vpMath.h>
52 #include <visp3/core/vpTrackingException.h>
58 #include <visp3/blob/vpDot2.h>
81 grayLevelPrecision = 0.80;
85 ellipsoidShapePrecision = 0.65;
86 maxSizeSearchDistancePrecision = 0.65;
91 bbox_u_min = bbox_u_max = bbox_v_min = bbox_v_max = 0;
96 compute_moment =
false;
105 : m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(), width(0), height(0),
106 surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0), grayLevelPrecision(0.8), gamma(1.5),
107 sizePrecision(0.65), ellipsoidShapePrecision(0.65), maxSizeSearchDistancePrecision(0.65),
108 allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(), compute_moment(false), graphics(false),
109 thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0), firstBorder_u(0), firstBorder_v()
122 : m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(ip), width(0), height(0),
123 surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0), grayLevelPrecision(0.8), gamma(1.5),
124 sizePrecision(0.65), ellipsoidShapePrecision(0.65), maxSizeSearchDistancePrecision(0.65),
125 allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(), compute_moment(false), graphics(false),
126 thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0), firstBorder_u(0), firstBorder_v()
134 :
vpTracker(twinDot), m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(),
135 width(0), height(0), surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0),
136 grayLevelPrecision(0.8), gamma(1.5), sizePrecision(0.65), ellipsoidShapePrecision(0.65),
137 maxSizeSearchDistancePrecision(0.65), allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(),
138 compute_moment(false), graphics(false), thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0),
139 firstBorder_u(0), firstBorder_v()
151 width = twinDot.width;
152 height = twinDot.height;
153 surface = twinDot.surface;
154 gray_level_min = twinDot.gray_level_min;
155 gray_level_max = twinDot.gray_level_max;
156 mean_gray_level = twinDot.mean_gray_level;
157 grayLevelPrecision = twinDot.grayLevelPrecision;
158 gamma = twinDot.gamma;
160 sizePrecision = twinDot.sizePrecision;
161 ellipsoidShapePrecision = twinDot.ellipsoidShapePrecision;
162 maxSizeSearchDistancePrecision = twinDot.maxSizeSearchDistancePrecision;
163 allowedBadPointsPercentage_ = twinDot.allowedBadPointsPercentage_;
166 direction_list = twinDot.direction_list;
167 ip_edges_list = twinDot.ip_edges_list;
169 compute_moment = twinDot.compute_moment;
170 graphics = twinDot.graphics;
171 thickness = twinDot.thickness;
173 bbox_u_min = twinDot.bbox_u_min;
174 bbox_u_max = twinDot.bbox_u_max;
175 bbox_v_min = twinDot.bbox_v_min;
176 bbox_v_max = twinDot.bbox_v_max;
178 firstBorder_u = twinDot.firstBorder_u;
179 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 = (
unsigned int)cog.
get_i();
259 unsigned int j = (
unsigned int)cog.
get_j();
261 double Ip = pow((
double)I[i][j] / 255, 1 / gamma);
263 if (Ip - (1 - grayLevelPrecision) < 0) {
266 gray_level_min = (
unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
267 if (gray_level_min > 255)
268 gray_level_min = 255;
270 gray_level_max = (
unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
271 if (gray_level_max > 255)
272 gray_level_max = 255;
316 unsigned int i = (
unsigned int)cog.
get_i();
317 unsigned int j = (
unsigned int)cog.
get_j();
319 double Ip = pow((
double)I[i][j] / 255, 1 / gamma);
321 if (Ip - (1 - grayLevelPrecision) < 0) {
324 gray_level_min = (
unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
325 if (gray_level_min > 255)
326 gray_level_min = 255;
328 gray_level_max = (
unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
329 if (gray_level_max > 255)
330 gray_level_max = 255;
383 unsigned int gray_lvl_max,
unsigned int size)
387 this->gray_level_min = gray_lvl_min;
388 this->gray_level_max = gray_lvl_max;
461 bool found = computeParameters(I, cog.
get_u(), cog.
get_v());
465 found = isValid(I, wantedDot);
484 double searchWindowWidth = 0.0, searchWindowHeight = 0.0;
486 if (std::fabs(
getWidth()) <= std::numeric_limits<double>::epsilon() ||
487 std::fabs(
getHeight()) <= std::numeric_limits<double>::epsilon()) {
488 searchWindowWidth = 80.;
489 searchWindowHeight = 80.;
490 }
else if (canMakeTheWindowGrow) {
498 std::list<vpDot2> candidates;
500 (
int)(this->cog.get_v() - searchWindowHeight / 2.0), (
unsigned int)searchWindowWidth,
501 (
unsigned int)searchWindowHeight, candidates);
505 if (candidates.empty()) {
511 vpDot2 movingDot = candidates.front();
527 bbox_u_min = movingDot.bbox_u_min;
528 bbox_u_max = movingDot.bbox_u_max;
529 bbox_v_min = movingDot.bbox_v_min;
530 bbox_v_max = movingDot.bbox_v_max;
555 "The center of gravity of the dot is not in the image"));
567 if (Ip - (1 - grayLevelPrecision) < 0) {
570 gray_level_min = (
unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
571 if (gray_level_min > 255)
572 gray_level_min = 255;
574 gray_level_max = (
unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
575 if (gray_level_max > 255)
576 gray_level_max = 255;
611 track(I, canMakeTheWindowGrow);
677 double diff_u = this->cog.
get_u() - cogDistantDot.
get_u();
678 double diff_v = this->cog.
get_v() - cogDistantDot.
get_v();
679 return sqrt(diff_u * diff_u + diff_v * diff_v);
738 double epsilon = 0.05;
739 if (grayLevelPrecision < epsilon) {
740 this->grayLevelPrecision = epsilon;
741 }
else if (grayLevelPrecision > 1) {
742 this->grayLevelPrecision = 1.0;
744 this->grayLevelPrecision = precision;
766 if (sizePrecision < 0) {
767 this->sizePrecision = 0;
768 }
else if (sizePrecision > 1) {
769 this->sizePrecision = 1.0;
771 this->sizePrecision = precision;
810 if (ellipsoidShapePrecision < 0) {
811 this->ellipsoidShapePrecision = 0;
812 }
else if (ellipsoidShapePrecision > 1) {
813 this->ellipsoidShapePrecision = 1.0;
815 this->ellipsoidShapePrecision = precision;
836 double epsilon = 0.05;
837 if (maxSizeSearchDistancePrecision < epsilon) {
838 this->maxSizeSearchDistancePrecision = epsilon;
839 }
else if (maxSizeSearchDistancePrecision > 1) {
840 this->maxSizeSearchDistancePrecision = 1.0;
842 this->maxSizeSearchDistancePrecision = precision;
870 unsigned int image_w = I.
getWidth();
876 else if (u >= (
int)image_w)
877 u = (int)image_w - 1;
880 else if (v >= (
int)image_h)
881 v = (
int)image_h - 1;
883 if (((
unsigned int)u + w) > image_w)
884 w = image_w - (
unsigned int)u - 1;
885 if (((
unsigned int)v + h) > image_h)
886 h = image_h - (
unsigned int)v - 1;
981 unsigned int area_h, std::list<vpDot2> &niceDots)
989 setArea(I, area_u, area_v, area_w, area_h);
992 unsigned int gridWidth;
993 unsigned int gridHeight;
994 getGridSize(gridWidth, gridHeight);
1009 std::list<vpDot2> badDotsVector;
1010 std::list<vpDot2>::iterator itnice;
1011 std::list<vpDot2>::iterator itbad;
1013 vpDot2 *dotToTest = NULL;
1016 unsigned int area_u_min = (
unsigned int)area.
getLeft();
1017 unsigned int area_u_max = (
unsigned int)area.
getRight();
1018 unsigned int area_v_min = (
unsigned int)area.
getTop();
1019 unsigned int area_v_max = (
unsigned int)area.
getBottom();
1024 for (v = area_v_min; v < area_v_max; v = v + gridHeight) {
1025 for (u = area_u_min; u < area_u_max; u = u + gridWidth) {
1029 if (!hasGoodLevel(I, u, v))
1034 bool good_germ =
true;
1036 itnice = niceDots.begin();
1037 while (itnice != niceDots.end() && good_germ ==
true) {
1040 cogTmpDot = tmpDot.
getCog();
1041 double u0 = cogTmpDot.
get_u();
1042 double v0 = cogTmpDot.
get_v();
1043 double half_w = tmpDot.
getWidth() / 2.;
1044 double half_h = tmpDot.
getHeight() / 2.;
1046 if (u >= (u0 - half_w) && u <= (u0 + half_w) && v >= (v0 - half_h) && v <= (v0 + half_h)) {
1057 unsigned int border_u;
1058 unsigned int border_v;
1059 if (findFirstBorder(I, u, v, border_u, border_v) ==
false) {
1068 itbad = badDotsVector.begin();
1069 #define vpBAD_DOT_VALUE (*itbad)
1072 while (itbad != badDotsVector.end() && good_germ ==
true) {
1073 if ((
double)u >= vpBAD_DOT_VALUE.bbox_u_min && (double)u <= vpBAD_DOT_VALUE.bbox_u_max &&
1074 (
double)v >= vpBAD_DOT_VALUE.bbox_v_min && (double)v <= vpBAD_DOT_VALUE.bbox_v_max) {
1075 std::list<vpImagePoint>::const_iterator it_edges = ip_edges_list.begin();
1076 while (it_edges != ip_edges_list.end() && good_germ ==
true) {
1080 cogBadDot = *it_edges;
1082 if ((std::fabs(border_u - cogBadDot.
get_u()) <=
1084 std::numeric_limits<double>::epsilon()) &&
1085 (std::fabs(v - cogBadDot.
get_v()) <=
1087 std::numeric_limits<double>::epsilon())) {
1095 #undef vpBAD_DOT_VALUE
1105 vpTRACE(4,
"Try germ (%d, %d)", u, v);
1113 if (dotToTest != NULL)
1115 dotToTest = getInstance();
1131 if (dotToTest->computeParameters(I) ==
false) {
1139 if (dotToTest->isValid(I, *
this)) {
1146 double area_center_u = area_u + area_w / 2.0 - 0.5;
1147 double area_center_v = area_v + area_h / 2.0 - 0.5;
1149 double thisDiff_u = cogDotToTest.
get_u() - area_center_u;
1150 double thisDiff_v = cogDotToTest.
get_v() - area_center_v;
1151 double thisDist = sqrt(thisDiff_u * thisDiff_u + thisDiff_v * thisDiff_v);
1153 bool stopLoop =
false;
1154 itnice = niceDots.begin();
1156 while (itnice != niceDots.end() && stopLoop ==
false) {
1160 double epsilon = 3.0;
1163 cogTmpDot = tmpDot.
getCog();
1165 if (fabs(cogTmpDot.
get_u() - cogDotToTest.
get_u()) < epsilon &&
1166 fabs(cogTmpDot.
get_v() - cogDotToTest.
get_v()) < epsilon) {
1175 double otherDiff_u = cogTmpDot.
get_u() - area_center_u;
1176 double otherDiff_v = cogTmpDot.
get_v() - area_center_v;
1177 double otherDist = sqrt(otherDiff_u * otherDiff_u + otherDiff_v * otherDiff_v);
1182 if (otherDist > thisDist) {
1183 niceDots.insert(itnice, *dotToTest);
1194 vpTRACE(4,
"End while (%d, %d)", u, v);
1198 if (itnice == niceDots.end() && stopLoop ==
false) {
1199 niceDots.push_back(*dotToTest);
1203 badDotsVector.push_front(*dotToTest);
1207 if (dotToTest != NULL)
1243 if ((std::fabs(wantedDot.
getWidth()) > std::numeric_limits<double>::epsilon()) &&
1244 (std::fabs(wantedDot.
getHeight()) > std::numeric_limits<double>::epsilon()) &&
1245 (std::fabs(wantedDot.
getArea()) > std::numeric_limits<double>::epsilon()))
1248 if (std::fabs(size_precision) > std::numeric_limits<double>::epsilon()) {
1249 double epsilon = 0.001;
1251 std::cout <<
"test size precision......................\n";
1252 std::cout <<
"wanted dot: "
1254 <<
" precision=" << size_precision <<
" epsilon=" << epsilon << std::endl;
1255 std::cout <<
"dot found: "
1259 if ((wantedDot.
getWidth() * size_precision - epsilon <
getWidth()) ==
false) {
1262 printf(
"Bad width > for dot (%g, %g)\n", cog.
get_u(), cog.
get_v());
1267 if ((
getWidth() < wantedDot.
getWidth() / (size_precision + epsilon)) ==
false) {
1270 printf(
"Bad width %g > %g for dot (%g, %g)\n",
getWidth(), wantedDot.
getWidth() / (size_precision + epsilon),
1279 printf(
"Bad height %g > %g for dot (%g, %g)\n", wantedDot.
getHeight() * size_precision - epsilon,
getHeight(),
1288 printf(
"Bad height %g > %g for dot (%g, %g)\n",
getHeight(), wantedDot.
getHeight() / (size_precision + epsilon),
1294 if ((wantedDot.
getArea() * (size_precision * size_precision) - epsilon <
getArea()) ==
false) {
1297 printf(
"Bad surface %g > %g for dot (%g, %g)\n",
1303 if ((
getArea() < wantedDot.
getArea() / (size_precision * size_precision + epsilon)) ==
false) {
1306 printf(
"Bad surface %g < %g for dot (%g, %g)\n",
getArea(),
1307 wantedDot.
getArea() / (size_precision * size_precision + epsilon), cog.
get_u(), cog.
get_v());
1318 int nb_point_to_test = 20;
1319 int nb_bad_points = 0;
1320 int nb_max_bad_points = (int)(nb_point_to_test * allowedBadPointsPercentage_);
1321 double step_angle = 2 * M_PI / nb_point_to_test;
1324 if (std::fabs(ellipsoidShape_precision) > std::numeric_limits<double>::epsilon() && compute_moment) {
1341 double Sqrt = sqrt(tmp1 * tmp1 + 4 * tmp2 * tmp2);
1351 double innerCoef = ellipsoidShape_precision;
1353 double cog_u = this->cog.
get_u();
1354 double cog_v = this->cog.
get_v();
1358 for (
double theta = 0.; theta < 2 * M_PI; theta += step_angle) {
1359 u = (
unsigned int)(cog_u + innerCoef * (a1 * cos(alpha) * cos(theta) - a2 * sin(alpha) * sin(theta)));
1360 v = (
unsigned int)(cog_v + innerCoef * (a1 * sin(alpha) * cos(theta) + a2 * cos(alpha) * sin(theta)));
1361 if (!this->hasGoodLevel(I, u, v)) {
1365 printf(
"Inner circle pixel (%u, %u) has bad level for dot (%g, %g): "
1366 "%d not in [%u, %u]\n",
1367 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1373 for (
unsigned int t = 0; t < thickness; t++) {
1384 if (nb_bad_points > nb_max_bad_points) {
1386 printf(
"Inner ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1395 double outCoef = 2 - ellipsoidShape_precision;
1397 for (
double theta = 0.; theta < 2 * M_PI; theta += step_angle) {
1398 u = (
unsigned int)(cog_u + outCoef * (a1 * cos(alpha) * cos(theta) - a2 * sin(alpha) * sin(theta)));
1399 v = (
unsigned int)(cog_v + outCoef * (a1 * sin(alpha) * cos(theta) + a2 * cos(alpha) * sin(theta)));
1410 if (!this->hasReverseLevel(I, u, v)) {
1414 printf(
"Outside circle pixel (%u, %u) has bad level for dot (%g, "
1415 "%g): %d not in [%u, %u]\n",
1416 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1422 for (
unsigned int t = 0; t < thickness; t++) {
1431 if (nb_bad_points > nb_max_bad_points) {
1433 printf(
"Outside ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1459 bool vpDot2::hasGoodLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1461 if (!isInArea(u, v))
1464 if (I[v][u] >= gray_level_min && I[v][u] <= gray_level_max) {
1483 bool vpDot2::hasReverseLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1486 if (!isInArea(u, v))
1489 if (I[v][u] < gray_level_min || I[v][u] > gray_level_max) {
1562 direction_list.clear();
1563 ip_edges_list.clear();
1570 if (std::fabs(est_u + 1.0) <=
vpMath::maximum(std::fabs(est_u), 1.) * std::numeric_limits<double>::epsilon()) {
1571 est_u = this->cog.
get_u();
1576 if (std::fabs(est_v + 1.0) <=
vpMath::maximum(std::fabs(est_v), 1.) * std::numeric_limits<double>::epsilon()) {
1577 est_v = this->cog.
get_v();
1582 if (!isInArea((
unsigned int)est_u, (
unsigned int)est_v)) {
1584 "Initial pixel coordinates (%d, %d) for dot tracking are "
1586 (
int)est_u, (
int)est_v);
1597 if (!hasGoodLevel(I, (
unsigned int)est_u, (
unsigned int)est_v)) {
1598 vpDEBUG_TRACE(3,
"Can't find a dot from pixel (%d, %d) coordinates", (
int)est_u, (
int)est_v);
1604 if (!findFirstBorder(I, (
unsigned int)est_u, (
unsigned int)est_v, this->firstBorder_u, this->firstBorder_v)) {
1606 vpDEBUG_TRACE(3,
"Can't find first border (%d, %d) coordinates", (
int)est_u, (
int)est_v);
1610 unsigned int dir = 6;
1613 computeFreemanChainElement(I, this->firstBorder_u, this->firstBorder_v, dir);
1614 unsigned int firstDir = dir;
1617 if (!isInArea(this->firstBorder_u, this->firstBorder_v)) {
1618 vpDEBUG_TRACE(3,
"Border pixel coordinates (%d, %d) of the dot are not in the area", this->firstBorder_u,
1619 this->firstBorder_v);
1624 direction_list.push_back(dir);
1626 ip.
set_u(this->firstBorder_u);
1627 ip.
set_v(this->firstBorder_v);
1629 ip_edges_list.push_back(ip);
1631 int border_u = (int)this->firstBorder_u;
1632 int border_v = (int)this->firstBorder_v;
1638 float dS, dMu, dMv, dMuv, dMu2, dMv2;
1649 for (
int t = 0; t < (int)thickness; t++) {
1650 ip.
set_u(border_u + t);
1662 computeFreemanParameters(border_u, border_v, dir, du, dv,
1673 if (compute_moment) {
1679 if (!isInArea((
unsigned int)border_u, (
unsigned int)border_v)) {
1681 vpDEBUG_TRACE(3,
"Dot (%d, %d) is not in the area", border_u, border_v);
1688 direction_list.push_back(dir);
1692 ip_edges_list.push_back(ip);
1697 if (border_v < bbox_v_min)
1698 bbox_v_min = border_v;
1699 if (border_v > bbox_v_max)
1700 bbox_v_max = border_v;
1701 if (border_u < bbox_u_min)
1702 bbox_u_min = border_u;
1703 if (border_u > bbox_u_max)
1704 bbox_u_max = border_u;
1707 if (computeFreemanChainElement(I, (
unsigned int)border_u, (
unsigned int)border_v, dir) ==
false) {
1708 vpDEBUG_TRACE(3,
"Can't compute Freeman chain for dot (%d, %d)", border_u, border_v);
1715 }
while ((getFirstBorder_u() != (
unsigned int)border_u || getFirstBorder_v() != (
unsigned int)border_v ||
1717 isInArea((
unsigned int)border_u, (
unsigned int)border_v));
1720 #if VP_DEBUG_MODE == 3
1728 if (std::fabs(
m00) <= std::numeric_limits<double>::epsilon() ||
1729 std::fabs(
m00 - 1.) <=
vpMath::maximum(std::fabs(
m00), 1.) * std::numeric_limits<double>::epsilon()) {
1730 vpDEBUG_TRACE(3,
"The center of gravity of the dot wasn't properly detected");
1735 double tmpCenter_u =
m10 /
m00;
1736 double tmpCenter_v =
m01 /
m00;
1739 if (compute_moment) {
1753 cog.
set_u(tmpCenter_u);
1754 cog.
set_v(tmpCenter_v);
1757 width = bbox_u_max - bbox_u_min + 1;
1758 height = bbox_v_max - bbox_v_min + 1;
1761 computeMeanGrayLevel(I);
1780 bool vpDot2::findFirstBorder(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1781 unsigned int &border_u,
unsigned int &border_v)
1791 double epsilon = 0.001;
1794 std::cout <<
"gray level: " << gray_level_min <<
" " << gray_level_max << std::endl;
1796 while (hasGoodLevel(I, border_u + 1, border_v) && border_u < area.
getRight() ) {
1802 "The found dot (%d, %d, %d) has a greater width than the "
1835 bool vpDot2::computeFreemanChainElement(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1836 unsigned int &element)
1839 if (hasGoodLevel(I, u, v)) {
1840 unsigned int _u = u;
1841 unsigned int _v = v;
1843 updateFreemanPosition(_u, _v, (element + 2) % 8);
1844 if (hasGoodLevel(I, _u, _v)) {
1845 element = (element + 2) % 8;
1847 unsigned int _u1 = u;
1848 unsigned int _v1 = v;
1849 updateFreemanPosition(_u1, _v1, (element + 1) % 8);
1851 if (hasGoodLevel(I, _u1, _v1)) {
1852 element = (element + 1) % 8;
1854 unsigned int _u2 = u;
1855 unsigned int _v2 = v;
1856 updateFreemanPosition(_u2, _v2, element);
1858 if (hasGoodLevel(I, _u2, _v2)) {
1861 unsigned int _u3 = u;
1862 unsigned int _v3 = v;
1863 updateFreemanPosition(_u3, _v3, (element + 7) % 8);
1865 if (hasGoodLevel(I, _u3, _v3)) {
1866 element = (element + 7) % 8;
1868 unsigned int _u4 = u;
1869 unsigned int _v4 = v;
1870 updateFreemanPosition(_u4, _v4, (element + 6) % 8);
1872 if (hasGoodLevel(I, _u4, _v4)) {
1873 element = (element + 6) % 8;
1875 unsigned int _u5 = u;
1876 unsigned int _v5 = v;
1877 updateFreemanPosition(_u5, _v5, (element + 5) % 8);
1879 if (hasGoodLevel(I, _u5, _v5)) {
1880 element = (element + 5) % 8;
1882 unsigned int _u6 = u;
1883 unsigned int _v6 = v;
1884 updateFreemanPosition(_u6, _v6, (element + 4) % 8);
1886 if (hasGoodLevel(I, _u6, _v6)) {
1887 element = (element + 4) % 8;
1889 unsigned int _u7 = u;
1890 unsigned int _v7 = v;
1891 updateFreemanPosition(_u7, _v7, (element + 3) % 8);
1893 if (hasGoodLevel(I, _u7, _v7)) {
1894 element = (element + 3) % 8;
1947 void vpDot2::computeFreemanParameters(
const int &u_p,
const int &v_p,
unsigned int &element,
int &du,
int &dv,
1948 float &dS,
float &dMu,
float &dMv,
float &dMuv,
float &dMu2,
float &dMv2)
1970 dMv = (float)(0.5 * v_p * v_p);
1971 if (compute_moment) {
1972 dMuv = (float)(0.25 * v_p * v_p * (2 * u_p + 1));
1974 dMv2 = (float)(1.0 / 3. * v_p * v_p * v_p);
1981 dS = (float)(v_p + 0.5);
1982 dMu = -(float)(0.5 * u_p * (u_p + 1) + 1.0 / 6.0);
1983 dMv = (float)(0.5 * v_p * (v_p + 1) + 1.0 / 6.0);
1984 if (compute_moment) {
1985 float half_u_p = (float)(0.5 * u_p);
1986 dMuv = (float)(v_p * v_p * (0.25 + half_u_p) + v_p * (1. / 3. + half_u_p) + 1. / 6. * u_p + 0.125);
1987 dMu2 = (float)(-1. / 3. * u_p * (u_p * u_p + 1.5 * u_p + 1.) - 1. / 12.0);
1988 dMv2 = (float)(1. / 3. * v_p * (v_p * v_p + 1.5 * v_p + 1.) + 1. / 12.0);
1995 dMu = (float)(-0.5 * u_p * u_p);
1997 if (compute_moment) {
1999 dMu2 = (float)(-1.0 / 3. * u_p * u_p * u_p);
2007 dS = (float)(-v_p - 0.5);
2008 dMu = -(float)(0.5 * u_p * (u_p - 1) + 1.0 / 6.0);
2009 dMv = -(float)(0.5 * v_p * (v_p + 1) + 1.0 / 6.0);
2010 if (compute_moment) {
2011 float half_u_p = (float)(0.5 * u_p);
2012 dMuv = (float)(v_p * v_p * (0.25 - half_u_p) + v_p * (1. / 3. - half_u_p) - 1. / 6. * u_p + 0.125);
2013 dMu2 = (float)(-1. / 3. * u_p * (u_p * u_p - 1.5 * u_p + 1.) - 1. / 12.0);
2014 dMv2 = (float)(-1. / 3. * v_p * (v_p * v_p + 1.5 * v_p + 1.) - 1. / 12.0);
2021 dMv = (float)(-0.5 * v_p * v_p);
2023 if (compute_moment) {
2024 dMuv = (float)(-0.25 * v_p * v_p * (2 * u_p - 1));
2026 dMv2 = (float)(-1.0 / 3. * v_p * v_p * v_p);
2033 dS = (float)(-v_p + 0.5);
2034 dMu = (float)(0.5 * u_p * (u_p - 1) + 1.0 / 6.0);
2035 dMv = (float)(-(0.5 * v_p * (v_p - 1) + 1.0 / 6.0));
2036 if (compute_moment) {
2037 float half_u_p = (float)(0.5 * u_p);
2038 dMuv = (float)(v_p * v_p * (0.25 - half_u_p) - v_p * (1. / 3. - half_u_p) - 1. / 6. * u_p + 0.125);
2039 dMu2 = (float)(1. / 3. * u_p * (u_p * u_p - 1.5 * u_p + 1.) - 1. / 12.0);
2040 dMv2 = (float)(-1. / 3. * v_p * (v_p * v_p - 1.5 * v_p + 1.) - 1. / 12.0);
2047 dMu = (float)(0.5 * u_p * u_p);
2049 if (compute_moment) {
2051 dMu2 = (float)(1.0 / 3. * u_p * u_p * u_p);
2059 dS = (float)(v_p - 0.5);
2060 dMu = (float)(0.5 * u_p * (u_p + 1) + 1.0 / 6.0);
2061 dMv = (float)(0.5 * v_p * (v_p - 1) + 1.0 / 6.0);
2062 if (compute_moment) {
2063 float half_u_p = (float)(0.5 * u_p);
2064 dMuv = (float)(v_p * v_p * (0.25 + half_u_p) - v_p * (1. / 3. + half_u_p) + 1. / 6. * u_p + 0.125);
2065 dMu2 = (float)(1. / 3. * u_p * (u_p * u_p + 1.5 * u_p + 1.) + 1. / 12.0);
2066 dMv2 = (float)(1. / 3. * v_p * (v_p * v_p - 1.5 * v_p + 1.) - 1. / 12.0);
2085 void vpDot2::updateFreemanPosition(
unsigned int &u,
unsigned int &v,
const unsigned int &dir)
2147 double u = ip.
get_u();
2148 double v = ip.
get_v();
2150 if (u < 0 || u >= w)
2152 if (v < 0 || v >= h)
2168 bool vpDot2::isInArea(
const unsigned int &u,
const unsigned int &v)
const
2170 unsigned int area_u_min = (
unsigned int)area.
getLeft();
2171 unsigned int area_u_max = (
unsigned int)area.
getRight();
2172 unsigned int area_v_min = (
unsigned int)area.
getTop();
2173 unsigned int area_v_max = (
unsigned int)area.
getBottom();
2175 if (u < area_u_min || u > area_u_max)
2177 if (v < area_v_min || v > area_v_max)
2193 void vpDot2::getGridSize(
unsigned int &gridWidth,
unsigned int &gridHeight)
2205 if (gridHeight == 0)
2223 int cog_u = (int)cog.
get_u();
2224 int cog_v = (int)cog.
get_v();
2226 unsigned int sum_value = 0;
2227 unsigned int nb_pixels = 0;
2229 for (
unsigned int i = (
unsigned int)this->bbox_u_min; i <= (
unsigned int)this->bbox_u_max; i++) {
2230 unsigned int pixel_gray = (
unsigned int)I[(
unsigned int)cog_v][i];
2232 sum_value += pixel_gray;
2236 for (
unsigned int i = (
unsigned int)this->bbox_v_min; i <= (
unsigned int)this->bbox_v_max; i++) {
2237 unsigned char pixel_gray = I[i][(
unsigned int)cog_u];
2239 sum_value += pixel_gray;
2243 if (nb_pixels < 10) {
2246 if ((cog_u - bbox_u_min) > (cog_v - bbox_v_min)) {
2247 imin = cog_v - bbox_v_min;
2249 imin = cog_u - bbox_u_min;
2251 if ((bbox_u_max - cog_u) > (bbox_v_max - cog_v)) {
2252 imax = bbox_v_max - cog_v;
2254 imax = bbox_u_max - cog_u;
2256 for (
int i = -imin; i <= imax; i++) {
2257 unsigned int pixel_gray = (
unsigned int)I[(
unsigned int)(cog_v + i)][(
unsigned int)(cog_u + i)];
2259 sum_value += pixel_gray;
2264 if ((cog_u - bbox_u_min) > (bbox_v_max - cog_v)) {
2265 imin = bbox_v_max - cog_v;
2267 imin = cog_u - bbox_u_min;
2269 if ((bbox_u_max - cog_u) > (cog_v - bbox_v_min)) {
2270 imax = cog_v - bbox_v_min;
2272 imax = bbox_u_max - cog_u;
2275 for (
int i = -imin; i <= imax; i++) {
2276 unsigned char pixel_gray = I[(
unsigned int)(cog_v - i)][(
unsigned int)(cog_u + i)];
2278 sum_value += pixel_gray;
2284 if (nb_pixels == 0) {
2288 mean_gray_level = sum_value / nb_pixels;
2319 std::cout << Cogs.
getRows() <<
" dots loaded from file " << dotFile << std::endl;
2324 std::cout <<
"Dot file has a wrong number of dots : redefining them" << std::endl;
2331 for (i = 0; i < n; ++i) {
2332 cog.
set_uv(Cogs[i][0], Cogs[i][1]);
2342 std::cout <<
"Cannot track dots from file" << std::endl;
2348 for (i = 0; i < n && fromFile; ++i) {
2350 for (
unsigned int j = 0; j < n && fromFile; ++j)
2354 std::cout <<
"Dots from file seem incoherent" << std::endl;
2363 std::cout <<
"Click on the " << n <<
" dots clockwise starting from upper/left dot..." << std::endl;
2364 for (i = 0; i < n; i++) {
2373 Cogs[i][0] = cog.
get_u();
2374 Cogs[i][1] = cog.
get_v();
2380 if (!fromFile && (dotFile !=
"")) {
2382 std::cout << Cogs.
getRows() <<
" dots written to file " << dotFile << std::endl;
2386 for (i = 0; i < n; ++i)
2409 std::vector<vpImagePoint> &cogs,
vpImagePoint *cogStar)
2413 for (i = 0; i < n; ++i) {
2415 cogs.push_back(dot[i].
getCog());
2418 for (i = n; i < cogs.size(); ++i)
2421 for (i = 0; i < n; ++i)
2424 if (cogStar != NULL)
2425 for (i = 0; i < n; ++i) {
2447 const std::list<vpImagePoint> &edges_list,
vpColor color,
unsigned int thickness)
2450 std::list<vpImagePoint>::const_iterator it;
2452 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2472 vpColor color,
unsigned int thickness)
2475 std::list<vpImagePoint>::const_iterator it;
2477 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2487 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 functionnalities.
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 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)
static void displayCircle(const vpImage< unsigned char > &I, const vpImagePoint ¢er, unsigned int radius, 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
static void trackAndDisplay(vpDot2 dot[], const unsigned int &n, vpImage< unsigned char > &I, std::vector< vpImagePoint > &cogs, vpImagePoint *cogStar=NULL)
void track(const vpImage< unsigned char > &I, bool canMakeTheWindowGrow=true)
void setGraphics(bool activate)
void setMaxSizeSearchDistancePrecision(const double &maxSizeSearchDistancePrecision)
vpDot2 & operator=(const vpDot2 &twinDot)
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)
error that can be emited by ViSP classes.
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=NULL)
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 emited by the vpTracker class and its derivates.