1 #include "opencv2/imgproc/imgproc.hpp"
2 #include "opencv2/imgcodecs.hpp"
3 #include "opencv2/videoio/videoio.hpp"
4 #include "opencv2/highgui/highgui.hpp"
5 
6 #include <iostream>
7 
8 using namespace cv;
9 using namespace std;
10 
help()11 static void help()
12 {
13     cout << "\nThis program demonstrated the floodFill() function\n"
14             "Call:\n"
15             "./ffilldemo [image_name -- Default: ../data/fruits.jpg]\n" << endl;
16 
17     cout << "Hot keys: \n"
18             "\tESC - quit the program\n"
19             "\tc - switch color/grayscale mode\n"
20             "\tm - switch mask mode\n"
21             "\tr - restore the original image\n"
22             "\ts - use null-range floodfill\n"
23             "\tf - use gradient floodfill with fixed(absolute) range\n"
24             "\tg - use gradient floodfill with floating(relative) range\n"
25             "\t4 - use 4-connectivity mode\n"
26             "\t8 - use 8-connectivity mode\n" << endl;
27 }
28 
29 Mat image0, image, gray, mask;
30 int ffillMode = 1;
31 int loDiff = 20, upDiff = 20;
32 int connectivity = 4;
33 int isColor = true;
34 bool useMask = false;
35 int newMaskVal = 255;
36 
onMouse(int event,int x,int y,int,void *)37 static void onMouse( int event, int x, int y, int, void* )
38 {
39     if( event != EVENT_LBUTTONDOWN )
40         return;
41 
42     Point seed = Point(x,y);
43     int lo = ffillMode == 0 ? 0 : loDiff;
44     int up = ffillMode == 0 ? 0 : upDiff;
45     int flags = connectivity + (newMaskVal << 8) +
46                 (ffillMode == 1 ? FLOODFILL_FIXED_RANGE : 0);
47     int b = (unsigned)theRNG() & 255;
48     int g = (unsigned)theRNG() & 255;
49     int r = (unsigned)theRNG() & 255;
50     Rect ccomp;
51 
52     Scalar newVal = isColor ? Scalar(b, g, r) : Scalar(r*0.299 + g*0.587 + b*0.114);
53     Mat dst = isColor ? image : gray;
54     int area;
55 
56     if( useMask )
57     {
58         threshold(mask, mask, 1, 128, THRESH_BINARY);
59         area = floodFill(dst, mask, seed, newVal, &ccomp, Scalar(lo, lo, lo),
60                   Scalar(up, up, up), flags);
61         imshow( "mask", mask );
62     }
63     else
64     {
65         area = floodFill(dst, seed, newVal, &ccomp, Scalar(lo, lo, lo),
66                   Scalar(up, up, up), flags);
67     }
68 
69     imshow("image", dst);
70     cout << area << " pixels were repainted\n";
71 }
72 
73 
main(int argc,char ** argv)74 int main( int argc, char** argv )
75 {
76     char* filename = argc >= 2 ? argv[1] : (char*)"../data/fruits.jpg";
77     image0 = imread(filename, 1);
78 
79     if( image0.empty() )
80     {
81         cout << "Image empty. Usage: ffilldemo <image_name>\n";
82         return 0;
83     }
84     help();
85     image0.copyTo(image);
86     cvtColor(image0, gray, COLOR_BGR2GRAY);
87     mask.create(image0.rows+2, image0.cols+2, CV_8UC1);
88 
89     namedWindow( "image", 0 );
90     createTrackbar( "lo_diff", "image", &loDiff, 255, 0 );
91     createTrackbar( "up_diff", "image", &upDiff, 255, 0 );
92 
93     setMouseCallback( "image", onMouse, 0 );
94 
95     for(;;)
96     {
97         imshow("image", isColor ? image : gray);
98 
99         int c = waitKey(0);
100         if( (c & 255) == 27 )
101         {
102             cout << "Exiting ...\n";
103             break;
104         }
105         switch( (char)c )
106         {
107         case 'c':
108             if( isColor )
109             {
110                 cout << "Grayscale mode is set\n";
111                 cvtColor(image0, gray, COLOR_BGR2GRAY);
112                 mask = Scalar::all(0);
113                 isColor = false;
114             }
115             else
116             {
117                 cout << "Color mode is set\n";
118                 image0.copyTo(image);
119                 mask = Scalar::all(0);
120                 isColor = true;
121             }
122             break;
123         case 'm':
124             if( useMask )
125             {
126                 destroyWindow( "mask" );
127                 useMask = false;
128             }
129             else
130             {
131                 namedWindow( "mask", 0 );
132                 mask = Scalar::all(0);
133                 imshow("mask", mask);
134                 useMask = true;
135             }
136             break;
137         case 'r':
138             cout << "Original image is restored\n";
139             image0.copyTo(image);
140             cvtColor(image, gray, COLOR_BGR2GRAY);
141             mask = Scalar::all(0);
142             break;
143         case 's':
144             cout << "Simple floodfill mode is set\n";
145             ffillMode = 0;
146             break;
147         case 'f':
148             cout << "Fixed Range floodfill mode is set\n";
149             ffillMode = 1;
150             break;
151         case 'g':
152             cout << "Gradient (floating range) floodfill mode is set\n";
153             ffillMode = 2;
154             break;
155         case '4':
156             cout << "4-connectivity mode is set\n";
157             connectivity = 4;
158             break;
159         case '8':
160             cout << "8-connectivity mode is set\n";
161             connectivity = 8;
162             break;
163         }
164     }
165 
166     return 0;
167 }
168