我使用OpenCV Watershed和我的图像:
#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("d:\\projekty\\OpenCV\\trainData\\base01.jpg"); //http://i.imgur.com/sEWFHfY.jpg
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;
}
但这只给我个人面具。我还尝试将标记创建为两个点 - 结果只有一个掩码。是否可以使用OpenCV将单元格(对象)与轮廓分开,如示例http://biodynamics.ucsd.edu/ir/中所示? 如果没有,是否可以使用值创建结果掩码:1表示第一个对象,2表示第二个,... 99表示99?
答案 0 :(得分:2)
执行后
cv::watershed(image, markers);
markers
图像在区域的边界处将为-1,并且在与标记为1的种子相对应的区域中将为1,并且在与该种子相对应的区域中将为2标记为2,依此类推。所以你可以这样做:
cv::Mat region1 = markers==1;
答案 1 :(得分:1)
我使用以下方法在分水岭分割后提取对象countours。分水岭输出是包含每个像素的分段代码的一个标记图像。我从标记图像为每个单个对象段创建二进制掩码图像。这可以在标记图像的所有像素上的一次迭代中完成。对于核心&#34; for循环&#34;,请参阅opencv示例https://github.com/Itseez/opencv/blob/master/samples/cpp/watershed.cpp。我将所有对象蒙版存储在vector <Mat>
中。然后我在每个这样的面具上运行findContours - &gt;每个物体的轮廓。见http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html。你不需要使用边缘检测器Canny,因为掩模图像已经是二进制的。