医学图像处理案例(三)——用分水岭算法分割重叠细胞

2020-06-29 12:00:57 浏览数 (1)

针对重叠的图像分割是非常具有挑战的,正好之前一起工作过的同事跟我一起讨论了关于这方面的问题,我首先想到的就是用分水岭来进行分割。

下面我将结合他提供的细胞图像来实现分水岭分割算法的实现。

1、RGB2HSV空间变换

首先我们观察图像可以看到背景是白色,而我们期望的目标颜色有深有浅,而且颜色也不一样,所以直接将RGB转成HSV,分割出白色区域然后再取反即可。关于白色在HSV中范围,我之前的文章中有分享过,这里就不给出来了。代码实现:

cv::Mat hsvimage, thresholdimage;

cv::cvtColor(src, hsvimage, CV_BGR2HSV);

cv::inRange(hsvimage, cv::Scalar(0, 0, 221), cv::Scalar(180, 30, 255), thresholdimage);

result = ~thresholdimage.clone();

2、形态学闭操作

因为分割的图像中间会有一些空洞,我们用形态学闭操作来弥补这个缺陷。

代码实现:

cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(kernelsize, kernelsize));

cv::morphologyEx(src, result, cv::MORPH_CLOSE, element, cv::Point(-1, -1));

3、生成标记区域

首先要生成前景区域,代码实现:

cv::distanceTransform(src, dist, CV_DIST_L2, 5);

cv::normalize(dist, dist, 0, 255, cv::NORM_MINMAX);

double minv = 0.0, maxv = 0.0;

cv::minMaxIdx(dist, &minv, &maxv);

cv::Mat sure_fg;

cv::threshold(dist, sure_fg, 0.4*maxv, 255, CV_THRESH_BINARY);

sure_fg.convertTo(sure_fg, CV_8U);

cv::imwrite("sure_fg.jpg", sure_fg);

然后生成背景区域,代码如下:

cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(kernelsize, kernelsize));

cv::morphologyEx(src, result, cv::MORPH_DILATE, element, cv::Point(-1, -1));

将上面两个结果相减得到未确定区域。

根据分水岭算法的特点,我们要把未确定区域设置为波谷值(例如0),而之前分割中背景也是0,因此通过连通域分析,我们将背景的值设置成1。代码如下:

cv::Mat labelmatImage = cv::Mat(dist.size(), CV_32SC1);

int label = cv::connectedComponents(sure_fg, labelmatImage, 8);

labelmatImage = labelmatImage 1;

for (int i = 0; i < labelmatImage.rows; i )

{

for (int j = 0; j < labelmatImage.cols; j )

{

if ((int)unkonwn.at<uchar>(i, j) == 255)

{

labelmatImage.at<int>(i, j) = 0;

}

}

}

4、用分水岭算法进行分割

opencv自带的分水岭算法。代码如下:

cv::watershed(src, markers);

最后的效果只能是差强人意吧,大家如果有更好的方法,欢迎一起交流学习。

0 人点赞