Visual Servoing Platform  version 3.6.1 under development (2024-11-14)
vpDot.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Track a white dot.
32  */
33 
34 /*
35  \file vpDot.cpp
36  \brief Track a white dot
37 */
38 
39 #include <visp3/blob/vpDot.h>
40 #include <visp3/core/vpColor.h>
41 #include <visp3/core/vpDisplay.h>
42 #include <visp3/core/vpTrackingException.h>
43 
44 #include <vector>
45 
46 BEGIN_VISP_NAMESPACE
47 
48 /*
49  \class vpDot
50  \brief Track a white dot
51 */
52 
53 /* spiral size for the dot search */
54 const unsigned int vpDot::SPIRAL_SEARCH_SIZE = 350;
55 
61 void vpDot::init()
62 {
63  const unsigned int val_max = 255;
64  const unsigned int val_median = 128;
65  m_cog.set_u(0);
66  m_cog.set_v(0);
67 
68  m_compute_moment = false;
69  m_graphics = false;
70  m_thickness = 1;
71  m_maxDotSizePercentage = 0.25; // 25 % of the image size
72 
73  m_mean_gray_level = 0;
74  m_gray_level_min = val_median;
75  m_gray_level_max = val_max;
76  m_grayLevelPrecision = 0.85;
77  m_gamma = 1.5;
78 
79  m00 = 0;
80  m11 = 0;
81  m02 = 0;
82  m20 = 0;
83  m10 = 0;
84  m01 = 0;
85  mu11 = 0;
86  mu02 = 0;
87  mu20 = 0;
88 
89  m_connexityType = CONNEXITY_4;
90 
91  m_u_min = 0;
92  m_u_max = 0;
93  m_v_min = 0;
94  m_v_max = 0;
95 
96  m_gray_level_out = 0;
97  m_nbMaxPoint = 0;
98 }
99 
101  : m00(0.), m01(0.), m10(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), m_ip_connexities_list(),
102  m_ip_edges_list(), m_connexityType(CONNEXITY_4), m_cog(), m_u_min(0), m_u_max(0), m_v_min(0), m_v_max(0), m_graphics(false),
103  m_thickness(1), m_maxDotSizePercentage(0.25), m_gray_level_out(0), m_mean_gray_level(0),
104  m_grayLevelPrecision(0.85), m_gamma(1.5), m_compute_moment(false), m_nbMaxPoint(0)
105 {
106  const unsigned int val_min = 128;
107  const unsigned int val_max = 255;
108  m_gray_level_min = val_min;
109  m_gray_level_max = val_max;
110 }
111 
118  : m00(0.), m01(0.), m10(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.), m_ip_connexities_list(),
119  m_ip_edges_list(), m_connexityType(CONNEXITY_4), m_cog(cog), m_u_min(0), m_u_max(0), m_v_min(0), m_v_max(0), m_graphics(false),
120  m_thickness(1), m_maxDotSizePercentage(0.25), m_gray_level_out(0), m_mean_gray_level(0),
121  m_grayLevelPrecision(0.85), m_gamma(1.5), m_compute_moment(false), m_nbMaxPoint(0)
122 {
123  const unsigned int val_min = 128;
124  const unsigned int val_max = 255;
125  m_gray_level_min = val_min;
126  m_gray_level_max = val_max;
127 }
128 
133  : vpTracker(d), m00(0.), m01(0.), m10(0.), m11(0.), m20(0.), m02(0.), mu11(0.), mu20(0.), mu02(0.),
134  m_ip_connexities_list(), m_ip_edges_list(), m_connexityType(CONNEXITY_4), m_cog(), m_u_min(0), m_u_max(0), m_v_min(0), m_v_max(0),
135  m_graphics(false), m_thickness(1), m_maxDotSizePercentage(0.25), m_gray_level_out(0), m_mean_gray_level(0),
136  m_grayLevelPrecision(0.85), m_gamma(1.5), m_compute_moment(false), m_nbMaxPoint(0)
137 {
138 
139  *this = d;
140 }
141 
145 vpDot::~vpDot() { m_ip_connexities_list.clear(); }
146 
151 {
152  m_ip_edges_list = d.m_ip_edges_list;
153  m_ip_connexities_list = d.m_ip_connexities_list;
154  m_connexityType = d.m_connexityType;
155  m_cog = d.getCog();
156 
157  m_u_min = d.m_u_min;
158  m_v_min = d.m_v_min;
159  m_u_max = d.m_u_max;
160  m_v_max = d.m_v_max;
161 
162  m_graphics = d.m_graphics;
163  m_thickness = d.m_thickness;
164  m_maxDotSizePercentage = d.m_maxDotSizePercentage;
165  m_gray_level_out = d.m_gray_level_out;
166  m_mean_gray_level = d.m_mean_gray_level;
167  m_gray_level_min = d.m_gray_level_min;
168  m_gray_level_max = d.m_gray_level_max;
169  m_grayLevelPrecision = d.m_grayLevelPrecision;
170  m_gamma = d.m_gamma;
171  m_compute_moment = d.m_compute_moment;
172  m_nbMaxPoint = d.m_nbMaxPoint;
173 
174  m00 = d.m00;
175  m01 = d.m01;
176  m10 = d.m10;
177  m11 = d.m11;
178  m02 = d.m02;
179  m20 = d.m20;
180 
181  mu11 = d.mu11;
182  mu20 = d.mu20;
183  mu02 = d.mu02;
184 
185  return *this;
186 }
187 
188 bool vpDot::operator!=(const vpDot &d) const { return (m_cog != d.getCog()); }
189 
190 bool vpDot::operator==(const vpDot &d) const { return (m_cog == d.getCog()); }
191 
203 void vpDot::setGrayLevelOut()
204 {
205  if (m_gray_level_min == 0) {
206  const unsigned int val_max = 255;
207  if (m_gray_level_max == val_max) {
208  // m_gray_level_min = 0 and m_gray_level_max = 255: this should not occur
209  throw(vpTrackingException(vpTrackingException::initializationError, "Unable to choose a good \"out\" level"));
210  }
211  m_gray_level_out = static_cast<unsigned char>(m_gray_level_max + 1u);
212  }
213 }
214 
231 bool vpDot::connexe(const vpImage<unsigned char> &I, unsigned int u, unsigned int v, double &mean_value,
232  vpImagePoint &uv_cog, unsigned int &npoints)
233 {
234  std::vector<bool> checkTab(I.getWidth() * I.getHeight(), false);
235  return connexe(I, u, v, mean_value, uv_cog, npoints, checkTab);
236 }
237 
254 bool vpDot::connexe(const vpImage<unsigned char> &I, unsigned int u, unsigned int v, double &mean_value,
255  vpImagePoint &uv_cog, unsigned int &npoints, std::vector<bool> &checkTab)
256 {
257 
258  unsigned int width = I.getWidth();
259  unsigned int height = I.getHeight();
260 
261  // Test if we are in the image
262  if ((u >= width) || (v >= height)) {
263  return false;
264  }
265 
266  if (checkTab[u + (v * I.getWidth())]) {
267  return true;
268  }
269 
270  vpImagePoint ip;
271  ip.set_u(u);
272  ip.set_v(v);
273 
274  if ((I[v][u] >= m_gray_level_min) && (I[v][u] <= m_gray_level_max)) {
275  checkTab[(v * I.getWidth()) + u] = true;
276 
277  m_ip_connexities_list.push_back(ip);
278 
279  uv_cog.set_u(uv_cog.get_u() + u);
280  uv_cog.set_v(uv_cog.get_v() + v);
281  ++npoints;
282 
283  if (npoints > m_nbMaxPoint) {
285  "Too many point %u (%f%% of image size). "
286  "This threshold can be modified using the setMaxDotSize() "
287  "method.",
288  npoints, static_cast<float>(npoints) / (I.getWidth() * I.getHeight()), m_nbMaxPoint, m_maxDotSizePercentage));
289  }
290 
291  // Bounding box update
292  if (u < m_u_min) {
293  m_u_min = u;
294  }
295  if (u > m_u_max) {
296  m_u_max = u;
297  }
298  if (v < m_v_min) {
299  m_v_min = v;
300  }
301  if (v > m_v_max) {
302  m_v_max = v;
303  }
304 
305  // Mean value of the dot intensities
306  mean_value = ((mean_value * (npoints - 1)) + I[v][u]) / npoints;
307  if (m_compute_moment == true) {
308  ++m00;
309  m10 += u;
310  m01 += v;
311  m11 += (u * v);
312  m20 += u * u;
313  m02 += v * v;
314  }
315  }
316  else {
317  return false;
318  }
319 
320  bool edge = false;
321 
322  if (u >= 1) {
323  if (!checkTab[(u - 1) + (v * I.getWidth())]) {
324  if (!connexe(I, u - 1, v, mean_value, uv_cog, npoints, checkTab)) {
325  edge = true;
326  }
327  }
328  }
329 
330  if ((u + 1) < I.getWidth()) {
331  if (!checkTab[u + 1 + (v * I.getWidth())]) {
332  if (!connexe(I, u + 1, v, mean_value, uv_cog, npoints, checkTab)) {
333  edge = true;
334  }
335  }
336  }
337 
338  if (v >= 1) {
339  if (!checkTab[u + ((v - 1) * I.getWidth())]) {
340  if (!connexe(I, u, v - 1, mean_value, uv_cog, npoints, checkTab)) {
341  edge = true;
342  }
343  }
344  }
345 
346  if ((v + 1) < I.getHeight()) {
347  if (!checkTab[u + ((v + 1) * I.getWidth())]) {
348  if (!connexe(I, u, v + 1, mean_value, uv_cog, npoints, checkTab)) {
349  edge = true;
350  }
351  }
352  }
353 
354  if (m_connexityType == CONNEXITY_8) {
355  if ((v >= 1) && (u >= 1)) {
356  if (!checkTab[(u - 1) + ((v - 1) * I.getWidth())]) {
357  if (!connexe(I, u - 1, v - 1, mean_value, uv_cog, npoints, checkTab)) {
358  edge = true;
359  }
360  }
361  }
362 
363  if ((v >= 1) && ((u + 1) < I.getWidth())) {
364  if (!checkTab[u + 1 + ((v - 1) * I.getWidth())]) {
365  if (!connexe(I, u + 1, v - 1, mean_value, uv_cog, npoints, checkTab)) {
366  edge = true;
367  }
368  }
369  }
370 
371  if (((v + 1) < I.getHeight()) && (u >= 1)) {
372  if (!checkTab[(u - 1) + ((v + 1) * I.getWidth())]) {
373  if (!connexe(I, u - 1, v + 1, mean_value, uv_cog, npoints, checkTab)) {
374  edge = true;
375  }
376  }
377  }
378 
379  if (((v + 1) < I.getHeight()) && ((u + 1) < I.getWidth())) {
380  if (!checkTab[u + 1 + ((v + 1) * I.getWidth())]) {
381  if (!connexe(I, u + 1, v + 1, mean_value, uv_cog, npoints, checkTab)) {
382  edge = true;
383  }
384  }
385  }
386  }
387 
388  if (edge) {
389  m_ip_edges_list.push_back(ip);
390  if (m_graphics == true) {
391  vpImagePoint ip_(ip);
392  for (unsigned int t = 0; t < m_thickness; ++t) {
393  ip_.set_u(ip.get_u() + t);
395  }
396  // --comment: use vpDisplay to flush I
397  }
398  }
399 
400  return true;
401 }
402 
422 void vpDot::COG(const vpImage<unsigned char> &I, double &u, double &v)
423 {
424  // Set the maximal number of points considering the maximal dot size
425  // image percentage
426  m_nbMaxPoint = (I.getWidth() * I.getHeight()) * m_maxDotSizePercentage;
427 
428  // segmentation de l'image apres seuillage
429  // (etiquetage des composante connexe)
430  if (m_compute_moment) {
431  m00 = 0;
432  m11 = 0;
433  m02 = 0;
434  m20 = 0;
435  m10 = 0;
436  m01 = 0;
437  mu11 = 0;
438  mu20 = 0;
439  mu02 = 0;
440  }
441 
442  vpImagePoint uv_cog(0, 0);
443  unsigned int npoints = 0;
444  m_mean_gray_level = 0;
445 
446  m_ip_connexities_list.clear();
447  m_ip_edges_list.clear();
448 
449  // Initialise the bounding box
450  m_u_min = I.getWidth();
451  m_u_max = 0;
452  m_v_min = I.getHeight();
453  m_v_max = 0;
454 
455  // If the dot is not found, search around using a spiral
456  if (!connexe(I, static_cast<unsigned int>(u), static_cast<unsigned int>(v), m_mean_gray_level, uv_cog, npoints)) {
457  bool sol = false;
458 
459  unsigned int right = 1;
460  unsigned int botom = 1;
461  unsigned int left = 2;
462  unsigned int up = 2;
463  double u_ = u, v_ = v;
464  unsigned int k;
465  const unsigned int val_2 = 2;
466  // Spiral search from the center to find the nearest dot
467  while ((right < SPIRAL_SEARCH_SIZE) && (sol == false)) {
468  for (k = 1; k <= right; ++k) {
469  if (sol == false) {
470  uv_cog.set_uv(0, 0);
471  m_ip_connexities_list.clear();
472  m_ip_edges_list.clear();
473 
474  m_mean_gray_level = 0;
475  if (connexe(I, static_cast<unsigned int>(u_) + k, static_cast<unsigned int>(v_), m_mean_gray_level, uv_cog, npoints)) {
476  sol = true;
477  u = u_ + k;
478  v = v_;
479  }
480  }
481  }
482  u_ += k;
483  right += val_2;
484 
485  for (k = 1; k <= botom; ++k) {
486  if (sol == false) {
487  uv_cog.set_uv(0, 0);
488  m_ip_connexities_list.clear();
489  m_ip_edges_list.clear();
490 
491  m_mean_gray_level = 0;
492 
493  if (connexe(I, static_cast<unsigned int>(u_), static_cast<unsigned int>(v_ + k), m_mean_gray_level, uv_cog, npoints)) {
494  sol = true;
495  u = u_;
496  v = v_ + k;
497  }
498  }
499  }
500  v_ += k;
501  botom += val_2;
502 
503  for (k = 1; k <= left; ++k) {
504  if (sol == false) {
505  uv_cog.set_uv(0, 0);
506  m_ip_connexities_list.clear();
507  m_ip_edges_list.clear();
508 
509  m_mean_gray_level = 0;
510 
511  if (connexe(I, static_cast<unsigned int>(u_ - k), static_cast<unsigned int>(v_), m_mean_gray_level, uv_cog, npoints)) {
512  sol = true;
513  u = u_ - k;
514  v = v_;
515  }
516  }
517  }
518  u_ -= k;
519  left += val_2;
520 
521  for (k = 1; k <= up; ++k) {
522  if (sol == false) {
523  uv_cog.set_uv(0, 0);
524  m_ip_connexities_list.clear();
525  m_ip_edges_list.clear();
526 
527  m_mean_gray_level = 0;
528 
529  if (connexe(I, static_cast<unsigned int>(u_), static_cast<unsigned int>(v_ - k), m_mean_gray_level, uv_cog, npoints)) {
530  sol = true;
531  u = u_;
532  v = v_ - k;
533  }
534  }
535  }
536  v_ -= k;
537  up += val_2;
538  }
539 
540  if (sol == false) {
541  throw(vpTrackingException(vpTrackingException::featureLostError, "Dot has been lost"));
542  }
543  }
544 
545  uv_cog.set_u(uv_cog.get_u() / npoints);
546  uv_cog.set_v(uv_cog.get_v() / npoints);
547 
548  u = uv_cog.get_u();
549  v = uv_cog.get_v();
550 
551  const unsigned int val_max = 255;
552  // Initialize the threshold for the next call to track()
553  double Ip = pow(static_cast<double>(m_mean_gray_level) / val_max, 1 / m_gamma);
554 
555  if ((Ip - (1 - m_grayLevelPrecision)) < 0) {
556  m_gray_level_min = 0;
557  }
558  else {
559  m_gray_level_min = static_cast<unsigned int>(val_max * pow(Ip - (1 - m_grayLevelPrecision), m_gamma));
560  if (m_gray_level_min > val_max) {
561  m_gray_level_min = val_max;
562  }
563  }
564  m_gray_level_max = static_cast<unsigned int>(val_max * pow(Ip + (1 - m_grayLevelPrecision), m_gamma));
565  if (m_gray_level_max > val_max) {
566  m_gray_level_max = val_max;
567  }
568 
569  const double nbMinPoint = 5;
570  if (npoints < nbMinPoint) {
572  }
573 
574  if (npoints > m_nbMaxPoint) {
576  "Too many point %lf (%lf%%). Max allowed is "
577  "%u (%f%%). This threshold can be modified "
578  "using the setMaxDotSize() method.",
579  npoints, static_cast<float>(npoints) / (I.getWidth() * I.getHeight()), m_nbMaxPoint, m_maxDotSizePercentage));
580  }
581 }
582 
595 void vpDot::setMaxDotSize(double percentage)
596 {
597  if ((percentage <= 0.0) || (percentage > 1.0)) {
598  // print a warning. We keep the default percentage
599  std::cout << "Max dot size percentage is requested to be set to " << percentage << "." << std::endl;
600  std::cout << "Value should be in ]0:1]. Value will be set to " << m_maxDotSizePercentage << "." << std::endl;
601  }
602  else {
603  m_maxDotSizePercentage = percentage;
604  }
605 }
606 
631 {
632  while (vpDisplay::getClick(I, m_cog) != true) {
633  // Wait until a click is detected
634  }
635 
636  unsigned int i = static_cast<unsigned int>(m_cog.get_i());
637  unsigned int j = static_cast<unsigned int>(m_cog.get_j());
638  const unsigned int val_max = 255;
639 
640  double Ip = pow(static_cast<double>(I[i][j]) / val_max, 1 / m_gamma);
641 
642  if ((Ip - (1 - m_grayLevelPrecision)) < 0) {
643  m_gray_level_min = 0;
644  }
645  else {
646  m_gray_level_min = static_cast<unsigned int>(val_max * pow(Ip - (1 - m_grayLevelPrecision), m_gamma));
647  if (m_gray_level_min > val_max) {
648  m_gray_level_min = val_max;
649  }
650  }
651  m_gray_level_max = static_cast<unsigned int>(val_max * pow(Ip + (1 - m_grayLevelPrecision), m_gamma));
652  if (m_gray_level_max > val_max) {
653  m_gray_level_max = val_max;
654  }
655 
656  track(I);
657 }
658 
683 {
684  m_cog = ip;
685 
686  unsigned int i = static_cast<unsigned int>(m_cog.get_i());
687  unsigned int j = static_cast<unsigned int>(m_cog.get_j());
688  const unsigned int val_max = 255;
689  double Ip = pow(static_cast<double>(I[i][j]) / val_max, 1 / m_gamma);
690 
691  if ((Ip - (1 - m_grayLevelPrecision)) < 0) {
692  m_gray_level_min = 0;
693  }
694  else {
695  m_gray_level_min = static_cast<unsigned int>(val_max * pow(Ip - (1 - m_grayLevelPrecision), m_gamma));
696  if (m_gray_level_min > val_max) {
697  m_gray_level_min = val_max;
698  }
699  }
700  m_gray_level_max = static_cast<unsigned int>(val_max * pow(Ip + (1 - m_grayLevelPrecision), m_gamma));
701  if (m_gray_level_max > val_max) {
702  m_gray_level_max = val_max;
703  }
704 
705  track(I);
706 }
707 
735 void vpDot::initTracking(const vpImage<unsigned char> &I, const vpImagePoint &ip, unsigned int level_min,
736  unsigned int level_max)
737 {
738  m_cog = ip;
739 
740  m_gray_level_min = level_min;
741  m_gray_level_max = level_max;
742 
743  track(I);
744 }
745 
761 {
762  setGrayLevelOut();
763  double u = m_cog.get_u();
764  double v = m_cog.get_v();
765 
766  COG(I, u, v);
767 
768  m_cog.set_u(u);
769  m_cog.set_v(v);
770 
771  if (m_compute_moment == true) {
772  mu11 = m11 - (u * m01);
773  mu02 = m02 - (v * m01);
774  mu20 = m20 - (u * m10);
775  }
776 
777  if (m_graphics) {
778  const unsigned int val_3 = 3;
779  const unsigned int val_8 = 8;
780  // display a red cross at the center of gravity's location in the image.
781  vpDisplay::displayCross(I, m_cog, (val_3 * m_thickness) + val_8, vpColor::red, m_thickness);
782  }
783 }
784 
800 {
801  track(I);
802 
803  ip = m_cog;
804 }
805 
813 void vpDot::display(const vpImage<unsigned char> &I, vpColor color, unsigned int thick) const
814 {
815  const unsigned int val_3 = 3;
816  const unsigned int val_8 = 8;
817  vpDisplay::displayCross(I, m_cog, (val_3 * m_thickness) + val_8, color, thick);
818  std::list<vpImagePoint>::const_iterator it;
819 
820  std::list<vpImagePoint>::const_iterator m_ip_edges_list_end = m_ip_edges_list.end();
821  for (it = m_ip_edges_list.begin(); it != m_ip_edges_list_end; ++it) {
822  vpDisplay::displayPoint(I, *it, color);
823  }
824 }
825 
844 void vpDot::setGrayLevelPrecision(const double &precision)
845 {
846  double epsilon = 0.05;
847  if (m_grayLevelPrecision < epsilon) {
848  m_grayLevelPrecision = epsilon;
849  }
850  else if (m_grayLevelPrecision > 1) {
851  m_grayLevelPrecision = 1.0;
852  }
853  else {
854  m_grayLevelPrecision = precision;
855  }
856 }
857 
872 void vpDot::display(const vpImage<unsigned char> &I, const vpImagePoint &cog, const std::list<vpImagePoint> &edges_list,
873  vpColor color, unsigned int thickness)
874 {
875  const unsigned int val_3 = 3;
876  const unsigned int val_8 = 8;
877  vpDisplay::displayCross(I, cog, (val_3 * thickness) + val_8, color, thickness);
878  std::list<vpImagePoint>::const_iterator it;
879 
880  std::list<vpImagePoint>::const_iterator edges_list_end = edges_list.end();
881  for (it = edges_list.begin(); it != edges_list_end; ++it) {
882  vpDisplay::displayPoint(I, *it, color);
883  }
884 }
885 
900 void vpDot::display(const vpImage<vpRGBa> &I, const vpImagePoint &cog, const std::list<vpImagePoint> &edges_list,
901  vpColor color, unsigned int thickness)
902 {
903  const unsigned int val_3 = 3;
904  const unsigned int val_8 = 8;
905  vpDisplay::displayCross(I, cog, (val_3 * thickness) + val_8, color, thickness);
906  std::list<vpImagePoint>::const_iterator it;
907 
908  std::list<vpImagePoint>::const_iterator edges_list_end = edges_list.end();
909  for (it = edges_list.begin(); it != edges_list_end; ++it) {
910  vpDisplay::displayPoint(I, *it, color);
911  }
912 }
913 
919 VISP_EXPORT std::ostream &operator<<(std::ostream &os, vpDot &d) { return (os << "(" << d.getCog() << ")"); };
920 
921 END_VISP_NAMESPACE
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:614
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:157
static const vpColor red
Definition: vpColor.h:217
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
This tracker is meant to track a dot (connected pixels with same gray level) on a vpImage.
Definition: vpDot.h:116
void setMaxDotSize(double percentage)
Definition: vpDot.cpp:595
void display(const vpImage< unsigned char > &I, vpColor color=vpColor::red, unsigned int thickness=1) const
Definition: vpDot.cpp:813
bool operator!=(const vpDot &d) const
Definition: vpDot.cpp:188
void initTracking(const vpImage< unsigned char > &I)
Definition: vpDot.cpp:630
vpDot()
Definition: vpDot.cpp:100
vpDot & operator=(const vpDot &d)
Copy operator.
Definition: vpDot.cpp:150
void setGrayLevelPrecision(const double &grayLevelPrecision)
Definition: vpDot.cpp:844
virtual ~vpDot() VP_OVERRIDE
Destructor.
Definition: vpDot.cpp:145
@ CONNEXITY_8
Definition: vpDot.h:125
@ CONNEXITY_4
Definition: vpDot.h:123
bool operator==(const vpDot &d) const
Definition: vpDot.cpp:190
void track(const vpImage< unsigned char > &I)
Definition: vpDot.cpp:760
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
double get_j() const
Definition: vpImagePoint.h:125
double get_u() const
Definition: vpImagePoint.h:136
void set_u(double u)
Definition: vpImagePoint.h:335
void set_uv(double u, double v)
Definition: vpImagePoint.h:357
void set_v(double v)
Definition: vpImagePoint.h:346
double get_i() const
Definition: vpImagePoint.h:114
double get_v() const
Definition: vpImagePoint.h:147
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
Class that defines what is a feature generic tracker.
Definition: vpTracker.h:61
Error that can be emitted by the vpTracker class and its derivatives.
@ featureLostError
Tracker lost feature.
@ initializationError
Tracker initialization error.