【问题标题】:watershed segmentation opencv xcode分水岭分割opencv xcode
【发布时间】:2012-07-11 06:24:35
【问题描述】:

我现在正在学习 opencv 代码书(OpenCV 2 计算机视觉应用程序编程手册)中的代码:第 5 章,使用分水岭分割图像,第 131 页。

这是我的主要代码:

#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);
}

但是,它不起作用。如何初始化二进制图像?我怎样才能使这个分段代码工作?

我对这本书的这一部分不是很清楚。 提前致谢!

【问题讨论】:

  • 您好,您对代码理解有问题吗?还要检查使用的 OpenCV 的版本。我也听说那本书有一些错误,我没有查过。
  • 我使用的是 opencv 2.4.1...是的,我在理解这段代码时有些困难...
  • 您可以查看我在答案中设置的链接。不是关于算法如何工作,而是如何使用它。

标签: c++ xcode opencv image-processing watershed


【解决方案1】:

下面是您的代码的简化版本,它对我来说很好用。看看吧:

#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);
}

下面是我的输入图片:

下面是我的输出图像:

这里查看代码说明:Simple watershed Sample in OpenCV

【讨论】:

  • 谢谢!我有一个问题:sofwatershed.jpg和sofwsthresh.png是什么关系?
  • 哦。我很抱歉。 softwatershed.png 是原始图像。 softwsthresh.png 是阈值图像。其实我用的是Python。所以我不想在 C++ 中再次对其进行二值化。您可以在我最后提供的链接中找到这些图片。
  • 我有一个问题,你最终的分割图是哪张图?是mat图吗?我的分水岭函数后的图和原图一样...
  • 第二张图片是结果。实际上我一点也不擅长 C++。我只使用 Python。
  • @AbidRahmanK +1 我赞成您对该倡议的回答,但这不会向 OP 显示他的错误。所以我也添加了一个答案。
【解决方案2】:

关于您的代码,有几点需要提及:

  • Watershed 期望输入和输出图像具有相同的大小;
  • 您可能希望去掉方法中的const 参数;
  • 请注意,分水岭的结果实际上是markers 而不是image,正如您的代码所建议的那样;关于这个,你需要抓住process()的回报!

这是你的代码,上面有修复:

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

我冒昧地使用 Abid 的输入图像进行测试,这就是我得到的:

【讨论】:

  • 酷!它的工作原理!原始图像和二进制图像的大小应该相同。谢谢!
  • 这是从 2012 年开始的。从那时起,OpenCV API 可能已经发生了一些变化。你有什么问题?
  • @karlphillip 我认为他指的是没有发生分段的事实?
  • @Daniel "Not working" 是对问题的错误定义。如果没有更多技术信息,我无法帮助任何人。
  • @Daniel 感谢您的 cmets。我永远不会从有人说“它不起作用”中弄清楚所有这些。我的第一个猜测是编译器或链接器相关的问题。
【解决方案3】:

我遇到了和你一样的问题,按照食谱的完全相同的代码示例(顺便说一句很棒的书)。

只是将我正在编码的问题放在 Visual Studio 2013 和 OpenCV 2.4.8 下。经过大量搜索但没有解决方案,我决定更改 IDE。

它仍然是 Visual Studio,但它是 2010 年!!!!并且成功了!

注意如何使用 OpenCV 配置 Visual Studio。这是一个很棒的安装教程here

祝大家今天好

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多