Visual Servoing Platform version 3.5.0
tutorial-flood-fill.cpp
1
2
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
15namespace
16{
18vpImagePoint 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
62vpImagePoint 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
106int 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
138void 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
174int 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)
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);
202
203 vpPolygon polygon;
204 polygon.initClick(I);
205 polygons.push_back(polygon);
206
210
211 // Update the lines draw internally in the current image
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.",
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:88
double get_u() const
Definition: vpImagePoint.h:262
void set_uv(double u, double v)
Definition: vpImagePoint.h:247
double get_v() const
Definition: vpImagePoint.h:273
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:104
const std::vector< vpImagePoint > & getCorners() const
Definition: vpPolygon.h:153
void initClick(const vpImage< unsigned char > &I, unsigned int size=5, const vpColor &color=vpColor::red, unsigned int thickness=1)
Definition: vpPolygon.cpp:173
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