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