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;
869 area.setRect(u, v, w, h);
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) {
1249 vpDEBUG_TRACE(3,
"Bad width > for dot (%g, %g)", cog.get_u(), cog.get_v());
1251 printf(
"Bad width %g > %g for dot (%g, %g)\n",
getWidth(), wantedDot.
getWidth() / (size_precision + epsilon),
1252 cog.get_u(), cog.get_v());
1258 vpDEBUG_TRACE(3,
"Bad height > for dot (%g, %g)", cog.get_u(), cog.get_v());
1260 printf(
"Bad height %g > %g for dot (%g, %g)\n", wantedDot.
getHeight() * size_precision - epsilon,
getHeight(),
1261 cog.get_u(), cog.get_v());
1267 vpDEBUG_TRACE(3,
"Bad height > for dot (%g, %g)", cog.get_u(), cog.get_v());
1269 printf(
"Bad height %g > %g for dot (%g, %g)\n",
getHeight(), wantedDot.
getHeight() / (size_precision + epsilon),
1270 cog.get_u(), cog.get_v());
1275 if ((wantedDot.
getArea() * (size_precision * size_precision) - epsilon <
getArea()) ==
false) {
1276 vpDEBUG_TRACE(3,
"Bad surface > for dot (%g, %g)", cog.get_u(), cog.get_v());
1278 printf(
"Bad surface %g > %g for dot (%g, %g)\n",
1279 wantedDot.
getArea() * (size_precision * size_precision) - epsilon,
getArea(), cog.get_u(), cog.get_v());
1284 if ((
getArea() < wantedDot.
getArea() / (size_precision * size_precision + epsilon)) ==
false) {
1285 vpDEBUG_TRACE(3,
"Bad surface > for dot (%g, %g)", cog.get_u(), cog.get_v());
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)));
1385 if ((
double)u < area.getLeft() || (
double)u > area.getRight() || (
double)v < area.getTop() ||
1386 (
double)v > area.getBottom()) {
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);
1436bool 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) {
1460bool 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);
1745bool 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 "
1800bool 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;
1912void 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);
2050void 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)
2133bool 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)
2158void 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) {
2452VISP_EXPORT std::ostream &
operator<<(std::ostream &os,
vpDot2 &d) {
return (os <<
"(" << d.getCog() <<
")"); }
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
friend VISP_EXPORT std::ostream & operator<<(std::ostream &os, vpDot2 &d)
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 ...
Definition of the vpImage class member functions.
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.
vpTracker()
Default constructor.
void init()
Default initialization.
Error that can be emitted by the vpTracker class and its derivatives.
@ featureLostError
Tracker lost feature.
@ notEnoughPointError
Not enough point to track.