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}