说明
1、基于距离变换的分水岭是相对于传统的findcontour函数而言的
2、采用的是连通域的方式进行mask图像标定
3、一下代码通过调剂膨胀和腐蚀参数,以及次数,可以分割粘合图片等
4、处理流程如下图:
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("000119.jpg");
imshow("src", src);
Rect box(72, 93, 90, 93);
Mat bin_img = Mat::zeros(src.size(), CV_8U);
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
if ((i<box.y || i>(box.y + box.height)) || (j<box.x || j>(box.x + box.width)))
{
bin_img.at<uchar>(i, j) = 0;
}
else
{
bin_img.at<uchar>(i, j) = 255;
}
}
}
imshow("二值化图像", bin_img);
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
//生成前景图像sure_fg
Mat dist;
distanceTransform(bin_img, dist, DIST_L2, 5);
normalize(dist, dist, 0, 255, cv::NORM_MINMAX);
double my_minv = 0.0, my_maxv = 0.0;
minMaxIdx(dist, &my_minv, &my_maxv);
Mat sure_fg;//注水点
threshold(dist, sure_fg, 0.8 * my_maxv, 255, THRESH_BINARY);
sure_fg.convertTo(sure_fg, CV_8U);
Mat element1 = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
dilate(sure_fg, sure_fg, element, Point(-1, -1), 3);
sure_fg.convertTo(sure_fg, CV_8U);
imshow("sure_fg", sure_fg);
//生成背景图像
Mat sure_bg;
dilate(bin_img, sure_bg, element, Point(-1, -1));
imshow("sure_bg", sure_bg);
//确定未知区域
Mat unkonwn = Mat(bin_img.size(), CV_8U);
unkonwn = sure_bg - sure_fg;
imshow("unkonwn", unkonwn);
//markers
Mat label_img = Mat(bin_img.size(), CV_32S);
int num = connectedComponents(sure_fg, label_img, 8);
label_img = label_img + 1;
for (int i = 0; i < unkonwn.rows; i++)
{
for (int j = 0; j < unkonwn.cols; j++)
{
if (((int)unkonwn.at<uchar>(i, j)) == 255)
{
label_img.at<signed int>(i, j) = 0;
}
}
}
cout << label_img;
watershed(src, label_img);
cout << label_img;
//显示图像
double maxVal = 0;
double minVal = 0;
minMaxLoc(label_img, &minVal, &maxVal);
Mat dst = Mat::zeros(src.size(), CV_8U);
label_img.convertTo(dst, CV_8U, 255.0 / (maxVal - minVal), -255.0 * minVal / (maxVal - minVal));
imshow("marks", dst);
waitKey(0);
return 0;
}