Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
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(HAVE_OPENCV_HIGHGUI)
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:211
Display for windows using GDI (available on any windows 32 platform).
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:132
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)
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 ...
double get_u() const
void set_uv(double u, double v)
double get_v() const
Definition of the vpImage class member functions.
Definition vpImage.h:135
unsigned int getWidth() const
Definition vpImage.h:242
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)
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)