运行环境:ubuntu16.04+Qt+opencv2.4.13
参考链接:http://blog.csdn.net/u010741471/article/details/45193521
watershedsegmenter.h
#ifndef WATERSHEDSEGMENTER
#define WATERSHEDSEGMENTER
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
class WatershedSegmenter {
private:
//用来表示标记(图)
cv::Mat markers;
public:
//设置标记图
void setMarkers(const cv::Mat& markerImage) {
//watershed()的输入参数必须为一个32位有符号的标记,所以要先进行转换
markerImage.convertTo(markers,CV_32S);
}
//执行watershed()
cv::Mat process(const cv::Mat &image) {
// Apply watershed
cv::watershed(image,markers);
return markers;
}
// 以图像形式返回结果
cv::Mat getSegmentation() {
cv::Mat tmp;
// 从32S到8U(0-255)会进行饱和运算,所以像素高于255的一律复制为255
markers.convertTo(tmp,CV_8U);//
return tmp;
}
// 以图像形式返回分水岭(我理解的是分割线)
cv::Mat getWatersheds() {
cv::Mat tmp;
//在设置标记图像,即执行setMarkers()后,边缘的像素会被赋值为-1,其他的用正整数表示
//下面的这个转换可以让边缘像素变为-1*255+255=0,即黑色,其余的溢出,赋值为255,即白色。
markers.convertTo(tmp,CV_8U,255,255);
return tmp;
}
};
#endif // WATERSHEDSEGMENTER
main.cpp
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "watershedsegmenter.h"
using namespace std;
using namespace cv;
int main()
{
// Read input image 原图
Mat image= imread("/home/osksh/skin_c/dulani_anuradha4.jpg");
if (!image.data)
return 0;
// Display the image
namedWindow("Original Image");
imshow("Original Image",image);
Mat binary,fg,bg;
cvtColor(image,binary,CV_RGBA2GRAY);
//Display the binary image
namedWindow("Binary Image");
imshow("Binary Image",binary);
// 由二值图像获得前景。腐蚀。移除噪点与微小物体
erode(binary,fg,cv::Mat(),cv::Point(-1,-1),6);
// Display the foreground image
namedWindow("Foreground Image");
imshow("Foreground Image",fg);
//膨胀二值图来获取背景(只有草地,没有树林)
dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),6);
threshold(bg,bg,150,128,cv::THRESH_BINARY_INV);
//最后一个参数的表示 ifsrc>1,dst=0,else dst=128。这样就使背景全为灰色(128)
// Display the background image
namedWindow("Background Image");
imshow("Background Image",bg);
// Show markers image
Mat markers(binary.size(),CV_8U,cv::Scalar(0));
markers= fg+bg;//使用重载操作符+
namedWindow("Markers");
imshow("Markers",markers);
// Create watershed segmentation object
WatershedSegmenter segmenter;
// Set markers and process
segmenter.setMarkers(markers);
segmenter.process(image);
// Display segmentation result
namedWindow("Segmentation");
imshow("Segmentation",segmenter.getSegmentation());
// Display watersheds
namedWindow("Watersheds");
imshow("Watersheds",segmenter.getWatersheds());
waitKey(0);
return 0;
}