Visual Servoing Platform  version 3.6.1 under development (2024-03-29)
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  }
115  else {
116  return 0;
117  }
118  }
119  else if (dx < 0 && dy >= 0) {
120  if (-dx >= dy) {
121  return 3;
122  }
123  else {
124  return 2;
125  }
126  }
127  else if (dx < 0 && dy < 0) {
128  if (dy <= dx) {
129  return 5;
130  }
131  else {
132  return 4;
133  }
134  }
135  else {
136  if (dx >= -dy) {
137  return 7;
138  }
139  else {
140  return 6;
141  }
142  }
143 }
144 
145 void drawLine(vpImage<unsigned char> &I, const unsigned char value, const vpImagePoint &imPt1_,
146  const vpImagePoint &imPt2_)
147 {
148  vpImagePoint imPt1((int)imPt1_.get_v(), (int)imPt1_.get_u());
149  vpImagePoint imPt2((int)imPt2_.get_v(), (int)imPt2_.get_u());
150 
151  int octant = getOctant(imPt1, imPt2);
152  imPt1 = switchToOctantZeroFrom(octant, imPt1);
153  imPt2 = switchToOctantZeroFrom(octant, imPt2);
154 
155  double dx = imPt2.get_u() - imPt1.get_u();
156  double dy = imPt2.get_v() - imPt1.get_v();
157  double D = 2 * dy - dx;
158  double y = imPt1.get_v();
159 
160  for (int x = (int)imPt1.get_u(); x <= (int)imPt2.get_u(); x++) {
161  vpImagePoint currentPt(y, x);
162  currentPt = switchFromOctantZeroTo(octant, currentPt);
163 
164  unsigned int i = std::min<unsigned int>(I.getHeight() - 1, (unsigned int)std::max<double>(0.0, currentPt.get_i()));
165  unsigned int j = std::min<unsigned int>(I.getWidth() - 1, (unsigned int)std::max<double>(0.0, currentPt.get_j()));
166  I[i][j] = value;
167 
168  if (D >= 0) {
169  y++;
170  D -= dx;
171  }
172 
173  D += dy;
174  }
175 }
177 } // namespace
178 
179 #endif
180 
181 int main()
182 {
184 #if defined(VISP_HAVE_MODULE_IMGPROC) && (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
186 
188  vpImage<vpRGBa> I(480, 640, vpRGBa());
190 
191 #ifdef VISP_HAVE_X11
192  vpDisplayX d;
193 #elif defined(VISP_HAVE_GDI)
194  vpDisplayGDI d;
195 #elif defined(HAVE_OPENCV_HIGHGUI)
196  vpDisplayOpenCV d;
197 #endif
198  d.init(I, 0, 0, "Paint");
199 
201  std::vector<vpPolygon> polygons;
202  for (int i = 0; i < 3; i++) {
204  std::stringstream ss;
205  ss << "Left click to draw polygon " << i + 1 << "/3"
206  << ", right click to close the shape.";
207  vpDisplay::displayText(I, 20, 20, ss.str(), vpColor::red);
208  vpDisplay::flush(I);
209 
210  vpPolygon polygon;
211  polygon.initClick(I);
212  polygons.push_back(polygon);
213 
215  vpDisplay::displayLine(I, polygon.getCorners(), true, vpColor::red);
216  vpDisplay::flush(I);
217 
218  // Update the lines draw internally in the current image
219  vpDisplay::getImage(I, I);
220  }
222 
224  vpImage<unsigned char> mask(I.getHeight(), I.getWidth(), 0);
225  for (size_t i = 0; i < polygons.size(); i++) {
226  if (polygons[i].getCorners().size() <= 1)
227  continue;
228 
229  for (size_t j = 0; j < polygons[i].getCorners().size() - 1; j++)
230  drawLine(mask, 255, polygons[i].getCorners()[j], polygons[i].getCorners()[j + 1]);
231 
232  drawLine(mask, 255, polygons[i].getCorners().front(), polygons[i].getCorners().back());
233  }
235 
236  bool quit = false;
237  while (!quit) {
239  vpDisplay::displayText(I, 20, 20,
240  "Left click on a pixel location to fill the "
241  "shape, right click to quit.",
242  vpColor::red);
243  vpDisplay::flush(I);
244 
246  vpImagePoint ip;
248  if (vpDisplay::getClick(I, ip, button, false))
250  {
251  switch (button) {
256 
258  for (unsigned int cpt = 0; cpt < mask.getSize(); cpt++) {
259  if (mask.bitmap[cpt])
260  I.bitmap[cpt] = vpColor::red;
261  }
263  break;
264 
266  quit = true;
267  break;
268 
269  default:
270  break;
271  }
272  }
273  }
274 #endif
275 
276  return EXIT_SUCCESS;
277 }
static const vpColor red
Definition: vpColor.h:211
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
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:128
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="") vp_override
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:138
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:82
double get_u() const
Definition: vpImagePoint.h:136
void set_uv(double u, double v)
Definition: vpImagePoint.h:352
double get_v() const
Definition: vpImagePoint.h:147
unsigned int getWidth() const
Definition: vpImage.h:245
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
unsigned int getHeight() const
Definition: vpImage.h:184
Defines a generic 2D polygon.
Definition: vpPolygon.h:97
const std::vector< vpImagePoint > & getCorners() const
Definition: vpPolygon.h:147
void initClick(const vpImage< unsigned char > &I, unsigned int size=5, const vpColor &color=vpColor::red, unsigned int thickness=1)
Definition: vpPolygon.cpp:258
Definition: vpRGBa.h:61
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:71