Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Watershed problems.

Hello everyone. I would very much appreciate if you take a look at my code and point me what I am doing wrong :(

The story is this. There is an image of some coins. I take the background and the foreground. Paint the background in grey and the foreground in white. Then apply watershed. As a result I got the border of the coins. (I know that is not the final objective but allow me)

Then I modify the code to change the foreground. I get borders of this and get a new foreground *that seems to be exactly the same as * the previous foreground. However when I apply the watershed the results are totally different.

WHY??

image description

In the image you can see the first result in the middle and the second result to the left.

Now here is my code

    #include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;



int main( int argc, char** argv )
{
    //Read input data
     char* filename = argc >= 2 ? argv[1] : (char*)"water_coins.jpg";
     Mat image = imread(filename, 1);

    if(!image.data) {
    cout<<"Can't read the image"<<endl; 
        return 0;
    }
    //Display the image
    imshow("Original Image", image);


    //Get the binary map
    Mat gray,binary;
    cvtColor(image,gray,COLOR_BGR2GRAY);
//  threshold(gray,binary,60,255,THRESH_BINARY_INV);
    threshold(gray,binary,0,255,THRESH_BINARY_INV+THRESH_OTSU);

    //Display the binary image
    imshow("Binary Image",binary);


    //Identify Image pixels without objects and asign it grey (128) (sure background)
    Mat bg;
    dilate(binary,bg,Mat(),Point(-1,-1),6);
    threshold(bg,bg,1,128,THRESH_BINARY_INV);

    imshow("Background Image",bg);

    //Now we have to find sure foreground
   //First we erode the image

    Mat fg;
    erode(binary,fg,Mat(),Point(-1,-1),10);
    imshow("Foreground Image",fg);









    //then find the contours (We use a clone because findContours modifies the original image passed to it
    Mat fg_clone=fg.clone();

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    findContours(fg_clone, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

    Mat cnt_img = Mat::zeros(image.rows, image.cols, CV_8UC1);

     drawContours(cnt_img, contours, -1, Scalar(255,255,255),
                  -1, CV_AA, hierarchy);
//   drawContours(cnt_img, contours, -1, Scalar(128,255,255),
 //                 3, CV_AA, hierarchy);


 //   for(int idx = 0; idx < contours.size(); idx++)
  //      drawContours(cnt_img, contours, idx, Scalar::all(idx + 1), -1, CV_AA);


    imshow("contours", cnt_img);


     cout << "Extracted " << contours.size() << " contours" << endl;

    //Try and erase later

    //Combine the images
    Mat markers(binary.size(),CV_8U,Scalar(0));
    markers= fg+bg;         //THIS produces result #1
    //markers= cnt_img+bg;  //THIS produces result #2

    imshow("Markers",markers);


    int count=contours.size();
    //watershed

    Mat markerIm;
    markers.convertTo(markerIm,CV_32SC1);

    watershed(image,markerIm);

     vector<Vec3b> colorTab;
    for(int i = 0; i < (contours.size()+1); i++) {
        int b = theRNG().uniform(0, 255);
        int g = theRNG().uniform(0, 255);
        int r = theRNG().uniform(0, 255);

        colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
    }

   // watershed output image
    Mat wshed(markerIm.size(), CV_8UC3);

    // paint the watershed output image
    for(int i = 0; i < markerIm.rows; i++)
        for(int j = 0; j < markerIm.cols; j++) {
            int index = markerIm.at<int>(i, j);
            if(index == -1)
                wshed.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
            else if(index <= 0 || index > count)
                wshed.at<Vec3b>(i, j) = Vec3b(0, 0, 0);
            else
                wshed.at<Vec3b>(i, j) = colorTab[index - 1];
        }

    imshow("Segmentation", wshed);

    cv::waitKey();
    return 0;
}

Notice the comments where it says THIS produces result #1 and THIS produces result #2 uncomment one of those to produces one or the other result.

Now as far as I can see fg and cnt_img produces the same image, so why the results are different?

Any help or comment greatly appreciated. Thanks