46 #include <visp3/core/vpDisplay.h>
49 #include <visp3/core/vpIoTools.h>
50 #include <visp3/core/vpMath.h>
51 #include <visp3/core/vpTrackingException.h>
57 #include <visp3/blob/vpDot2.h>
80 grayLevelPrecision = 0.80;
84 ellipsoidShapePrecision = 0.65;
85 maxSizeSearchDistancePrecision = 0.65;
90 bbox_u_min = bbox_u_max = bbox_v_min = bbox_v_max = 0;
95 compute_moment =
false;
104 : m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(), width(0), height(0),
105 surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0), grayLevelPrecision(0.8), gamma(1.5),
106 sizePrecision(0.65), ellipsoidShapePrecision(0.65), maxSizeSearchDistancePrecision(0.65),
107 allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(), compute_moment(false), graphics(false),
108 thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0), firstBorder_u(0), firstBorder_v()
121 : m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(ip), width(0), height(0),
122 surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0), grayLevelPrecision(0.8), gamma(1.5),
123 sizePrecision(0.65), ellipsoidShapePrecision(0.65), maxSizeSearchDistancePrecision(0.65),
124 allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(), compute_moment(false), graphics(false),
125 thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0), firstBorder_u(0), firstBorder_v()
133 :
vpTracker(twinDot), m00(0.), m10(0.), m01(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), cog(),
134 width(0), height(0), surface(0), gray_level_min(128), gray_level_max(255), mean_gray_level(0),
135 grayLevelPrecision(0.8), gamma(1.5), sizePrecision(0.65), ellipsoidShapePrecision(0.65),
136 maxSizeSearchDistancePrecision(0.65), allowedBadPointsPercentage_(0.), area(), direction_list(), ip_edges_list(),
137 compute_moment(false), graphics(false), thickness(1), bbox_u_min(0), bbox_u_max(0), bbox_v_min(0), bbox_v_max(0),
138 firstBorder_u(0), firstBorder_v()
150 width = twinDot.width;
151 height = twinDot.height;
152 surface = twinDot.surface;
153 gray_level_min = twinDot.gray_level_min;
154 gray_level_max = twinDot.gray_level_max;
155 mean_gray_level = twinDot.mean_gray_level;
156 grayLevelPrecision = twinDot.grayLevelPrecision;
157 gamma = twinDot.gamma;
159 sizePrecision = twinDot.sizePrecision;
160 ellipsoidShapePrecision = twinDot.ellipsoidShapePrecision;
161 maxSizeSearchDistancePrecision = twinDot.maxSizeSearchDistancePrecision;
162 allowedBadPointsPercentage_ = twinDot.allowedBadPointsPercentage_;
165 direction_list = twinDot.direction_list;
166 ip_edges_list = twinDot.ip_edges_list;
168 compute_moment = twinDot.compute_moment;
169 graphics = twinDot.graphics;
170 thickness = twinDot.thickness;
172 bbox_u_min = twinDot.bbox_u_min;
173 bbox_u_max = twinDot.bbox_u_max;
174 bbox_v_min = twinDot.bbox_v_min;
175 bbox_v_max = twinDot.bbox_v_max;
177 firstBorder_u = twinDot.firstBorder_u;
178 firstBorder_v = twinDot.firstBorder_v;
214 std::list<vpImagePoint>::const_iterator it;
216 for (it = ip_edges_list.begin(); it != ip_edges_list.end(); ++it) {
257 unsigned int i = (
unsigned int)cog.
get_i();
258 unsigned int j = (
unsigned int)cog.
get_j();
260 double Ip = pow((
double)I[i][j] / 255, 1 / gamma);
262 if (Ip - (1 - grayLevelPrecision) < 0) {
265 gray_level_min = (
unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
266 if (gray_level_min > 255)
267 gray_level_min = 255;
269 gray_level_max = (
unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
270 if (gray_level_max > 255)
271 gray_level_max = 255;
315 unsigned int i = (
unsigned int)cog.
get_i();
316 unsigned int j = (
unsigned int)cog.
get_j();
318 double Ip = pow((
double)I[i][j] / 255, 1 / gamma);
320 if (Ip - (1 - grayLevelPrecision) < 0) {
323 gray_level_min = (
unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
324 if (gray_level_min > 255)
325 gray_level_min = 255;
327 gray_level_max = (
unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
328 if (gray_level_max > 255)
329 gray_level_max = 255;
382 unsigned int gray_lvl_max,
unsigned int size)
386 this->gray_level_min = gray_lvl_min;
387 this->gray_level_max = gray_lvl_max;
460 bool found = computeParameters(I, cog.
get_u(), cog.
get_v());
464 found = isValid(I, wantedDot);
483 double searchWindowWidth = 0.0, searchWindowHeight = 0.0;
485 if (std::fabs(
getWidth()) <= std::numeric_limits<double>::epsilon() ||
486 std::fabs(
getHeight()) <= std::numeric_limits<double>::epsilon()) {
487 searchWindowWidth = 80.;
488 searchWindowHeight = 80.;
489 }
else if (canMakeTheWindowGrow) {
497 std::list<vpDot2> candidates;
499 (
int)(this->cog.get_v() - searchWindowHeight / 2.0), (
unsigned int)searchWindowWidth,
500 (
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) {
551 gray_level_min = (
unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
552 if (gray_level_min > 255)
553 gray_level_min = 255;
555 gray_level_max = (
unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
556 if (gray_level_max > 255)
557 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;
722 }
else if (grayLevelPrecision > 1) {
723 this->grayLevelPrecision = 1.0;
725 this->grayLevelPrecision = precision;
747 if (sizePrecision < 0) {
748 this->sizePrecision = 0;
749 }
else if (sizePrecision > 1) {
750 this->sizePrecision = 1.0;
752 this->sizePrecision = precision;
791 if (ellipsoidShapePrecision < 0) {
792 this->ellipsoidShapePrecision = 0;
793 }
else if (ellipsoidShapePrecision > 1) {
794 this->ellipsoidShapePrecision = 1.0;
796 this->ellipsoidShapePrecision = precision;
817 double epsilon = 0.05;
818 if (maxSizeSearchDistancePrecision < epsilon) {
819 this->maxSizeSearchDistancePrecision = epsilon;
820 }
else if (maxSizeSearchDistancePrecision > 1) {
821 this->maxSizeSearchDistancePrecision = 1.0;
823 this->maxSizeSearchDistancePrecision = precision;
851 unsigned int image_w = I.
getWidth();
857 else if (u >= (
int)image_w)
858 u = (int)image_w - 1;
861 else if (v >= (
int)image_h)
862 v = (
int)image_h - 1;
864 if (((
unsigned int)u + w) > image_w)
865 w = image_w - (
unsigned int)u - 1;
866 if (((
unsigned int)v + h) > image_h)
867 h = image_h - (
unsigned int)v - 1;
962 unsigned int area_h, std::list<vpDot2> &niceDots)
970 setArea(I, area_u, area_v, area_w, area_h);
973 unsigned int gridWidth;
974 unsigned int gridHeight;
975 getGridSize(gridWidth, gridHeight);
990 std::list<vpDot2> badDotsVector;
991 std::list<vpDot2>::iterator itnice;
992 std::list<vpDot2>::iterator itbad;
997 unsigned int area_u_min = (
unsigned int)area.
getLeft();
998 unsigned int area_u_max = (
unsigned int)area.
getRight();
999 unsigned int area_v_min = (
unsigned int)area.
getTop();
1000 unsigned int area_v_max = (
unsigned int)area.
getBottom();
1005 for (v = area_v_min; v < area_v_max; v = v + gridHeight) {
1006 for (u = area_u_min; u < area_u_max; u = u + gridWidth) {
1010 if (!hasGoodLevel(I, u, v))
1015 bool good_germ =
true;
1017 itnice = niceDots.begin();
1018 while (itnice != niceDots.end() && good_germ ==
true) {
1021 cogTmpDot = tmpDot.
getCog();
1022 double u0 = cogTmpDot.
get_u();
1023 double v0 = cogTmpDot.
get_v();
1024 double half_w = tmpDot.
getWidth() / 2.;
1025 double half_h = tmpDot.
getHeight() / 2.;
1027 if (u >= (u0 - half_w) && u <= (u0 + half_w) && v >= (v0 - half_h) && v <= (v0 + half_h)) {
1038 unsigned int border_u;
1039 unsigned int border_v;
1040 if (findFirstBorder(I, u, v, border_u, border_v) ==
false) {
1049 itbad = badDotsVector.begin();
1050 #define vpBAD_DOT_VALUE (*itbad)
1053 while (itbad != badDotsVector.end() && good_germ ==
true) {
1054 if ((
double)u >= vpBAD_DOT_VALUE.bbox_u_min && (double)u <= vpBAD_DOT_VALUE.bbox_u_max &&
1055 (
double)v >= vpBAD_DOT_VALUE.bbox_v_min && (double)v <= vpBAD_DOT_VALUE.bbox_v_max) {
1056 std::list<vpImagePoint>::const_iterator it_edges = ip_edges_list.begin();
1057 while (it_edges != ip_edges_list.end() && good_germ ==
true) {
1061 cogBadDot = *it_edges;
1063 if ((std::fabs(border_u - cogBadDot.
get_u()) <=
1065 std::numeric_limits<double>::epsilon()) &&
1066 (std::fabs(v - cogBadDot.
get_v()) <=
1068 std::numeric_limits<double>::epsilon())) {
1076 #undef vpBAD_DOT_VALUE
1086 vpTRACE(4,
"Try germ (%d, %d)", u, v);
1094 if (dotToTest != NULL)
1096 dotToTest = getInstance();
1112 if (dotToTest->computeParameters(I) ==
false) {
1120 if (dotToTest->isValid(I, *
this)) {
1127 double area_center_u = area_u + area_w / 2.0 - 0.5;
1128 double area_center_v = area_v + area_h / 2.0 - 0.5;
1130 double thisDiff_u = cogDotToTest.
get_u() - area_center_u;
1131 double thisDiff_v = cogDotToTest.
get_v() - area_center_v;
1132 double thisDist = sqrt(thisDiff_u * thisDiff_u + thisDiff_v * thisDiff_v);
1134 bool stopLoop =
false;
1135 itnice = niceDots.begin();
1137 while (itnice != niceDots.end() && stopLoop ==
false) {
1141 double epsilon = 3.0;
1144 cogTmpDot = tmpDot.
getCog();
1146 if (fabs(cogTmpDot.
get_u() - cogDotToTest.
get_u()) < epsilon &&
1147 fabs(cogTmpDot.
get_v() - cogDotToTest.
get_v()) < epsilon) {
1156 double otherDiff_u = cogTmpDot.
get_u() - area_center_u;
1157 double otherDiff_v = cogTmpDot.
get_v() - area_center_v;
1158 double otherDist = sqrt(otherDiff_u * otherDiff_u + otherDiff_v * otherDiff_v);
1163 if (otherDist > thisDist) {
1164 niceDots.insert(itnice, *dotToTest);
1175 vpTRACE(4,
"End while (%d, %d)", u, v);
1179 if (itnice == niceDots.end() && stopLoop ==
false) {
1180 niceDots.push_back(*dotToTest);
1184 badDotsVector.push_front(*dotToTest);
1188 if (dotToTest != NULL)
1224 if ((std::fabs(wantedDot.
getWidth()) > std::numeric_limits<double>::epsilon()) &&
1225 (std::fabs(wantedDot.
getHeight()) > std::numeric_limits<double>::epsilon()) &&
1226 (std::fabs(wantedDot.
getArea()) > std::numeric_limits<double>::epsilon()))
1229 if (std::fabs(size_precision) > std::numeric_limits<double>::epsilon()) {
1230 double epsilon = 0.001;
1232 std::cout <<
"test size precision......................\n";
1233 std::cout <<
"wanted dot: "
1235 <<
" precision=" << size_precision <<
" epsilon=" << epsilon << std::endl;
1236 std::cout <<
"dot found: "
1240 if ((wantedDot.
getWidth() * size_precision - epsilon <
getWidth()) ==
false) {
1243 printf(
"Bad width > for dot (%g, %g)\n", cog.
get_u(), cog.
get_v());
1248 if ((
getWidth() < wantedDot.
getWidth() / (size_precision + epsilon)) ==
false) {
1251 printf(
"Bad width %g > %g for dot (%g, %g)\n",
getWidth(), wantedDot.
getWidth() / (size_precision + epsilon),
1260 printf(
"Bad height %g > %g for dot (%g, %g)\n", wantedDot.
getHeight() * size_precision - epsilon,
getHeight(),
1269 printf(
"Bad height %g > %g for dot (%g, %g)\n",
getHeight(), wantedDot.
getHeight() / (size_precision + epsilon),
1275 if ((wantedDot.
getArea() * (size_precision * size_precision) - epsilon <
getArea()) ==
false) {
1278 printf(
"Bad surface %g > %g for dot (%g, %g)\n",
1284 if ((
getArea() < wantedDot.
getArea() / (size_precision * size_precision + epsilon)) ==
false) {
1287 printf(
"Bad surface %g < %g for dot (%g, %g)\n",
getArea(),
1288 wantedDot.
getArea() / (size_precision * size_precision + epsilon), cog.
get_u(), cog.
get_v());
1299 int nb_point_to_test = 20;
1300 int nb_bad_points = 0;
1301 int nb_max_bad_points = (int)(nb_point_to_test * allowedBadPointsPercentage_);
1302 double step_angle = 2 * M_PI / nb_point_to_test;
1305 if (std::fabs(ellipsoidShape_precision) > std::numeric_limits<double>::epsilon() && compute_moment) {
1322 double Sqrt = sqrt(tmp1 * tmp1 + 4 * tmp2 * tmp2);
1332 double innerCoef = ellipsoidShape_precision;
1334 double cog_u = this->cog.
get_u();
1335 double cog_v = this->cog.
get_v();
1339 for (
double theta = 0.; theta < 2 * M_PI; theta += step_angle) {
1340 u = (
unsigned int)(cog_u + innerCoef * (a1 * cos(alpha) * cos(theta) - a2 * sin(alpha) * sin(theta)));
1341 v = (
unsigned int)(cog_v + innerCoef * (a1 * sin(alpha) * cos(theta) + a2 * cos(alpha) * sin(theta)));
1342 if (!this->hasGoodLevel(I, u, v)) {
1344 printf(
"Inner circle pixel (%u, %u) has bad level for dot (%g, %g): "
1345 "%d not in [%u, %u]\n",
1346 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1352 for (
unsigned int t = 0; t < thickness; t++) {
1363 if (nb_bad_points > nb_max_bad_points) {
1365 printf(
"Inner ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1374 double outCoef = 2 - ellipsoidShape_precision;
1376 for (
double theta = 0.; theta < 2 * M_PI; theta += step_angle) {
1377 u = (
unsigned int)(cog_u + outCoef * (a1 * cos(alpha) * cos(theta) - a2 * sin(alpha) * sin(theta)));
1378 v = (
unsigned int)(cog_v + outCoef * (a1 * sin(alpha) * cos(theta) + a2 * cos(alpha) * sin(theta)));
1389 if (!this->hasReverseLevel(I, u, v)) {
1391 printf(
"Outside circle pixel (%u, %u) has bad level for dot (%g, "
1392 "%g): %d not in [%u, %u]\n",
1393 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1399 for (
unsigned int t = 0; t < thickness; t++) {
1408 if (nb_bad_points > nb_max_bad_points) {
1410 printf(
"Outside ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1436 bool vpDot2::hasGoodLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1438 if (!isInArea(u, v))
1441 if (I[v][u] >= gray_level_min && I[v][u] <= gray_level_max) {
1460 bool vpDot2::hasReverseLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1463 if (!isInArea(u, v))
1466 if (I[v][u] < gray_level_min || I[v][u] > gray_level_max) {
1539 direction_list.clear();
1540 ip_edges_list.clear();
1547 if (std::fabs(est_u + 1.0) <=
vpMath::maximum(std::fabs(est_u), 1.) * std::numeric_limits<double>::epsilon()) {
1548 est_u = this->cog.
get_u();
1553 if (std::fabs(est_v + 1.0) <=
vpMath::maximum(std::fabs(est_v), 1.) * std::numeric_limits<double>::epsilon()) {
1554 est_v = this->cog.
get_v();
1559 if (!isInArea((
unsigned int)est_u, (
unsigned int)est_v)) {
1561 "Initial pixel coordinates (%d, %d) for dot tracking are "
1563 (
int)est_u, (
int)est_v);
1574 if (!hasGoodLevel(I, (
unsigned int)est_u, (
unsigned int)est_v)) {
1575 vpDEBUG_TRACE(3,
"Can't find a dot from pixel (%d, %d) coordinates", (
int)est_u, (
int)est_v);
1581 if (!findFirstBorder(I, (
unsigned int)est_u, (
unsigned int)est_v, this->firstBorder_u, this->firstBorder_v)) {
1583 vpDEBUG_TRACE(3,
"Can't find first border (%d, %d) coordinates", (
int)est_u, (
int)est_v);
1587 unsigned int dir = 6;
1590 computeFreemanChainElement(I, this->firstBorder_u, this->firstBorder_v, dir);
1591 unsigned int firstDir = dir;
1594 if (!isInArea(this->firstBorder_u, this->firstBorder_v)) {
1595 vpDEBUG_TRACE(3,
"Border pixel coordinates (%d, %d) of the dot are not in the area", this->firstBorder_u,
1596 this->firstBorder_v);
1601 direction_list.push_back(dir);
1603 ip.
set_u(this->firstBorder_u);
1604 ip.
set_v(this->firstBorder_v);
1606 ip_edges_list.push_back(ip);
1608 int border_u = (int)this->firstBorder_u;
1609 int border_v = (int)this->firstBorder_v;
1611 float dS, dMu, dMv, dMuv, dMu2, dMv2;
1622 for (
int t = 0; t < (int)thickness; t++) {
1623 ip.
set_u(border_u + t);
1635 computeFreemanParameters(border_u, border_v, dir, du, dv,
1646 if (compute_moment) {
1652 if (!isInArea((
unsigned int)border_u, (
unsigned int)border_v)) {
1654 vpDEBUG_TRACE(3,
"Dot (%d, %d) is not in the area", border_u, border_v);
1661 direction_list.push_back(dir);
1665 ip_edges_list.push_back(ip);
1670 if (border_v < bbox_v_min)
1671 bbox_v_min = border_v;
1672 if (border_v > bbox_v_max)
1673 bbox_v_max = border_v;
1674 if (border_u < bbox_u_min)
1675 bbox_u_min = border_u;
1676 if (border_u > bbox_u_max)
1677 bbox_u_max = border_u;
1680 if (computeFreemanChainElement(I, (
unsigned int)border_u, (
unsigned int)border_v, dir) ==
false) {
1681 vpDEBUG_TRACE(3,
"Can't compute Freeman chain for dot (%d, %d)", border_u, border_v);
1688 }
while ((getFirstBorder_u() != (
unsigned int)border_u || getFirstBorder_v() != (
unsigned int)border_v ||
1690 isInArea((
unsigned int)border_u, (
unsigned int)border_v));
1693 #if VP_DEBUG_MODE == 3
1701 if (std::fabs(
m00) <= std::numeric_limits<double>::epsilon() ||
1702 std::fabs(
m00 - 1.) <=
vpMath::maximum(std::fabs(
m00), 1.) * std::numeric_limits<double>::epsilon()) {
1703 vpDEBUG_TRACE(3,
"The center of gravity of the dot wasn't properly detected");
1708 double tmpCenter_u =
m10 /
m00;
1709 double tmpCenter_v =
m01 /
m00;
1712 if (compute_moment) {
1718 cog.
set_u(tmpCenter_u);
1719 cog.
set_v(tmpCenter_v);
1722 width = bbox_u_max - bbox_u_min + 1;
1723 height = bbox_v_max - bbox_v_min + 1;
1726 computeMeanGrayLevel(I);
1745 bool vpDot2::findFirstBorder(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1746 unsigned int &border_u,
unsigned int &border_v)
1756 double epsilon = 0.001;
1759 std::cout <<
"gray level: " << gray_level_min <<
" " << gray_level_max << std::endl;
1761 while (hasGoodLevel(I, border_u + 1, border_v) && border_u < area.
getRight() ) {
1767 "The found dot (%d, %d, %d) has a greater width than the "
1800 bool vpDot2::computeFreemanChainElement(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1801 unsigned int &element)
1804 if (hasGoodLevel(I, u, v)) {
1805 unsigned int _u = u;
1806 unsigned int _v = v;
1808 updateFreemanPosition(_u, _v, (element + 2) % 8);
1809 if (hasGoodLevel(I, _u, _v)) {
1810 element = (element + 2) % 8;
1812 unsigned int _u1 = u;
1813 unsigned int _v1 = v;
1814 updateFreemanPosition(_u1, _v1, (element + 1) % 8);
1816 if (hasGoodLevel(I, _u1, _v1)) {
1817 element = (element + 1) % 8;
1819 unsigned int _u2 = u;
1820 unsigned int _v2 = v;
1821 updateFreemanPosition(_u2, _v2, element);
1823 if (hasGoodLevel(I, _u2, _v2)) {
1826 unsigned int _u3 = u;
1827 unsigned int _v3 = v;
1828 updateFreemanPosition(_u3, _v3, (element + 7) % 8);
1830 if (hasGoodLevel(I, _u3, _v3)) {
1831 element = (element + 7) % 8;
1833 unsigned int _u4 = u;
1834 unsigned int _v4 = v;
1835 updateFreemanPosition(_u4, _v4, (element + 6) % 8);
1837 if (hasGoodLevel(I, _u4, _v4)) {
1838 element = (element + 6) % 8;
1840 unsigned int _u5 = u;
1841 unsigned int _v5 = v;
1842 updateFreemanPosition(_u5, _v5, (element + 5) % 8);
1844 if (hasGoodLevel(I, _u5, _v5)) {
1845 element = (element + 5) % 8;
1847 unsigned int _u6 = u;
1848 unsigned int _v6 = v;
1849 updateFreemanPosition(_u6, _v6, (element + 4) % 8);
1851 if (hasGoodLevel(I, _u6, _v6)) {
1852 element = (element + 4) % 8;
1854 unsigned int _u7 = u;
1855 unsigned int _v7 = v;
1856 updateFreemanPosition(_u7, _v7, (element + 3) % 8);
1858 if (hasGoodLevel(I, _u7, _v7)) {
1859 element = (element + 3) % 8;
1912 void vpDot2::computeFreemanParameters(
const int &u_p,
const int &v_p,
unsigned int &element,
int &du,
int &dv,
1913 float &dS,
float &dMu,
float &dMv,
float &dMuv,
float &dMu2,
float &dMv2)
1935 dMv = (float)(0.5 * v_p * v_p);
1936 if (compute_moment) {
1937 dMuv = (float)(0.25 * v_p * v_p * (2 * u_p + 1));
1939 dMv2 = (float)(1.0 / 3. * v_p * v_p * v_p);
1946 dS = (float)(v_p + 0.5);
1947 dMu = -(float)(0.5 * u_p * (u_p + 1) + 1.0 / 6.0);
1948 dMv = (float)(0.5 * v_p * (v_p + 1) + 1.0 / 6.0);
1949 if (compute_moment) {
1950 float half_u_p = (float)(0.5 * u_p);
1951 dMuv = (float)(v_p * v_p * (0.25 + half_u_p) + v_p * (1. / 3. + half_u_p) + 1. / 6. * u_p + 0.125);
1952 dMu2 = (float)(-1. / 3. * u_p * (u_p * u_p + 1.5 * u_p + 1.) - 1. / 12.0);
1953 dMv2 = (float)(1. / 3. * v_p * (v_p * v_p + 1.5 * v_p + 1.) + 1. / 12.0);
1960 dMu = (float)(-0.5 * u_p * u_p);
1962 if (compute_moment) {
1964 dMu2 = (float)(-1.0 / 3. * u_p * u_p * u_p);
1972 dS = (float)(-v_p - 0.5);
1973 dMu = -(float)(0.5 * u_p * (u_p - 1) + 1.0 / 6.0);
1974 dMv = -(float)(0.5 * v_p * (v_p + 1) + 1.0 / 6.0);
1975 if (compute_moment) {
1976 float half_u_p = (float)(0.5 * u_p);
1977 dMuv = (float)(v_p * v_p * (0.25 - half_u_p) + v_p * (1. / 3. - half_u_p) - 1. / 6. * u_p + 0.125);
1978 dMu2 = (float)(-1. / 3. * u_p * (u_p * u_p - 1.5 * u_p + 1.) - 1. / 12.0);
1979 dMv2 = (float)(-1. / 3. * v_p * (v_p * v_p + 1.5 * v_p + 1.) - 1. / 12.0);
1986 dMv = (float)(-0.5 * v_p * v_p);
1988 if (compute_moment) {
1989 dMuv = (float)(-0.25 * v_p * v_p * (2 * u_p - 1));
1991 dMv2 = (float)(-1.0 / 3. * v_p * v_p * v_p);
1998 dS = (float)(-v_p + 0.5);
1999 dMu = (float)(0.5 * u_p * (u_p - 1) + 1.0 / 6.0);
2000 dMv = (float)(-(0.5 * v_p * (v_p - 1) + 1.0 / 6.0));
2001 if (compute_moment) {
2002 float half_u_p = (float)(0.5 * u_p);
2003 dMuv = (float)(v_p * v_p * (0.25 - half_u_p) - v_p * (1. / 3. - half_u_p) - 1. / 6. * u_p + 0.125);
2004 dMu2 = (float)(1. / 3. * u_p * (u_p * u_p - 1.5 * u_p + 1.) - 1. / 12.0);
2005 dMv2 = (float)(-1. / 3. * v_p * (v_p * v_p - 1.5 * v_p + 1.) - 1. / 12.0);
2012 dMu = (float)(0.5 * u_p * u_p);
2014 if (compute_moment) {
2016 dMu2 = (float)(1.0 / 3. * u_p * u_p * u_p);
2024 dS = (float)(v_p - 0.5);
2025 dMu = (float)(0.5 * u_p * (u_p + 1) + 1.0 / 6.0);
2026 dMv = (float)(0.5 * v_p * (v_p - 1) + 1.0 / 6.0);
2027 if (compute_moment) {
2028 float half_u_p = (float)(0.5 * u_p);
2029 dMuv = (float)(v_p * v_p * (0.25 + half_u_p) - v_p * (1. / 3. + half_u_p) + 1. / 6. * u_p + 0.125);
2030 dMu2 = (float)(1. / 3. * u_p * (u_p * u_p + 1.5 * u_p + 1.) + 1. / 12.0);
2031 dMv2 = (float)(1. / 3. * v_p * (v_p * v_p - 1.5 * v_p + 1.) - 1. / 12.0);
2050 void vpDot2::updateFreemanPosition(
unsigned int &u,
unsigned int &v,
const unsigned int &dir)
2112 double u = ip.
get_u();
2113 double v = ip.
get_v();
2115 if (u < 0 || u >= w)
2117 if (v < 0 || v >= h)
2133 bool vpDot2::isInArea(
const unsigned int &u,
const unsigned int &v)
const
2135 unsigned int area_u_min = (
unsigned int)area.
getLeft();
2136 unsigned int area_u_max = (
unsigned int)area.
getRight();
2137 unsigned int area_v_min = (
unsigned int)area.
getTop();
2138 unsigned int area_v_max = (
unsigned int)area.
getBottom();
2140 if (u < area_u_min || u > area_u_max)
2142 if (v < area_v_min || v > area_v_max)
2158 void vpDot2::getGridSize(
unsigned int &gridWidth,
unsigned int &gridHeight)
2170 if (gridHeight == 0)
2188 int cog_u = (int)cog.
get_u();
2189 int cog_v = (int)cog.
get_v();
2191 unsigned int sum_value = 0;
2192 unsigned int nb_pixels = 0;
2194 for (
unsigned int i = (
unsigned int)this->bbox_u_min; i <= (
unsigned int)this->bbox_u_max; i++) {
2195 unsigned int pixel_gray = (
unsigned int)I[(
unsigned int)cog_v][i];
2197 sum_value += pixel_gray;
2201 for (
unsigned int i = (
unsigned int)this->bbox_v_min; i <= (
unsigned int)this->bbox_v_max; i++) {
2202 unsigned char pixel_gray = I[i][(
unsigned int)cog_u];
2204 sum_value += pixel_gray;
2208 if (nb_pixels < 10) {
2211 if ((cog_u - bbox_u_min) > (cog_v - bbox_v_min)) {
2212 imin = cog_v - bbox_v_min;
2214 imin = cog_u - bbox_u_min;
2216 if ((bbox_u_max - cog_u) > (bbox_v_max - cog_v)) {
2217 imax = bbox_v_max - cog_v;
2219 imax = bbox_u_max - cog_u;
2221 for (
int i = -imin; i <= imax; i++) {
2222 unsigned int pixel_gray = (
unsigned int)I[(
unsigned int)(cog_v + i)][(
unsigned int)(cog_u + i)];
2224 sum_value += pixel_gray;
2229 if ((cog_u - bbox_u_min) > (bbox_v_max - cog_v)) {
2230 imin = bbox_v_max - cog_v;
2232 imin = cog_u - bbox_u_min;
2234 if ((bbox_u_max - cog_u) > (cog_v - bbox_v_min)) {
2235 imax = cog_v - bbox_v_min;
2237 imax = bbox_u_max - cog_u;
2240 for (
int i = -imin; i <= imax; i++) {
2241 unsigned char pixel_gray = I[(
unsigned int)(cog_v - i)][(
unsigned int)(cog_u + i)];
2243 sum_value += pixel_gray;
2249 if (nb_pixels == 0) {
2253 mean_gray_level = sum_value / nb_pixels;
2284 std::cout << Cogs.
getRows() <<
" dots loaded from file " << dotFile << std::endl;
2289 std::cout <<
"Dot file has a wrong number of dots : redefining them" << std::endl;
2296 for (i = 0; i < n; ++i) {
2297 cog.
set_uv(Cogs[i][0], Cogs[i][1]);
2307 std::cout <<
"Cannot track dots from file" << std::endl;
2313 for (i = 0; i < n && fromFile; ++i) {
2315 for (
unsigned int j = 0; j < n && fromFile; ++j)
2319 std::cout <<
"Dots from file seem incoherent" << std::endl;
2328 std::cout <<
"Click on the " << n <<
" dots clockwise starting from upper/left dot..." << std::endl;
2329 for (i = 0; i < n; i++) {
2338 Cogs[i][0] = cog.
get_u();
2339 Cogs[i][1] = cog.
get_v();
2345 if (!fromFile && (dotFile !=
"")) {
2347 std::cout << Cogs.
getRows() <<
" dots written to file " << dotFile << std::endl;
2351 for (i = 0; i < n; ++i)
2374 std::vector<vpImagePoint> &cogs,
vpImagePoint *cogStar)
2378 for (i = 0; i < n; ++i) {
2380 cogs.push_back(dot[i].
getCog());
2383 for (i = n; i < cogs.size(); ++i)
2386 for (i = 0; i < n; ++i)
2389 if (cogStar != NULL)
2390 for (i = 0; i < n; ++i) {
2412 const std::list<vpImagePoint> &edges_list,
vpColor color,
unsigned int thickness)
2415 std::list<vpImagePoint>::const_iterator it;
2417 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2437 vpColor color,
unsigned int thickness)
2440 std::list<vpImagePoint>::const_iterator it;
2442 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2452 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
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 emitted 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 emitted by the vpTracker class and its derivatives.
@ featureLostError
Tracker lost feature.
@ notEnoughPointError
Not enough point to track.