Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
vpDot.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Track a white dot.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  * Aurelien Yol
38  *
39  *****************************************************************************/
40 
41 /*
42  \file vpDot.cpp
43  \brief Track a white dot
44 */
45 
46 #include <visp3/blob/vpDot.h>
47 #include <visp3/core/vpColor.h>
48 #include <visp3/core/vpDisplay.h>
49 #include <visp3/core/vpTrackingException.h>
50 
51 #include <vector>
52 
53 /*
54  \class vpDot
55  \brief Track a white dot
56 */
57 
58 /* spiral size for the dot search */
59 const unsigned int vpDot::SPIRAL_SEARCH_SIZE = 350;
60 
67 void vpDot::init()
68 {
69  cog.set_u(0);
70  cog.set_v(0);
71 
72  compute_moment = false;
73  graphics = false;
74  thickness = 1;
75  maxDotSizePercentage = 0.25; // 25 % of the image size
76 
77  mean_gray_level = 0;
78  gray_level_min = 128;
79  gray_level_max = 255;
80  grayLevelPrecision = 0.85;
81  gamma = 1.5;
82 
83  m00 = m11 = m02 = m20 = m10 = m01 = mu11 = mu02 = mu20 = 0;
84 
85  connexityType = CONNEXITY_4;
86 
87  u_min = u_max = v_min = v_max = 0;
88 
89  gray_level_out = 0;
90  nbMaxPoint = 0;
91 }
92 
94  : m00(0.), m01(0.), m10(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), ip_connexities_list(),
95  ip_edges_list(), connexityType(CONNEXITY_4), cog(), u_min(0), u_max(0), v_min(0), v_max(0), graphics(false),
96  thickness(1), maxDotSizePercentage(0.25), gray_level_out(0), mean_gray_level(0), gray_level_min(128),
97  gray_level_max(255), grayLevelPrecision(0.85), gamma(1.5), compute_moment(false), nbMaxPoint(0)
98 {
99 }
100 
107  : m00(0.), m01(0.), m10(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), ip_connexities_list(),
108  ip_edges_list(), connexityType(CONNEXITY_4), cog(ip), u_min(0), u_max(0), v_min(0), v_max(0), graphics(false),
109  thickness(1), maxDotSizePercentage(0.25), gray_level_out(0), mean_gray_level(0), gray_level_min(128),
110  gray_level_max(255), grayLevelPrecision(0.85), gamma(1.5), compute_moment(false), nbMaxPoint(0)
111 {
112 }
113 
118  : vpTracker(d), m00(0.), m01(0.), m10(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.),
119  ip_connexities_list(), ip_edges_list(), connexityType(CONNEXITY_4), cog(), u_min(0), u_max(0), v_min(0), v_max(0),
120  graphics(false), thickness(1), maxDotSizePercentage(0.25), gray_level_out(0), mean_gray_level(0),
121  gray_level_min(128), gray_level_max(255), grayLevelPrecision(0.85), gamma(1.5), compute_moment(false), nbMaxPoint(0)
122 {
123  *this = d;
124 }
125 
129 vpDot::~vpDot() { ip_connexities_list.clear(); }
130 
135 {
136  ip_edges_list = d.ip_edges_list;
137  ip_connexities_list = d.ip_connexities_list;
138  connexityType = d.connexityType;
139  cog = d.getCog();
140 
141  u_min = d.u_min;
142  v_min = d.v_min;
143  u_max = d.u_max;
144  v_max = d.v_max;
145 
146  graphics = d.graphics;
147  thickness = d.thickness;
148  maxDotSizePercentage = d.maxDotSizePercentage;
149  gray_level_out = d.gray_level_out;
150  mean_gray_level = d.mean_gray_level;
151  gray_level_min = d.gray_level_min;
152  gray_level_max = d.gray_level_max;
153  grayLevelPrecision = d.grayLevelPrecision;
154  gamma = d.gamma;
155  compute_moment = d.compute_moment;
156  nbMaxPoint = d.nbMaxPoint;
157 
158  m00 = d.m00;
159  m01 = d.m01;
160  m10 = d.m10;
161  m11 = d.m11;
162  m02 = d.m02;
163  m20 = d.m20;
164 
165  mu11 = d.mu11;
166  mu20 = d.mu20;
167  mu02 = d.mu02;
168 
169  return *this;
170 }
171 
172 bool vpDot::operator!=(const vpDot &d) const { return (cog != d.getCog()); }
173 
174 bool vpDot::operator==(const vpDot &d) const { return (cog == d.getCog()); }
175 
187 void vpDot::setGrayLevelOut()
188 {
189  if (gray_level_min == 0) {
190  if (gray_level_max == 255) {
191  // gray_level_min = 0 and gray_level_max = 255: this should not occur
192  // vpERROR_TRACE("Unable to choose a good \"out\" level") ;
193  throw(vpTrackingException(vpTrackingException::initializationError, "Unable to choose a good \"out\" level"));
194  }
195  gray_level_out = static_cast<unsigned char>(gray_level_max + 1u);
196  }
197 }
198 
216 bool vpDot::connexe(const vpImage<unsigned char> &I, unsigned int u, unsigned int v, double &mean_value, double &u_cog,
217  double &v_cog, double &n)
218 {
219  std::vector<bool> checkTab(I.getWidth() * I.getHeight(), false);
220  return connexe(I, u, v, mean_value, u_cog, v_cog, n, checkTab);
221 }
239 bool vpDot::connexe(const vpImage<unsigned char> &I, unsigned int u, unsigned int v, double &mean_value, double &u_cog,
240  double &v_cog, double &n, std::vector<bool> &checkTab)
241 {
242 
243  unsigned int width = I.getWidth();
244  unsigned int height = I.getHeight();
245 
246  // Test if we are in the image
247  if ((u >= width) || (v >= height)) {
248  // std::cout << "out of bound" << std::endl;
249  return false;
250  }
251 
252  if (checkTab[u + v * I.getWidth()])
253  return true;
254 
255  vpImagePoint ip;
256  ip.set_u(u);
257  ip.set_v(v);
258 
259  if (I[v][u] >= gray_level_min && I[v][u] <= gray_level_max) {
260  checkTab[v * I.getWidth() + u] = true;
261 
262  ip_connexities_list.push_back(ip);
263 
264  u_cog += u;
265  v_cog += v;
266  n += 1;
267 
268  if (n > nbMaxPoint) {
269  // vpERROR_TRACE("Too many point %lf (%lf%% of image size). "
270  // "This threshold can be modified using the
271  // setMaxDotSize() " "method.", n, n /
272  //(I.getWidth() * I.getHeight()), nbMaxPoint,
273  // maxDotSizePercentage) ;
274 
276  "Too many point %lf (%lf%% of image size). "
277  "This threshold can be modified using the setMaxDotSize() "
278  "method.",
279  n, n / (I.getWidth() * I.getHeight()), nbMaxPoint, maxDotSizePercentage));
280  }
281 
282  // Bounding box update
283  if (u < this->u_min)
284  this->u_min = u;
285  if (u > this->u_max)
286  this->u_max = u;
287  if (v < this->v_min)
288  this->v_min = v;
289  if (v > this->v_max)
290  this->v_max = v;
291 
292  // Mean value of the dot intensities
293  mean_value = (mean_value * (n - 1) + I[v][u]) / n;
294  if (compute_moment == true) {
295  m00++;
296  m10 += u;
297  m01 += v;
298  m11 += (u * v);
299  m20 += u * u;
300  m02 += v * v;
301  }
302  } else {
303  // std::cout << "not in" << std::endl;
304  return false;
305  }
306 
307  bool edge = false;
308 
309  // if((int)u-1 >= 0)
310  if (u >= 1)
311  if (!checkTab[u - 1 + v * I.getWidth()])
312  if (!connexe(I, u - 1, v, mean_value, u_cog, v_cog, n, checkTab))
313  edge = true;
314 
315  if (u + 1 < I.getWidth())
316  if (!checkTab[u + 1 + v * I.getWidth()])
317  if (!connexe(I, u + 1, v, mean_value, u_cog, v_cog, n, checkTab))
318  edge = true;
319 
320  if (v >= 1)
321  if (!checkTab[u + (v - 1) * I.getWidth()])
322  if (!connexe(I, u, v - 1, mean_value, u_cog, v_cog, n, checkTab))
323  edge = true;
324 
325  if (v + 1 < I.getHeight())
326  if (!checkTab[u + (v + 1) * I.getWidth()])
327  if (!connexe(I, u, v + 1, mean_value, u_cog, v_cog, n, checkTab))
328  edge = true;
329 
330  if (connexityType == CONNEXITY_8) {
331  if (v >= 1 && u >= 1)
332  if (!checkTab[u - 1 + (v - 1) * I.getWidth()])
333  if (!connexe(I, u - 1, v - 1, mean_value, u_cog, v_cog, n, checkTab))
334  edge = true;
335 
336  if (v >= 1 && u + 1 < I.getWidth())
337  if (!checkTab[u + 1 + (v - 1) * I.getWidth()])
338  if (!connexe(I, u + 1, v - 1, mean_value, u_cog, v_cog, n, checkTab))
339  edge = true;
340 
341  if (v + 1 < I.getHeight() && u >= 1)
342  if (!checkTab[u - 1 + (v + 1) * I.getWidth()])
343  if (!connexe(I, u - 1, v + 1, mean_value, u_cog, v_cog, n, checkTab))
344  edge = true;
345 
346  if (v + 1 < I.getHeight() && u + 1 < I.getWidth())
347  if (!checkTab[u + 1 + (v + 1) * I.getWidth()])
348  if (!connexe(I, u + 1, v + 1, mean_value, u_cog, v_cog, n, checkTab))
349  edge = true;
350  }
351 
352  if (edge) {
353  ip_edges_list.push_back(ip);
354  if (graphics == true) {
355  vpImagePoint ip_(ip);
356  for (unsigned int t = 0; t < thickness; t++) {
357  ip_.set_u(ip.get_u() + t);
359  }
360  // vpDisplay::flush(I);
361  }
362  }
363 
364  return true;
365 }
366 
386 void vpDot::COG(const vpImage<unsigned char> &I, double &u, double &v)
387 {
388  // Set the maximal number of points considering the maximal dot size
389  // image percentage
390  nbMaxPoint = (I.getWidth() * I.getHeight()) * maxDotSizePercentage;
391 
392  // segmentation de l'image apres seuillage
393  // (etiquetage des composante connexe)
394  if (compute_moment)
395  m00 = m11 = m02 = m20 = m10 = m01 = mu11 = mu20 = mu02 = 0;
396 
397  double u_cog = 0;
398  double v_cog = 0;
399  double npoint = 0;
400  this->mean_gray_level = 0;
401 
402  ip_connexities_list.clear();
403  ip_edges_list.clear();
404 
405  // Initialise the boundig box
406  this->u_min = I.getWidth();
407  this->u_max = 0;
408  this->v_min = I.getHeight();
409  this->v_max = 0;
410 
411 #if 0
412  // Original version
413  if ( connexe(I, (unsigned int)u, (unsigned int)v,
414  gray_level_min, gray_level_max,
415  mean_gray_level, u_cog, v_cog, npoint) == vpDot::out)
416  {
417  bool sol = false ;
418  unsigned int pas ;
419  for (pas = 2 ; pas <= 25 ; pas ++ )if (sol==false)
420  {
421  for (int k=-1 ; k <=1 ; k++) if (sol==false)
422  for (int l=-1 ; l <=1 ; l++) if (sol==false)
423  {
424  u_cog = 0 ;
425  v_cog = 0 ;
426  ip_connexities_list.clear() ;
427 
428  this->mean_gray_level = 0 ;
429  if (connexe(I, (unsigned int)(u+k*pas),(unsigned int)(v+l*pas),
430  gray_level_min, gray_level_max,
431  mean_gray_level, u_cog, v_cog, npoint) != vpDot::out)
432  {
433  sol = true ; u += k*pas ; v += l*pas ;
434  }
435  }
436  }
437  if (sol == false)
438  {
439  //vpERROR_TRACE("Dot has been lost") ;
441  "Dot has been lost")) ;
442  }
443  }
444 #else
445  // If the dot is not found, search around using a spiral
446  if (!connexe(I, (unsigned int)u, (unsigned int)v, mean_gray_level, u_cog, v_cog, npoint)) {
447  bool sol = false;
448 
449  unsigned int right = 1;
450  unsigned int botom = 1;
451  unsigned int left = 2;
452  unsigned int up = 2;
453  double u_ = u, v_ = v;
454  unsigned int k;
455 
456  // Spiral search from the center to find the nearest dot
457  while ((right < SPIRAL_SEARCH_SIZE) && (sol == false)) {
458  for (k = 1; k <= right; k++)
459  if (sol == false) {
460  u_cog = 0;
461  v_cog = 0;
462  ip_connexities_list.clear();
463  ip_edges_list.clear();
464 
465  this->mean_gray_level = 0;
466  if (connexe(I, (unsigned int)u_ + k, (unsigned int)(v_), mean_gray_level, u_cog, v_cog, npoint)) {
467  sol = true;
468  u = u_ + k;
469  v = v_;
470  }
471  }
472  u_ += k;
473  right += 2;
474 
475  for (k = 1; k <= botom; k++)
476  if (sol == false) {
477  u_cog = 0;
478  v_cog = 0;
479  ip_connexities_list.clear();
480  ip_edges_list.clear();
481 
482  this->mean_gray_level = 0;
483 
484  if (connexe(I, (unsigned int)(u_), (unsigned int)(v_ + k), mean_gray_level, u_cog, v_cog, npoint)) {
485  sol = true;
486  u = u_;
487  v = v_ + k;
488  }
489  }
490  v_ += k;
491  botom += 2;
492 
493  for (k = 1; k <= left; k++)
494  if (sol == false) {
495  u_cog = 0;
496  v_cog = 0;
497  ip_connexities_list.clear();
498  ip_edges_list.clear();
499 
500  this->mean_gray_level = 0;
501 
502  if (connexe(I, (unsigned int)(u_ - k), (unsigned int)(v_), mean_gray_level, u_cog, v_cog, npoint)) {
503  sol = true;
504  u = u_ - k;
505  v = v_;
506  }
507  }
508  u_ -= k;
509  left += 2;
510 
511  for (k = 1; k <= up; k++)
512  if (sol == false) {
513  u_cog = 0;
514  v_cog = 0;
515  ip_connexities_list.clear();
516  ip_edges_list.clear();
517 
518  this->mean_gray_level = 0;
519 
520  if (connexe(I, (unsigned int)(u_), (unsigned int)(v_ - k), mean_gray_level, u_cog, v_cog, npoint)) {
521  sol = true;
522  u = u_;
523  v = v_ - k;
524  }
525  }
526  v_ -= k;
527  up += 2;
528  }
529 
530  if (sol == false) {
531  // vpERROR_TRACE("Dot has been lost") ;
532  throw(vpTrackingException(vpTrackingException::featureLostError, "Dot has been lost"));
533  }
534  }
535 
536 #endif
537  /*
538  vpImagePoint ip;
539  unsigned int i, j;
540  std::list<vpImagePoint>::iterator it;
541  for (it = ip_connexities_list.begin(); it != ip_connexities_list.end(); it
542  ++) { ip = *it; i = (unsigned int) ip.get_i(); j = (unsigned int)
543  ip.get_j(); I[i][j] = 255 ;
544  }*/
545 
546  u_cog = u_cog / npoint;
547  v_cog = v_cog / npoint;
548 
549  u = u_cog;
550  v = v_cog;
551 
552  // Initialize the threshold for the next call to track()
553  double Ip = pow((double)this->mean_gray_level / 255, 1 / gamma);
554 
555  if (Ip - (1 - grayLevelPrecision) < 0) {
556  gray_level_min = 0;
557  } else {
558  gray_level_min = (unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
559  if (gray_level_min > 255)
560  gray_level_min = 255;
561  }
562  gray_level_max = (unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
563  if (gray_level_max > 255)
564  gray_level_max = 255;
565 
566  // vpCTRACE << "gray_level_min: " << gray_level_min << std::endl;
567  // vpCTRACE << "gray_level_max: " << gray_level_max << std::endl;
568 
569  if (npoint < 5) {
570  // vpERROR_TRACE("Dot to small") ;
572  }
573 
574  if (npoint > nbMaxPoint) {
575  // vpERROR_TRACE("Too many point %lf (%lf%%). Max allowed is %lf
576  // (%lf%%). This threshold can be modified using the setMaxDotSize()
577  // method.",
578  // npoint, npoint / (I.getWidth() * I.getHeight()),
579  // nbMaxPoint, maxDotSizePercentage) ;
580 
582  "Too many point %lf (%lf%%). Max allowed is "
583  "%lf (%lf%%). This threshold can be modified "
584  "using the setMaxDotSize() method.",
585  npoint, npoint / (I.getWidth() * I.getHeight()), nbMaxPoint, maxDotSizePercentage));
586  }
587 }
588 
601 void vpDot::setMaxDotSize(double percentage)
602 {
603  if (percentage <= 0.0 || percentage > 1.0) {
604  // print a warning. We keep the default percentage
605  vpTRACE("Max dot size percentage is requested to be set to %lf.",
606  "Value should be in ]0:1]. Value will be set to %lf.", percentage, maxDotSizePercentage);
607  } else {
608  maxDotSizePercentage = percentage;
609  }
610 }
611 
636 {
637  while (vpDisplay::getClick(I, cog) != true)
638  ;
639 
640  unsigned int i = (unsigned int)cog.get_i();
641  unsigned int j = (unsigned int)cog.get_j();
642 
643  double Ip = pow((double)I[i][j] / 255, 1 / gamma);
644 
645  if (Ip - (1 - grayLevelPrecision) < 0) {
646  gray_level_min = 0;
647  } else {
648  gray_level_min = (unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
649  if (gray_level_min > 255)
650  gray_level_min = 255;
651  }
652  gray_level_max = (unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
653  if (gray_level_max > 255)
654  gray_level_max = 255;
655 
656  try {
657  track(I);
658  } catch (const vpException &e) {
659  throw(e);
660  }
661 }
662 
687 {
688 
689  cog = ip;
690 
691  unsigned int i = (unsigned int)cog.get_i();
692  unsigned int j = (unsigned int)cog.get_j();
693 
694  double Ip = pow((double)I[i][j] / 255, 1 / gamma);
695 
696  if (Ip - (1 - grayLevelPrecision) < 0) {
697  gray_level_min = 0;
698  } else {
699  gray_level_min = (unsigned int)(255 * pow(Ip - (1 - grayLevelPrecision), gamma));
700  if (gray_level_min > 255)
701  gray_level_min = 255;
702  }
703  gray_level_max = (unsigned int)(255 * pow(Ip + (1 - grayLevelPrecision), gamma));
704  if (gray_level_max > 255)
705  gray_level_max = 255;
706  try {
707  track(I);
708  } catch (const vpException &e) {
709  throw(e);
710  }
711 }
712 
740 void vpDot::initTracking(const vpImage<unsigned char> &I, const vpImagePoint &ip, unsigned int level_min,
741  unsigned int level_max)
742 {
743 
744  cog = ip;
745 
746  this->gray_level_min = level_min;
747  this->gray_level_max = level_max;
748 
749  try {
750  track(I);
751  } catch (const vpException &e) {
752  throw(e);
753  }
754 }
755 
771 {
772  try {
773  setGrayLevelOut();
774  double u = this->cog.get_u();
775  double v = this->cog.get_v();
776 
777  COG(I, u, v);
778 
779  this->cog.set_u(u);
780  this->cog.set_v(v);
781 
782  if (compute_moment == true) {
783  mu11 = m11 - u * m01;
784  mu02 = m02 - v * m01;
785  mu20 = m20 - u * m10;
786  }
787 
788  if (graphics) {
789  // display a red cross at the center of gravity's location in the image.
790  vpDisplay::displayCross(I, this->cog, 3 * thickness + 8, vpColor::red, thickness);
791  }
792 
793  } catch (const vpException &e) {
794  throw(e);
795  }
796 }
797 
813 {
814  track(I);
815 
816  ip = this->cog;
817 }
818 
826 void vpDot::display(const vpImage<unsigned char> &I, vpColor color, unsigned int thick) const
827 {
828  vpDisplay::displayCross(I, cog, 3 * thickness + 8, color, thick);
829  std::list<vpImagePoint>::const_iterator it;
830 
831  for (it = ip_edges_list.begin(); it != ip_edges_list.end(); ++it) {
832  vpDisplay::displayPoint(I, *it, color);
833  }
834 }
835 
854 void vpDot::setGrayLevelPrecision(const double &precision)
855 {
856  double epsilon = 0.05;
857  if (grayLevelPrecision < epsilon) {
858  this->grayLevelPrecision = epsilon;
859  } else if (grayLevelPrecision > 1) {
860  this->grayLevelPrecision = 1.0;
861  } else {
862  this->grayLevelPrecision = precision;
863  }
864 }
865 
880 void vpDot::display(const vpImage<unsigned char> &I, const vpImagePoint &cog, const std::list<vpImagePoint> &edges_list,
881  vpColor color, unsigned int thickness)
882 {
883  vpDisplay::displayCross(I, cog, 3 * thickness + 8, color, thickness);
884  std::list<vpImagePoint>::const_iterator it;
885 
886  for (it = edges_list.begin(); it != edges_list.end(); ++it) {
887  vpDisplay::displayPoint(I, *it, color);
888  }
889 }
890 
905 void vpDot::display(const vpImage<vpRGBa> &I, const vpImagePoint &cog, const std::list<vpImagePoint> &edges_list,
906  vpColor color, unsigned int thickness)
907 {
908  vpDisplay::displayCross(I, cog, 3 * thickness + 8, color, thickness);
909  std::list<vpImagePoint>::const_iterator it;
910 
911  for (it = edges_list.begin(); it != edges_list.end(); ++it) {
912  vpDisplay::displayPoint(I, *it, color);
913  }
914 }
915 
921 VISP_EXPORT std::ostream &operator<<(std::ostream &os, vpDot &d) { return (os << "(" << d.getCog() << ")"); };
friend VISP_EXPORT std::ostream & operator<<(std::ostream &os, vpDot &d)
Definition: vpDot.cpp:921
double get_i() const
Definition: vpImagePoint.h:203
double mu20
Definition: vpDot.h:182
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
void setMaxDotSize(double percentage)
Definition: vpDot.cpp:601
void setGrayLevelPrecision(const double &grayLevelPrecision)
Definition: vpDot.cpp:854
double m10
Definition: vpDot.h:149
void set_u(double u)
Definition: vpImagePoint.h:225
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:157
void track(const vpImage< unsigned char > &I)
Definition: vpDot.cpp:770
double m00
Definition: vpDot.h:135
error that can be emited by ViSP classes.
Definition: vpException.h:71
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
double mu11
Definition: vpDot.h:177
double mu02
Definition: vpDot.h:187
static const unsigned int SPIRAL_SEARCH_SIZE
Definition: vpDot.h:133
double m20
Definition: vpDot.h:163
double m11
Definition: vpDot.h:156
static const vpColor red
Definition: vpColor.h:217
Class that defines what is a feature generic tracker.
Definition: vpTracker.h:64
double m01
Definition: vpDot.h:142
double get_u() const
Definition: vpImagePoint.h:262
vpImagePoint getCog() const
Definition: vpDot.h:247
Error that can be emited by the vpTracker class and its derivates.
bool operator==(const vpDot &d) const
Definition: vpDot.cpp:174
vpDot & operator=(const vpDot &d)
Copy operator.
Definition: vpDot.cpp:134
#define vpTRACE
Definition: vpDebug.h:416
double get_j() const
Definition: vpImagePoint.h:214
bool operator!=(const vpDot &d) const
Definition: vpDot.cpp:172
void display(const vpImage< unsigned char > &I, vpColor color=vpColor::red, unsigned int thickness=1) const
Definition: vpDot.cpp:826
double m02
Definition: vpDot.h:170
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
vpDot()
Definition: vpDot.cpp:93
void set_v(double v)
Definition: vpImagePoint.h:236
unsigned int getHeight() const
Definition: vpImage.h:188
This tracker is meant to track a dot (connected pixels with same gray level) on a vpImage...
Definition: vpDot.h:115
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
unsigned int getWidth() const
Definition: vpImage.h:246
void initTracking(const vpImage< unsigned char > &I)
Definition: vpDot.cpp:635
double get_v() const
Definition: vpImagePoint.h:273
virtual ~vpDot()
Destructor.
Definition: vpDot.cpp:129