使用Watershed算法在C++中进行OpenCV图像分割

3

您好,我正在使用OpenCV库编写基本的C++应用程序,以将图像中的主体与其背景分离。该应用程序读取一个图像文件,并使用分水岭算法,根据其发现在边缘周围和图像中心的数据来生成掩模。

(首先,我创建了一个图像对象,其整体值为-1。然后,在空图像周围创建一个值为1的边框。接着,我在图像中心大约创建了一个矩形,其值为2。边框和矩形没有接触。)

我尝试使用自动生成的掩模通过对原始图像和掩模进行逐位与操作来从图像中删除数据。

我用C++写了这个程序,如果有人能快速查看我的代码,我会非常感激。我找到的唯一相似的示例是使用Python的本地OpenCV绑定。

示例掩模:http://i.imgur.com/a0SUwy3.png

示例图像:http://i.imgur.com/FQywu6P.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;
}

1
那么,你有什么问题/疑问? - Niko
https://dev59.com/RWgu5IYBdhLWcg3we3Ct?rq=1 - Abid Rahman K
https://dev59.com/LWXWa4cB1Zd3GeqPSP7u?lq=1 - Abid Rahman K
@Niko,问题在于当我运行应用程序时它会崩溃。而Abid Rahman-第一个链接使用的是Python绑定,但并不完全相同,第二个链接是C++编写的,但没有使用bitwise_and()函数。非常感谢任何帮助。 - Hugh Pearse
//底部矩形 markers(Rect(0,image.rows-5,image.cols, 5)) = Scalar::all(1); - Cynichniy Bandera
1个回答

8

搞定了!

// 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;
}

附上两张图片:花卉图片叶子图片 - Hugh Pearse
3
如果您解决了自己的问题,完全可以并且也会受到赞赏地接受(accept)您自己的答案。我建议您指出您解决的问题,这对其他人会很有帮助。祝好运! - Pervez Alam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接