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) {
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;
554 "The center of gravity of the dot is not in the image"));
566 if (Ip - (1 - grayLevelPrecision) < 0) {
569 gray_level_min = (
unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
570 if (gray_level_min > 255)
571 gray_level_min = 255;
573 gray_level_max = (
unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
574 if (gray_level_max > 255)
575 gray_level_max = 255;
610 track(I, canMakeTheWindowGrow);
676 double diff_u = this->cog.
get_u() - cogDistantDot.
get_u();
677 double diff_v = this->cog.
get_v() - cogDistantDot.
get_v();
678 return sqrt(diff_u * diff_u + diff_v * diff_v);
737 double epsilon = 0.05;
738 if (grayLevelPrecision < epsilon) {
739 this->grayLevelPrecision = epsilon;
740 }
else if (grayLevelPrecision > 1) {
741 this->grayLevelPrecision = 1.0;
743 this->grayLevelPrecision = precision;
765 if (sizePrecision < 0) {
766 this->sizePrecision = 0;
767 }
else if (sizePrecision > 1) {
768 this->sizePrecision = 1.0;
770 this->sizePrecision = precision;
809 if (ellipsoidShapePrecision < 0) {
810 this->ellipsoidShapePrecision = 0;
811 }
else if (ellipsoidShapePrecision > 1) {
812 this->ellipsoidShapePrecision = 1.0;
814 this->ellipsoidShapePrecision = precision;
835 double epsilon = 0.05;
836 if (maxSizeSearchDistancePrecision < epsilon) {
837 this->maxSizeSearchDistancePrecision = epsilon;
838 }
else if (maxSizeSearchDistancePrecision > 1) {
839 this->maxSizeSearchDistancePrecision = 1.0;
841 this->maxSizeSearchDistancePrecision = precision;
869 unsigned int image_w = I.
getWidth();
875 else if (u >= (
int)image_w)
876 u = (int)image_w - 1;
879 else if (v >= (
int)image_h)
880 v = (
int)image_h - 1;
882 if (((
unsigned int)u + w) > image_w)
883 w = image_w - (
unsigned int)u - 1;
884 if (((
unsigned int)v + h) > image_h)
885 h = image_h - (
unsigned int)v - 1;
980 unsigned int area_h, std::list<vpDot2> &niceDots)
988 setArea(I, area_u, area_v, area_w, area_h);
991 unsigned int gridWidth;
992 unsigned int gridHeight;
993 getGridSize(gridWidth, gridHeight);
1008 std::list<vpDot2> badDotsVector;
1009 std::list<vpDot2>::iterator itnice;
1010 std::list<vpDot2>::iterator itbad;
1012 vpDot2 *dotToTest = NULL;
1015 unsigned int area_u_min = (
unsigned int)area.
getLeft();
1016 unsigned int area_u_max = (
unsigned int)area.
getRight();
1017 unsigned int area_v_min = (
unsigned int)area.
getTop();
1018 unsigned int area_v_max = (
unsigned int)area.
getBottom();
1023 for (v = area_v_min; v < area_v_max; v = v + gridHeight) {
1024 for (u = area_u_min; u < area_u_max; u = u + gridWidth) {
1028 if (!hasGoodLevel(I, u, v))
1033 bool good_germ =
true;
1035 itnice = niceDots.begin();
1036 while (itnice != niceDots.end() && good_germ ==
true) {
1039 cogTmpDot = tmpDot.
getCog();
1040 double u0 = cogTmpDot.
get_u();
1041 double v0 = cogTmpDot.
get_v();
1042 double half_w = tmpDot.
getWidth() / 2.;
1043 double half_h = tmpDot.
getHeight() / 2.;
1045 if (u >= (u0 - half_w) && u <= (u0 + half_w) && v >= (v0 - half_h) && v <= (v0 + half_h)) {
1056 unsigned int border_u;
1057 unsigned int border_v;
1058 if (findFirstBorder(I, u, v, border_u, border_v) ==
false) {
1067 itbad = badDotsVector.begin();
1068#define vpBAD_DOT_VALUE (*itbad)
1071 while (itbad != badDotsVector.end() && good_germ ==
true) {
1072 if ((
double)u >= vpBAD_DOT_VALUE.bbox_u_min && (double)u <= vpBAD_DOT_VALUE.bbox_u_max &&
1073 (
double)v >= vpBAD_DOT_VALUE.bbox_v_min && (double)v <= vpBAD_DOT_VALUE.bbox_v_max) {
1074 std::list<vpImagePoint>::const_iterator it_edges = ip_edges_list.begin();
1075 while (it_edges != ip_edges_list.end() && good_germ ==
true) {
1079 cogBadDot = *it_edges;
1081 if ((std::fabs(border_u - cogBadDot.
get_u()) <=
1083 std::numeric_limits<double>::epsilon()) &&
1084 (std::fabs(v - cogBadDot.
get_v()) <=
1086 std::numeric_limits<double>::epsilon())) {
1094#undef vpBAD_DOT_VALUE
1104 vpTRACE(4,
"Try germ (%d, %d)", u, v);
1112 if (dotToTest != NULL)
1114 dotToTest = getInstance();
1130 if (dotToTest->computeParameters(I) ==
false) {
1138 if (dotToTest->isValid(I, *
this)) {
1145 double area_center_u = area_u + area_w / 2.0 - 0.5;
1146 double area_center_v = area_v + area_h / 2.0 - 0.5;
1148 double thisDiff_u = cogDotToTest.
get_u() - area_center_u;
1149 double thisDiff_v = cogDotToTest.
get_v() - area_center_v;
1150 double thisDist = sqrt(thisDiff_u * thisDiff_u + thisDiff_v * thisDiff_v);
1152 bool stopLoop =
false;
1153 itnice = niceDots.begin();
1155 while (itnice != niceDots.end() && stopLoop ==
false) {
1159 double epsilon = 3.0;
1162 cogTmpDot = tmpDot.
getCog();
1164 if (fabs(cogTmpDot.
get_u() - cogDotToTest.
get_u()) < epsilon &&
1165 fabs(cogTmpDot.
get_v() - cogDotToTest.
get_v()) < epsilon) {
1174 double otherDiff_u = cogTmpDot.
get_u() - area_center_u;
1175 double otherDiff_v = cogTmpDot.
get_v() - area_center_v;
1176 double otherDist = sqrt(otherDiff_u * otherDiff_u + otherDiff_v * otherDiff_v);
1181 if (otherDist > thisDist) {
1182 niceDots.insert(itnice, *dotToTest);
1193 vpTRACE(4,
"End while (%d, %d)", u, v);
1197 if (itnice == niceDots.end() && stopLoop ==
false) {
1198 niceDots.push_back(*dotToTest);
1202 badDotsVector.push_front(*dotToTest);
1206 if (dotToTest != NULL)
1242 if ((std::fabs(wantedDot.
getWidth()) > std::numeric_limits<double>::epsilon()) &&
1243 (std::fabs(wantedDot.
getHeight()) > std::numeric_limits<double>::epsilon()) &&
1244 (std::fabs(wantedDot.
getArea()) > std::numeric_limits<double>::epsilon()))
1247 if (std::fabs(size_precision) > std::numeric_limits<double>::epsilon()) {
1248 double epsilon = 0.001;
1250 std::cout <<
"test size precision......................\n";
1251 std::cout <<
"wanted dot: "
1253 <<
" precision=" << size_precision <<
" epsilon=" << epsilon << std::endl;
1254 std::cout <<
"dot found: "
1258 if ((wantedDot.
getWidth() * size_precision - epsilon <
getWidth()) ==
false) {
1261 printf(
"Bad width > for dot (%g, %g)\n", cog.
get_u(), cog.
get_v());
1266 if ((
getWidth() < wantedDot.
getWidth() / (size_precision + epsilon)) ==
false) {
1269 printf(
"Bad width %g > %g for dot (%g, %g)\n",
getWidth(), wantedDot.
getWidth() / (size_precision + epsilon),
1278 printf(
"Bad height %g > %g for dot (%g, %g)\n", wantedDot.
getHeight() * size_precision - epsilon,
getHeight(),
1287 printf(
"Bad height %g > %g for dot (%g, %g)\n",
getHeight(), wantedDot.
getHeight() / (size_precision + epsilon),
1293 if ((wantedDot.
getArea() * (size_precision * size_precision) - epsilon <
getArea()) ==
false) {
1296 printf(
"Bad surface %g > %g for dot (%g, %g)\n",
1302 if ((
getArea() < wantedDot.
getArea() / (size_precision * size_precision + epsilon)) ==
false) {
1305 printf(
"Bad surface %g < %g for dot (%g, %g)\n",
getArea(),
1306 wantedDot.
getArea() / (size_precision * size_precision + epsilon), cog.
get_u(), cog.
get_v());
1317 int nb_point_to_test = 20;
1318 int nb_bad_points = 0;
1319 int nb_max_bad_points = (int)(nb_point_to_test * allowedBadPointsPercentage_);
1320 double step_angle = 2 * M_PI / nb_point_to_test;
1323 if (std::fabs(ellipsoidShape_precision) > std::numeric_limits<double>::epsilon() && compute_moment) {
1340 double Sqrt = sqrt(tmp1 * tmp1 + 4 * tmp2 * tmp2);
1350 double innerCoef = ellipsoidShape_precision;
1352 double cog_u = this->cog.
get_u();
1353 double cog_v = this->cog.
get_v();
1357 for (
double theta = 0.; theta < 2 * M_PI; theta += step_angle) {
1358 u = (
unsigned int)(cog_u + innerCoef * (a1 * cos(alpha) * cos(theta) - a2 * sin(alpha) * sin(theta)));
1359 v = (
unsigned int)(cog_v + innerCoef * (a1 * sin(alpha) * cos(theta) + a2 * cos(alpha) * sin(theta)));
1360 if (!this->hasGoodLevel(I, u, v)) {
1364 printf(
"Inner circle pixel (%u, %u) has bad level for dot (%g, %g): "
1365 "%d not in [%u, %u]\n",
1366 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1372 for (
unsigned int t = 0; t < thickness; t++) {
1383 if (nb_bad_points > nb_max_bad_points) {
1385 printf(
"Inner ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1394 double outCoef = 2 - ellipsoidShape_precision;
1396 for (
double theta = 0.; theta < 2 * M_PI; theta += step_angle) {
1397 u = (
unsigned int)(cog_u + outCoef * (a1 * cos(alpha) * cos(theta) - a2 * sin(alpha) * sin(theta)));
1398 v = (
unsigned int)(cog_v + outCoef * (a1 * sin(alpha) * cos(theta) + a2 * cos(alpha) * sin(theta)));
1409 if (!this->hasReverseLevel(I, u, v)) {
1413 printf(
"Outside circle pixel (%u, %u) has bad level for dot (%g, "
1414 "%g): %d not in [%u, %u]\n",
1415 u, v, cog_u, cog_v, I[v][u], gray_level_min, gray_level_max);
1421 for (
unsigned int t = 0; t < thickness; t++) {
1430 if (nb_bad_points > nb_max_bad_points) {
1432 printf(
"Outside ellipse has %d bad points. Max allowed is %d\n", nb_bad_points, nb_max_bad_points);
1458bool vpDot2::hasGoodLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1460 if (!isInArea(u, v))
1463 if (I[v][u] >= gray_level_min && I[v][u] <= gray_level_max) {
1482bool vpDot2::hasReverseLevel(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v)
const
1485 if (!isInArea(u, v))
1488 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((
unsigned int)est_u, (
unsigned int)est_v)) {
1583 "Initial pixel coordinates (%d, %d) for dot tracking are "
1585 (
int)est_u, (
int)est_v);
1596 if (!hasGoodLevel(I, (
unsigned int)est_u, (
unsigned int)est_v)) {
1597 vpDEBUG_TRACE(3,
"Can't find a dot from pixel (%d, %d) coordinates", (
int)est_u, (
int)est_v);
1603 if (!findFirstBorder(I, (
unsigned int)est_u, (
unsigned int)est_v, this->firstBorder_u, this->firstBorder_v)) {
1605 vpDEBUG_TRACE(3,
"Can't find first border (%d, %d) coordinates", (
int)est_u, (
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 = (int)this->firstBorder_u;
1631 int border_v = (int)this->firstBorder_v;
1637 float dS, dMu, dMv, dMuv, dMu2, dMv2;
1648 for (
int t = 0; t < (int)thickness; t++) {
1649 ip.
set_u(border_u + t);
1661 computeFreemanParameters(border_u, border_v, dir, du, dv,
1672 if (compute_moment) {
1678 if (!isInArea((
unsigned int)border_u, (
unsigned int)border_v)) {
1680 vpDEBUG_TRACE(3,
"Dot (%d, %d) is not in the area", border_u, border_v);
1687 direction_list.push_back(dir);
1691 ip_edges_list.push_back(ip);
1696 if (border_v < bbox_v_min)
1697 bbox_v_min = border_v;
1698 if (border_v > bbox_v_max)
1699 bbox_v_max = border_v;
1700 if (border_u < bbox_u_min)
1701 bbox_u_min = border_u;
1702 if (border_u > bbox_u_max)
1703 bbox_u_max = border_u;
1706 if (computeFreemanChainElement(I, (
unsigned int)border_u, (
unsigned int)border_v, dir) ==
false) {
1707 vpDEBUG_TRACE(3,
"Can't compute Freeman chain for dot (%d, %d)", border_u, border_v);
1714 }
while ((getFirstBorder_u() != (
unsigned int)border_u || getFirstBorder_v() != (
unsigned int)border_v ||
1716 isInArea((
unsigned int)border_u, (
unsigned int)border_v));
1719#if VP_DEBUG_MODE == 3
1727 if (std::fabs(
m00) <= std::numeric_limits<double>::epsilon() ||
1728 std::fabs(
m00 - 1.) <=
vpMath::maximum(std::fabs(
m00), 1.) * std::numeric_limits<double>::epsilon()) {
1729 vpDEBUG_TRACE(3,
"The center of gravity of the dot wasn't properly detected");
1734 double tmpCenter_u =
m10 /
m00;
1735 double tmpCenter_v =
m01 /
m00;
1738 if (compute_moment) {
1752 cog.
set_u(tmpCenter_u);
1753 cog.
set_v(tmpCenter_v);
1756 width = bbox_u_max - bbox_u_min + 1;
1757 height = bbox_v_max - bbox_v_min + 1;
1760 computeMeanGrayLevel(I);
1779bool vpDot2::findFirstBorder(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1780 unsigned int &border_u,
unsigned int &border_v)
1790 double epsilon = 0.001;
1793 std::cout <<
"gray level: " << gray_level_min <<
" " << gray_level_max << std::endl;
1795 while (hasGoodLevel(I, border_u + 1, border_v) && border_u < area.
getRight() ) {
1801 "The found dot (%d, %d, %d) has a greater width than the "
1834bool vpDot2::computeFreemanChainElement(
const vpImage<unsigned char> &I,
const unsigned int &u,
const unsigned int &v,
1835 unsigned int &element)
1838 if (hasGoodLevel(I, u, v)) {
1839 unsigned int _u = u;
1840 unsigned int _v = v;
1842 updateFreemanPosition(_u, _v, (element + 2) % 8);
1843 if (hasGoodLevel(I, _u, _v)) {
1844 element = (element + 2) % 8;
1846 unsigned int _u1 = u;
1847 unsigned int _v1 = v;
1848 updateFreemanPosition(_u1, _v1, (element + 1) % 8);
1850 if (hasGoodLevel(I, _u1, _v1)) {
1851 element = (element + 1) % 8;
1853 unsigned int _u2 = u;
1854 unsigned int _v2 = v;
1855 updateFreemanPosition(_u2, _v2, element);
1857 if (hasGoodLevel(I, _u2, _v2)) {
1860 unsigned int _u3 = u;
1861 unsigned int _v3 = v;
1862 updateFreemanPosition(_u3, _v3, (element + 7) % 8);
1864 if (hasGoodLevel(I, _u3, _v3)) {
1865 element = (element + 7) % 8;
1867 unsigned int _u4 = u;
1868 unsigned int _v4 = v;
1869 updateFreemanPosition(_u4, _v4, (element + 6) % 8);
1871 if (hasGoodLevel(I, _u4, _v4)) {
1872 element = (element + 6) % 8;
1874 unsigned int _u5 = u;
1875 unsigned int _v5 = v;
1876 updateFreemanPosition(_u5, _v5, (element + 5) % 8);
1878 if (hasGoodLevel(I, _u5, _v5)) {
1879 element = (element + 5) % 8;
1881 unsigned int _u6 = u;
1882 unsigned int _v6 = v;
1883 updateFreemanPosition(_u6, _v6, (element + 4) % 8);
1885 if (hasGoodLevel(I, _u6, _v6)) {
1886 element = (element + 4) % 8;
1888 unsigned int _u7 = u;
1889 unsigned int _v7 = v;
1890 updateFreemanPosition(_u7, _v7, (element + 3) % 8);
1892 if (hasGoodLevel(I, _u7, _v7)) {
1893 element = (element + 3) % 8;
1946void vpDot2::computeFreemanParameters(
const int &u_p,
const int &v_p,
unsigned int &element,
int &du,
int &dv,
1947 float &dS,
float &dMu,
float &dMv,
float &dMuv,
float &dMu2,
float &dMv2)
1969 dMv = (float)(0.5 * v_p * v_p);
1970 if (compute_moment) {
1971 dMuv = (float)(0.25 * v_p * v_p * (2 * u_p + 1));
1973 dMv2 = (float)(1.0 / 3. * v_p * v_p * v_p);
1980 dS = (float)(v_p + 0.5);
1981 dMu = -(float)(0.5 * u_p * (u_p + 1) + 1.0 / 6.0);
1982 dMv = (float)(0.5 * v_p * (v_p + 1) + 1.0 / 6.0);
1983 if (compute_moment) {
1984 float half_u_p = (float)(0.5 * u_p);
1985 dMuv = (float)(v_p * v_p * (0.25 + half_u_p) + v_p * (1. / 3. + half_u_p) + 1. / 6. * u_p + 0.125);
1986 dMu2 = (float)(-1. / 3. * u_p * (u_p * u_p + 1.5 * u_p + 1.) - 1. / 12.0);
1987 dMv2 = (float)(1. / 3. * v_p * (v_p * v_p + 1.5 * v_p + 1.) + 1. / 12.0);
1994 dMu = (float)(-0.5 * u_p * u_p);
1996 if (compute_moment) {
1998 dMu2 = (float)(-1.0 / 3. * u_p * u_p * u_p);
2006 dS = (float)(-v_p - 0.5);
2007 dMu = -(float)(0.5 * u_p * (u_p - 1) + 1.0 / 6.0);
2008 dMv = -(float)(0.5 * v_p * (v_p + 1) + 1.0 / 6.0);
2009 if (compute_moment) {
2010 float half_u_p = (float)(0.5 * u_p);
2011 dMuv = (float)(v_p * v_p * (0.25 - half_u_p) + v_p * (1. / 3. - half_u_p) - 1. / 6. * u_p + 0.125);
2012 dMu2 = (float)(-1. / 3. * u_p * (u_p * u_p - 1.5 * u_p + 1.) - 1. / 12.0);
2013 dMv2 = (float)(-1. / 3. * v_p * (v_p * v_p + 1.5 * v_p + 1.) - 1. / 12.0);
2020 dMv = (float)(-0.5 * v_p * v_p);
2022 if (compute_moment) {
2023 dMuv = (float)(-0.25 * v_p * v_p * (2 * u_p - 1));
2025 dMv2 = (float)(-1.0 / 3. * v_p * v_p * v_p);
2032 dS = (float)(-v_p + 0.5);
2033 dMu = (float)(0.5 * u_p * (u_p - 1) + 1.0 / 6.0);
2034 dMv = (float)(-(0.5 * v_p * (v_p - 1) + 1.0 / 6.0));
2035 if (compute_moment) {
2036 float half_u_p = (float)(0.5 * u_p);
2037 dMuv = (float)(v_p * v_p * (0.25 - half_u_p) - v_p * (1. / 3. - half_u_p) - 1. / 6. * u_p + 0.125);
2038 dMu2 = (float)(1. / 3. * u_p * (u_p * u_p - 1.5 * u_p + 1.) - 1. / 12.0);
2039 dMv2 = (float)(-1. / 3. * v_p * (v_p * v_p - 1.5 * v_p + 1.) - 1. / 12.0);
2046 dMu = (float)(0.5 * u_p * u_p);
2048 if (compute_moment) {
2050 dMu2 = (float)(1.0 / 3. * u_p * u_p * u_p);
2058 dS = (float)(v_p - 0.5);
2059 dMu = (float)(0.5 * u_p * (u_p + 1) + 1.0 / 6.0);
2060 dMv = (float)(0.5 * v_p * (v_p - 1) + 1.0 / 6.0);
2061 if (compute_moment) {
2062 float half_u_p = (float)(0.5 * u_p);
2063 dMuv = (float)(v_p * v_p * (0.25 + half_u_p) - v_p * (1. / 3. + half_u_p) + 1. / 6. * u_p + 0.125);
2064 dMu2 = (float)(1. / 3. * u_p * (u_p * u_p + 1.5 * u_p + 1.) + 1. / 12.0);
2065 dMv2 = (float)(1. / 3. * v_p * (v_p * v_p - 1.5 * v_p + 1.) - 1. / 12.0);
2084void vpDot2::updateFreemanPosition(
unsigned int &u,
unsigned int &v,
const unsigned int &dir)
2146 double u = ip.
get_u();
2147 double v = ip.
get_v();
2149 if (u < 0 || u >= w)
2151 if (v < 0 || v >= h)
2167bool vpDot2::isInArea(
const unsigned int &u,
const unsigned int &v)
const
2169 unsigned int area_u_min = (
unsigned int)area.
getLeft();
2170 unsigned int area_u_max = (
unsigned int)area.
getRight();
2171 unsigned int area_v_min = (
unsigned int)area.
getTop();
2172 unsigned int area_v_max = (
unsigned int)area.
getBottom();
2174 if (u < area_u_min || u > area_u_max)
2176 if (v < area_v_min || v > area_v_max)
2192void vpDot2::getGridSize(
unsigned int &gridWidth,
unsigned int &gridHeight)
2204 if (gridHeight == 0)
2222 int cog_u = (int)cog.
get_u();
2223 int cog_v = (int)cog.
get_v();
2225 unsigned int sum_value = 0;
2226 unsigned int nb_pixels = 0;
2228 for (
unsigned int i = (
unsigned int)this->bbox_u_min; i <= (
unsigned int)this->bbox_u_max; i++) {
2229 unsigned int pixel_gray = (
unsigned int)I[(
unsigned int)cog_v][i];
2231 sum_value += pixel_gray;
2235 for (
unsigned int i = (
unsigned int)this->bbox_v_min; i <= (
unsigned int)this->bbox_v_max; i++) {
2236 unsigned char pixel_gray = I[i][(
unsigned int)cog_u];
2238 sum_value += pixel_gray;
2242 if (nb_pixels < 10) {
2245 if ((cog_u - bbox_u_min) > (cog_v - bbox_v_min)) {
2246 imin = cog_v - bbox_v_min;
2248 imin = cog_u - bbox_u_min;
2250 if ((bbox_u_max - cog_u) > (bbox_v_max - cog_v)) {
2251 imax = bbox_v_max - cog_v;
2253 imax = bbox_u_max - cog_u;
2255 for (
int i = -imin; i <= imax; i++) {
2256 unsigned int pixel_gray = (
unsigned int)I[(
unsigned int)(cog_v + i)][(
unsigned int)(cog_u + i)];
2258 sum_value += pixel_gray;
2263 if ((cog_u - bbox_u_min) > (bbox_v_max - cog_v)) {
2264 imin = bbox_v_max - cog_v;
2266 imin = cog_u - bbox_u_min;
2268 if ((bbox_u_max - cog_u) > (cog_v - bbox_v_min)) {
2269 imax = cog_v - bbox_v_min;
2271 imax = bbox_u_max - cog_u;
2274 for (
int i = -imin; i <= imax; i++) {
2275 unsigned char pixel_gray = I[(
unsigned int)(cog_v - i)][(
unsigned int)(cog_u + i)];
2277 sum_value += pixel_gray;
2283 if (nb_pixels == 0) {
2287 mean_gray_level = sum_value / nb_pixels;
2318 std::cout << Cogs.
getRows() <<
" dots loaded from file " << dotFile << std::endl;
2323 std::cout <<
"Dot file has a wrong number of dots : redefining them" << std::endl;
2330 for (i = 0; i < n; ++i) {
2331 cog.
set_uv(Cogs[i][0], Cogs[i][1]);
2341 std::cout <<
"Cannot track dots from file" << std::endl;
2347 for (i = 0; i < n && fromFile; ++i) {
2349 for (
unsigned int j = 0; j < n && fromFile; ++j)
2353 std::cout <<
"Dots from file seem incoherent" << std::endl;
2362 std::cout <<
"Click on the " << n <<
" dots clockwise starting from upper/left dot..." << std::endl;
2363 for (i = 0; i < n; i++) {
2372 Cogs[i][0] = cog.
get_u();
2373 Cogs[i][1] = cog.
get_v();
2379 if (!fromFile && (dotFile !=
"")) {
2381 std::cout << Cogs.
getRows() <<
" dots written to file " << dotFile << std::endl;
2385 for (i = 0; i < n; ++i)
2408 std::vector<vpImagePoint> &cogs,
vpImagePoint *cogStar)
2412 for (i = 0; i < n; ++i) {
2414 cogs.push_back(dot[i].
getCog());
2417 for (i = n; i < cogs.size(); ++i)
2420 for (i = 0; i < n; ++i)
2423 if (cogStar != NULL)
2424 for (i = 0; i < n; ++i) {
2446 const std::list<vpImagePoint> &edges_list,
vpColor color,
unsigned int thickness)
2449 std::list<vpImagePoint>::const_iterator it;
2451 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2471 vpColor color,
unsigned int thickness)
2474 std::list<vpImagePoint>::const_iterator it;
2476 for (it = edges_list.begin(); it != edges_list.end(); ++it) {
2486VISP_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.