Visual Servoing Platform  version 3.5.1 under development (2022-12-01)
tutorial-flood-fill.cpp
1 
3 #include <cstdlib>
4 #include <iostream>
5 #include <visp3/core/vpImage.h>
6 #include <visp3/gui/vpDisplayGDI.h>
7 #include <visp3/gui/vpDisplayOpenCV.h>
8 #include <visp3/gui/vpDisplayX.h>
9 
10 #if defined(VISP_HAVE_MODULE_IMGPROC) && (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
12 #include <visp3/imgproc/vpImgproc.h>
14 
15 namespace
16 {
18 vpImagePoint switchToOctantZeroFrom(const int octant, const vpImagePoint &imPt)
19 {
20  vpImagePoint imPt_switched = imPt;
21 
22  switch (octant) {
23  case 0: // return (x, y)
24  imPt_switched.set_uv(imPt.get_u(), imPt.get_v());
25  break;
26 
27  case 1: // return (y, x)
28  imPt_switched.set_uv(imPt.get_v(), imPt.get_u());
29  break;
30 
31  case 2: // return (y, -x)
32  imPt_switched.set_uv(imPt.get_v(), -imPt.get_u());
33  break;
34 
35  case 3: // return (-x, y)
36  imPt_switched.set_uv(-imPt.get_u(), imPt.get_v());
37  break;
38 
39  case 4: // return (-x, -y)
40  imPt_switched.set_uv(-imPt.get_u(), -imPt.get_v());
41  break;
42 
43  case 5: // return (-y, -x)
44  imPt_switched.set_uv(-imPt.get_v(), -imPt.get_u());
45  break;
46 
47  case 6: // return (-y, x)
48  imPt_switched.set_uv(-imPt.get_v(), imPt.get_u());
49  break;
50 
51  case 7: // return (x, -y)
52  imPt_switched.set_uv(imPt.get_u(), -imPt.get_v());
53  break;
54 
55  default:
56  break;
57  }
58 
59  return imPt_switched;
60 }
61 
62 vpImagePoint switchFromOctantZeroTo(const int octant, const vpImagePoint &imPt)
63 {
64  vpImagePoint imPt_switched = imPt;
65 
66  switch (octant) {
67  case 0: // return (x, y)
68  imPt_switched.set_uv(imPt.get_u(), imPt.get_v());
69  break;
70 
71  case 1: // return (y, x)
72  imPt_switched.set_uv(imPt.get_v(), imPt.get_u());
73  break;
74 
75  case 2: // return (-y, x)
76  imPt_switched.set_uv(-imPt.get_v(), imPt.get_u());
77  break;
78 
79  case 3: // return (-x, y)
80  imPt_switched.set_uv(-imPt.get_u(), imPt.get_v());
81  break;
82 
83  case 4: // return (-x, -y)
84  imPt_switched.set_uv(-imPt.get_u(), -imPt.get_v());
85  break;
86 
87  case 5: // return (-y, -x)
88  imPt_switched.set_uv(-imPt.get_v(), -imPt.get_u());
89  break;
90 
91  case 6: // return (y, -x)
92  imPt_switched.set_uv(imPt.get_v(), -imPt.get_u());
93  break;
94 
95  case 7: // return (x, -y)
96  imPt_switched.set_uv(imPt.get_u(), -imPt.get_v());
97  break;
98 
99  default:
100  break;
101  }
102 
103  return imPt_switched;
104 }
105 
106 int getOctant(const vpImagePoint &imPt1, const vpImagePoint &imPt2)
107 {
108  double dx = imPt2.get_u() - imPt1.get_u();
109  double dy = imPt2.get_v() - imPt1.get_v();
110 
111  if (dx >= 0 && dy >= 0) {
112  if (dy >= dx) {
113  return 1;
114  } else {
115  return 0;
116  }
117  } else if (dx < 0 && dy >= 0) {
118  if (-dx >= dy) {
119  return 3;
120  } else {
121  return 2;
122  }
123  } else if (dx < 0 && dy < 0) {
124  if (dy <= dx) {
125  return 5;
126  } else {
127  return 4;
128  }
129  } else {
130  if (dx >= -dy) {
131  return 7;
132  } else {
133  return 6;
134  }
135  }
136 }
137 
138 void drawLine(vpImage<unsigned char> &I, const unsigned char value, const vpImagePoint &imPt1_,
139  const vpImagePoint &imPt2_)
140 {
141  vpImagePoint imPt1((int)imPt1_.get_v(), (int)imPt1_.get_u());
142  vpImagePoint imPt2((int)imPt2_.get_v(), (int)imPt2_.get_u());
143 
144  int octant = getOctant(imPt1, imPt2);
145  imPt1 = switchToOctantZeroFrom(octant, imPt1);
146  imPt2 = switchToOctantZeroFrom(octant, imPt2);
147 
148  double dx = imPt2.get_u() - imPt1.get_u();
149  double dy = imPt2.get_v() - imPt1.get_v();
150  double D = 2 * dy - dx;
151  double y = imPt1.get_v();
152 
153  for (int x = (int)imPt1.get_u(); x <= (int)imPt2.get_u(); x++) {
154  vpImagePoint currentPt(y, x);
155  currentPt = switchFromOctantZeroTo(octant, currentPt);
156 
157  unsigned int i = std::min(I.getHeight() - 1, (unsigned int)std::max(0.0, currentPt.get_i()));
158  unsigned int j = std::min(I.getWidth() - 1, (unsigned int)std::max(0.0, currentPt.get_j()));
159  I[i][j] = value;
160 
161  if (D >= 0) {
162  y++;
163  D -= dx;
164  }
165 
166  D += dy;
167  }
168 }
170 } // namespace
171 
172 #endif
173 
174 int main()
175 {
177 #if defined(VISP_HAVE_MODULE_IMGPROC) && (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
179 
181  vpImage<vpRGBa> I(480, 640, vpRGBa());
183 
184 #ifdef VISP_HAVE_X11
185  vpDisplayX d;
186 #elif defined(VISP_HAVE_GDI)
187  vpDisplayGDI d;
188 #elif defined(VISP_HAVE_OPENCV)
189  vpDisplayOpenCV d;
190 #endif
191  d.init(I, 0, 0, "Paint");
192 
194  std::vector<vpPolygon> polygons;
195  for (int i = 0; i < 3; i++) {
197  std::stringstream ss;
198  ss << "Left click to draw polygon " << i + 1 << "/3"
199  << ", right click to close the shape.";
200  vpDisplay::displayText(I, 20, 20, ss.str(), vpColor::red);
201  vpDisplay::flush(I);
202 
203  vpPolygon polygon;
204  polygon.initClick(I);
205  polygons.push_back(polygon);
206 
208  vpDisplay::displayLine(I, polygon.getCorners(), true, vpColor::red);
209  vpDisplay::flush(I);
210 
211  // Update the lines draw internally in the current image
212  vpDisplay::getImage(I, I);
213  }
215 
217  vpImage<unsigned char> mask(I.getHeight(), I.getWidth(), 0);
218  for (size_t i = 0; i < polygons.size(); i++) {
219  if (polygons[i].getCorners().size() <= 1)
220  continue;
221 
222  for (size_t j = 0; j < polygons[i].getCorners().size() - 1; j++)
223  drawLine(mask, 255, polygons[i].getCorners()[j], polygons[i].getCorners()[j + 1]);
224 
225  drawLine(mask, 255, polygons[i].getCorners().front(), polygons[i].getCorners().back());
226  }
228 
229  bool quit = false;
230  while (!quit) {
232  vpDisplay::displayText(I, 20, 20,
233  "Left click on a pixel location to fill the "
234  "shape, right click to quit.",
235  vpColor::red);
236  vpDisplay::flush(I);
237 
239  vpImagePoint ip;
241  if (vpDisplay::getClick(I, ip, button, false))
243  {
244  switch (button) {
249 
251  for (unsigned int cpt = 0; cpt < mask.getSize(); cpt++) {
252  if (mask.bitmap[cpt])
253  I.bitmap[cpt] = vpColor::red;
254  }
256  break;
257 
259  quit = true;
260  break;
261 
262  default:
263  break;
264  }
265  }
266  }
267 #endif
268 
269  return EXIT_SUCCESS;
270 }
static const vpColor red
Definition: vpColor.h:217
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:129
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:135
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
Definition: vpDisplay.cpp:144
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:89
double get_u() const
Definition: vpImagePoint.h:143
void set_uv(double u, double v)
Definition: vpImagePoint.h:357
double get_v() const
Definition: vpImagePoint.h:154
unsigned int getWidth() const
Definition: vpImage.h:246
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
unsigned int getHeight() const
Definition: vpImage.h:188
Defines a generic 2D polygon.
Definition: vpPolygon.h:106
const std::vector< vpImagePoint > & getCorners() const
Definition: vpPolygon.h:156
void initClick(const vpImage< unsigned char > &I, unsigned int size=5, const vpColor &color=vpColor::red, unsigned int thickness=1)
Definition: vpPolygon.cpp:265
Definition: vpRGBa.h:67
VISP_EXPORT void floodFill(vpImage< unsigned char > &I, const vpImagePoint &seedPoint, const unsigned char oldValue, const unsigned char newValue, const vpImageMorphology::vpConnexityType &connexity=vpImageMorphology::CONNEXITY_4)
Definition: vpFloodFill.cpp:85