4

I am now learning a code from the opencv codebook (OpenCV 2 Computer Vision Application Programming Cookbook): Chapter 5, Segmenting images using watersheds, page 131.

Here is my main code:

#include "opencv2/opencv.hpp"
#include <string>

using namespace cv;
using namespace std;

class WatershedSegmenter {
    private:
    cv::Mat markers;
    public:
    void setMarkers(const cv::Mat& markerImage){
        markerImage.convertTo(markers, CV_32S);
    }

    cv::Mat process(const cv::Mat &image){
        cv::watershed(image,markers);
        return markers;
    }
};

int main ()
{
    cv::Mat image = cv::imread("/Users/yaozhongsong/Pictures/IMG_1648.JPG");

    // Eliminate noise and smaller objects
    cv::Mat fg;
    cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),6);

    // Identify image pixels without objects
    cv::Mat bg;
    cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),6);
    cv::threshold(bg,bg,1,128,cv::THRESH_BINARY_INV);

    // Create markers image
    cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
    markers= fg+bg;

    // Create watershed segmentation object
    WatershedSegmenter segmenter;
    // Set markers and process
    segmenter.setMarkers(markers);
    segmenter.process(image);

    imshow("a",image);
    std::cout<<".";
    cv::waitKey(0);
}

However, it doesn't work. How could I initialize a binary image? And how could I make this segmentation code work?

I am not very clear about this part of the book. Thanks in advance!

3
  • Hi, Is your problem with understanding the code? Also check the versions of the OpenCV used. I have also heard that there are some errors in that book, i haven't checked it. Commented Jul 11, 2012 at 16:42
  • I am using opencv 2.4.1...yea, I have some difficulty understanding this code... Commented Jul 11, 2012 at 18:35
  • You can check the link i have set in my answer. Not about how algorithm works, but how it function can be used. Commented Jul 11, 2012 at 18:36

3 Answers 3

11

There's a couple of things that should be mentioned about your code:

  • Watershed expects the input and the output image to have the same size;
  • You probably want to get rid of the const parameters in the methods;
  • Notice that the result of watershed is actually markers and not image as your code suggests; About that, you need to grab the return of process()!

This is your code, with the fixes above:

// Usage: ./app input.jpg
#include "opencv2/opencv.hpp"
#include <string>

using namespace cv;
using namespace std;

class WatershedSegmenter{
private:
    cv::Mat markers;
public:
    void setMarkers(cv::Mat& markerImage)
    {
        markerImage.convertTo(markers, CV_32S);
    }

    cv::Mat process(cv::Mat &image)
    {
        cv::watershed(image, markers);
        markers.convertTo(markers,CV_8U);
        return markers;
    }
};


int main(int argc, char* argv[])
{
    cv::Mat image = cv::imread(argv[1]);
    cv::Mat binary;// = cv::imread(argv[2], 0);
    cv::cvtColor(image, binary, CV_BGR2GRAY);
    cv::threshold(binary, binary, 100, 255, THRESH_BINARY);

    imshow("originalimage", image);
    imshow("originalbinary", binary);

    // Eliminate noise and smaller objects
    cv::Mat fg;
    cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),2);
    imshow("fg", fg);

    // Identify image pixels without objects
    cv::Mat bg;
    cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),3);
    cv::threshold(bg,bg,1, 128,cv::THRESH_BINARY_INV);
    imshow("bg", bg);

    // Create markers image
    cv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));
    markers= fg+bg;
    imshow("markers", markers);

    // Create watershed segmentation object
    WatershedSegmenter segmenter;
    segmenter.setMarkers(markers);

    cv::Mat result = segmenter.process(image);
    result.convertTo(result,CV_8U);
    imshow("final_result", result);

    cv::waitKey(0);

    return 0;
}

I took the liberty of using Abid's input image for testing and this is what I got:

enter image description here

Sign up to request clarification or add additional context in comments.

8 Comments

cool!it works!the size of original image and binary image should be the same. Thx!
This is from 2012. OpenCV API may have changed a bit since then. What problems are you having?
@karlphillip I think he is referring to the fact that no segmentation has occurred?
@Daniel "Not working" is a poor definition of the problem. I can't help anyone without more technical information.
@Daniel Thanks for your comments. I would have never figured out all of that just from someone saying "It's not working". My first guess would be a compiler or a linker-related issue.
|
4

Below is the simplified version of your code, and it works fine for me. Check it out :

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;

int main ()
{
    Mat image = imread("sofwatershed.jpg");
    Mat binary = imread("sofwsthresh.png",0);

    // Eliminate noise and smaller objects
    Mat fg;
    erode(binary,fg,Mat(),Point(-1,-1),2);

    // Identify image pixels without objects
    Mat bg;
    dilate(binary,bg,Mat(),Point(-1,-1),3);
    threshold(bg,bg,1,128,THRESH_BINARY_INV);

// Create markers image
    Mat markers(binary.size(),CV_8U,Scalar(0));
    markers= fg+bg;

markers.convertTo(markers, CV_32S);
watershed(image,markers);

markers.convertTo(markers,CV_8U);
imshow("a",markers);
waitKey(0);
}

Below is my input image :

enter image description here

Below is my output image :

enter image description here

See the code explanation here : Simple watershed Sample in OpenCV

6 Comments

Thx! I have one question: what's the relationship between sofwatershed.jpg and sofwsthresh.png?
OH. i am sorry. sofwatershed.png is the original image. sofwsthresh.png is the thresholded image. Actually i used Python. So i didn't want to binarize it again in C++. You can find those images in the link i have provided at end.
I have a question, which image is your final segmentation image?is mat image?my image after the watershed function is the same as the original image...
second image is the result. Actually i am not at all good in C++. I use Python only.
@AbidRahmanK +1 I upvoted your answer for the initiative, but that won't show the OP his mistakes. So I added an answer as well.
|
0

I had the same problem as you, following the exact same code sample of the cookbook (great book btw).

Just to place the matter I was coding under Visual Studio 2013 and OpenCV 2.4.8. After a lot of searching and no solutions I decided to change the IDE.

It's still Visual Studio BUT it's 2010!!!! And boom it works!

Becareful of how you configure Visual Studio with OpenCV. Here's a great tutorial for installation here

Good day to all

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.