3

Hi i'm currently writing a basic C++ application using the OpenCV library to segment the subject of the image from its background. The application reads in an image file and uses the watershed algorithm to generate a mask based on data it finds around the edges and data it finds in the centre of the image.

(To start I created an image object that has an overall value of -1. Then I created a border around an empty image which has a value of 1. Then I created a rectangle roughly in the centre of the image which has a value of 2. The border and the rectangle are not touching.)

I attempt to remove data from the image using the generated mask using a bitwise AND between the original image and the auto-generated mask.

I have written this in C++ and would be very grateful if someone could take a quick look at my code. The only similar example I could find was using the native OpenCV bindings for Python.

Sample Mask: https://i.sstatic.net/wW0PJ.png

Sample Image: https://i.sstatic.net/w2Tpp.png

// 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 blank(image.size(),CV_8U,cv::Scalar(0xFF));
    cv::Mat dest(image.size(),CV_8U,cv::Scalar(0xFF));
    imshow("originalimage", image);

    // Create markers image
    cv::Mat markers(image.size(),CV_8U,cv::Scalar(-1));
    //Rect(topleftcornerX, topleftcornerY, width, height);
    //top rectangle
    markers(Rect(0,0,image.cols, 5)) = Scalar::all(1);
    //bottom rectangle
    markers(Rect(0,image.cols-5,image.cols, 5)) = Scalar::all(1);
    //left rectangle
    markers(Rect(0,0,5,image.rows)) = Scalar::all(1);
    //right rectangle
    markers(Rect(image.cols-5,0,5,image.rows)) = Scalar::all(1);
    //centre rectangle
    markers(Rect(image.cols/2,image.rows/2,50, 50)) = Scalar::all(2);


    //Create watershed segmentation object
    WatershedSegmenter segmenter;
    segmenter.setMarkers(markers);
    cv::Mat result = segmenter.process(image);
    result.convertTo(result,CV_8U);

    bitwise_and(image, blank, dest, result);
    imshow("final_result", dest);

    cv::waitKey(0);

    return 0;
}
5
  • 1
    So, what is your problem / question? Commented Apr 17, 2013 at 20:36
  • stackoverflow.com/questions/11294859/… Commented Apr 18, 2013 at 4:10
  • stackoverflow.com/questions/11435974/… Commented Apr 18, 2013 at 4:10
  • @Niko The problem is that the application crashes when I run it. And Abid Rahman - That first link uses the python bindings which are not identical, and the second link is in C++ but does not use bitwise_and(). Any help would be greatly appreciated. Commented Apr 18, 2013 at 9:10
  • //bottom rectangle markers(Rect(0,image.rows-5,image.cols, 5)) = Scalar::all(1); Commented Jul 14, 2017 at 9:53

1 Answer 1

8

Got it working!

// 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 blank(image.size(),CV_8U,cv::Scalar(0xFF));
    cv::Mat dest;
    imshow("originalimage", image);

    // Create markers image
    cv::Mat markers(image.size(),CV_8U,cv::Scalar(-1));
    //Rect(topleftcornerX, topleftcornerY, width, height);
    //top rectangle
    markers(Rect(0,0,image.cols, 5)) = Scalar::all(1);
    //bottom rectangle
    markers(Rect(0,image.rows-5,image.cols, 5)) = Scalar::all(1);
    //left rectangle
    markers(Rect(0,0,5,image.rows)) = Scalar::all(1);
    //right rectangle
    markers(Rect(image.cols-5,0,5,image.rows)) = Scalar::all(1);
    //centre rectangle
    int centreW = image.cols/4;
    int centreH = image.rows/4;
    markers(Rect((image.cols/2)-(centreW/2),(image.rows/2)-(centreH/2), centreW, centreH)) = Scalar::all(2);
    markers.convertTo(markers,CV_BGR2GRAY);
    imshow("markers", markers);

    //Create watershed segmentation object
    WatershedSegmenter segmenter;
    segmenter.setMarkers(markers);
    cv::Mat wshedMask = segmenter.process(image);
    cv::Mat mask;
    convertScaleAbs(wshedMask, mask, 1, 0);
    double thresh = threshold(mask, mask, 1, 255, THRESH_BINARY);
    bitwise_and(image, image, dest, mask);
    dest.convertTo(dest,CV_8U);

    imshow("final_result", dest);
    cv::waitKey(0);

    return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

attached 2 images flower-image leaf-image
@Hugh If you solved your own problem, it is completely fine and appreciated to accept your own answer. I suggest you to point the problem you resolved, it can be helpful for others. Good Luck.

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.