Home | History | Annotate | Download | only in cpp
      1 #include <opencv2/core/utility.hpp>
      2 #include "opencv2/imgproc.hpp"
      3 #include "opencv2/imgcodecs.hpp"
      4 #include "opencv2/highgui.hpp"
      5 
      6 #include <cstdio>
      7 #include <iostream>
      8 
      9 using namespace cv;
     10 using namespace std;
     11 
     12 static void help()
     13 {
     14     cout << "\nThis program demonstrates the famous watershed segmentation algorithm in OpenCV: watershed()\n"
     15             "Usage:\n"
     16             "./watershed [image_name -- default is ../data/fruits.jpg]\n" << endl;
     17 
     18 
     19     cout << "Hot keys: \n"
     20         "\tESC - quit the program\n"
     21         "\tr - restore the original image\n"
     22         "\tw or SPACE - run watershed segmentation algorithm\n"
     23         "\t\t(before running it, *roughly* mark the areas to segment on the image)\n"
     24         "\t  (before that, roughly outline several markers on the image)\n";
     25 }
     26 Mat markerMask, img;
     27 Point prevPt(-1, -1);
     28 
     29 static void onMouse( int event, int x, int y, int flags, void* )
     30 {
     31     if( x < 0 || x >= img.cols || y < 0 || y >= img.rows )
     32         return;
     33     if( event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON) )
     34         prevPt = Point(-1,-1);
     35     else if( event == EVENT_LBUTTONDOWN )
     36         prevPt = Point(x,y);
     37     else if( event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON) )
     38     {
     39         Point pt(x, y);
     40         if( prevPt.x < 0 )
     41             prevPt = pt;
     42         line( markerMask, prevPt, pt, Scalar::all(255), 5, 8, 0 );
     43         line( img, prevPt, pt, Scalar::all(255), 5, 8, 0 );
     44         prevPt = pt;
     45         imshow("image", img);
     46     }
     47 }
     48 
     49 int main( int argc, char** argv )
     50 {
     51     char* filename = argc >= 2 ? argv[1] : (char*)"../data/fruits.jpg";
     52     Mat img0 = imread(filename, 1), imgGray;
     53 
     54     if( img0.empty() )
     55     {
     56         cout << "Couldn'g open image " << filename << ". Usage: watershed <image_name>\n";
     57         return 0;
     58     }
     59     help();
     60     namedWindow( "image", 1 );
     61 
     62     img0.copyTo(img);
     63     cvtColor(img, markerMask, COLOR_BGR2GRAY);
     64     cvtColor(markerMask, imgGray, COLOR_GRAY2BGR);
     65     markerMask = Scalar::all(0);
     66     imshow( "image", img );
     67     setMouseCallback( "image", onMouse, 0 );
     68 
     69     for(;;)
     70     {
     71         int c = waitKey(0);
     72 
     73         if( (char)c == 27 )
     74             break;
     75 
     76         if( (char)c == 'r' )
     77         {
     78             markerMask = Scalar::all(0);
     79             img0.copyTo(img);
     80             imshow( "image", img );
     81         }
     82 
     83         if( (char)c == 'w' || (char)c == ' ' )
     84         {
     85             int i, j, compCount = 0;
     86             vector<vector<Point> > contours;
     87             vector<Vec4i> hierarchy;
     88 
     89             findContours(markerMask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
     90 
     91             if( contours.empty() )
     92                 continue;
     93             Mat markers(markerMask.size(), CV_32S);
     94             markers = Scalar::all(0);
     95             int idx = 0;
     96             for( ; idx >= 0; idx = hierarchy[idx][0], compCount++ )
     97                 drawContours(markers, contours, idx, Scalar::all(compCount+1), -1, 8, hierarchy, INT_MAX);
     98 
     99             if( compCount == 0 )
    100                 continue;
    101 
    102             vector<Vec3b> colorTab;
    103             for( i = 0; i < compCount; i++ )
    104             {
    105                 int b = theRNG().uniform(0, 255);
    106                 int g = theRNG().uniform(0, 255);
    107                 int r = theRNG().uniform(0, 255);
    108 
    109                 colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
    110             }
    111 
    112             double t = (double)getTickCount();
    113             watershed( img0, markers );
    114             t = (double)getTickCount() - t;
    115             printf( "execution time = %gms\n", t*1000./getTickFrequency() );
    116 
    117             Mat wshed(markers.size(), CV_8UC3);
    118 
    119             // paint the watershed image
    120             for( i = 0; i < markers.rows; i++ )
    121                 for( j = 0; j < markers.cols; j++ )
    122                 {
    123                     int index = markers.at<int>(i,j);
    124                     if( index == -1 )
    125                         wshed.at<Vec3b>(i,j) = Vec3b(255,255,255);
    126                     else if( index <= 0 || index > compCount )
    127                         wshed.at<Vec3b>(i,j) = Vec3b(0,0,0);
    128                     else
    129                         wshed.at<Vec3b>(i,j) = colorTab[index - 1];
    130                 }
    131 
    132             wshed = wshed*0.5 + imgGray*0.5;
    133             imshow( "watershed transform", wshed );
    134         }
    135     }
    136 
    137     return 0;
    138 }
    139