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 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 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 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