在matlab中正确的使用水坝算法分割图像
网址:http://www.it165.net/pro/html/201312/8297.html
上看到一篇讲解这个算法的帖子,看看如何能够正确的使用这个算法。 例如,这是一张图像,我们希望用watershed的方法对这幅图像进行分割。
当然,在matlab里面,直接对这幅图像使用watershed这个函数,并不能得到很好的分割结果。这里我们看看如何能够正确的使用watershed分割这个图像,同时也看看watershed变换和watershed分割的区别。
首先,我们直接调用watershed,看看结果是什么样的
view sourceprint?
1.url = 'http://www.bfcat.com/wp-content/uploads/auto_save_image/2013/12/004306JQI.png';
2.bw = imread(url);
3.L = watershed(bw);
4.Lrgb = label2rgb(L);
5.imshow(Lrgb)
刚刚看到结果的时候,我们可能很纳闷分割结果为什么是这个样子。让我们用imfuse这个函数,将两幅图像显示在一起,将图像中的一个区块放大看
imshow(imfuse(bw,Lrgb))
axis([10 175 15 155])
我们可以看出,watershed变换总会在每一个局部最小的地方给出一个水坝区域。这些小的黑色“点”就是局部最小值,因此在每个周围都有一个watershed区域。
即使我们填补了这些空洞,我们也没法获得用户想要的分割效果。这就是我们要注意到的watershed变换和watershed分割的区别。也就是说,watershed分割算法是watershed变
换的一种应用,而简单的对图像进行watershed
变换,并不能达到最终的分割目的。
这里有一个帖子 The Watershed Transform: Strategies for Image Segmentation,详细介绍了watershed变换的原理。这个帖子的中心思想概括为一句话:用水坝变换进行图像分割的关键,在于先要将图像进行转换,使得目标对应不同的“蓄水池”.
对于这样一副图像,包含一些接近圆形,互相接触的区块,我们可以使用距离变换来生成另一幅图像,其中的目标对应“蓄水池”。
进行距离变换之前,我们先清理一下噪声。bwareaopen这个“开”运算,可以用来清除很小的点。
bw2 = ~bwareaopen(~bw, 10);
imshow(bw2)
然后我们进行距离变换。
D = -bwdist(~bw);
imshow(D,[])
基于这个图像,我们再来做水坝变换
Ld = watershed(D);
imshow(label2rgb(Ld))
这里的白线就是分割的边缘。由于原图是二值图,因此我们很容易区分前景和背景。
bw2 = bw;
bw2(Ld == 0) = 0;
imshow(bw2)
这样的结果中包含了不少过分割。原因和上面提到的一样,局部最小太多。对于这种情况,通用的技巧是,在基于watershed的图像分割中使用imextendedmin这个函数过滤掉一些特别小(指区域小)的局部最小。然后,我们修改距离变换的结果,让滤波后的区域不会出现局部最小值,这个操作叫做“强制最小(minima imposition)”,可以用imimposemin这个函数实现。
使用imextendedmin将会只在我们希望分割的区块中间产生小点。然后我们使用imshowpair来将模板叠加到原图上。
mask = imextendedmin(D,2);
imshowpair(bw,mask,'blend')
最后,我们我们修改距离变换的结果,让其只在想要的位置具有局部最小。然后进行watershed。这就是我们想要的结果了。
D2 = imimposemin(D,mask);
Ld2 = watershed(D2);
bw3 = bw;
bw3(Ld2 == 0) = 0;
imshow(bw3)
在matlab中正确的使用水坝算法分割图像
网址:http://www.it165.net/pro/html/201312/8297.html
上看到一篇讲解这个算法的帖子,看看如何能够正确的使用这个算法。 例如,这是一张图像,我们希望用watershed的方法对这幅图像进行分割。
当然,在matlab里面,直接对这幅图像使用watershed这个函数,并不能得到很好的分割结果。这里我们看看如何能够正确的使用watershed分割这个图像,同时也看看watershed变换和watershed分割的区别。
首先,我们直接调用watershed,看看结果是什么样的
view sourceprint?
1.url = 'http://www.bfcat.com/wp-content/uploads/auto_save_image/2013/12/004306JQI.png';
2.bw = imread(url);
3.L = watershed(bw);
4.Lrgb = label2rgb(L);
5.imshow(Lrgb)
刚刚看到结果的时候,我们可能很纳闷分割结果为什么是这个样子。让我们用imfuse这个函数,将两幅图像显示在一起,将图像中的一个区块放大看
imshow(imfuse(bw,Lrgb))
axis([10 175 15 155])
我们可以看出,watershed变换总会在每一个局部最小的地方给出一个水坝区域。这些小的黑色“点”就是局部最小值,因此在每个周围都有一个watershed区域。
即使我们填补了这些空洞,我们也没法获得用户想要的分割效果。这就是我们要注意到的watershed变换和watershed分割的区别。也就是说,watershed分割算法是watershed变
换的一种应用,而简单的对图像进行watershed
变换,并不能达到最终的分割目的。
这里有一个帖子 The Watershed Transform: Strategies for Image Segmentation,详细介绍了watershed变换的原理。这个帖子的中心思想概括为一句话:用水坝变换进行图像分割的关键,在于先要将图像进行转换,使得目标对应不同的“蓄水池”.
对于这样一副图像,包含一些接近圆形,互相接触的区块,我们可以使用距离变换来生成另一幅图像,其中的目标对应“蓄水池”。
进行距离变换之前,我们先清理一下噪声。bwareaopen这个“开”运算,可以用来清除很小的点。
bw2 = ~bwareaopen(~bw, 10);
imshow(bw2)
然后我们进行距离变换。
D = -bwdist(~bw);
imshow(D,[])
基于这个图像,我们再来做水坝变换
Ld = watershed(D);
imshow(label2rgb(Ld))
这里的白线就是分割的边缘。由于原图是二值图,因此我们很容易区分前景和背景。
bw2 = bw;
bw2(Ld == 0) = 0;
imshow(bw2)
这样的结果中包含了不少过分割。原因和上面提到的一样,局部最小太多。对于这种情况,通用的技巧是,在基于watershed的图像分割中使用imextendedmin这个函数过滤掉一些特别小(指区域小)的局部最小。然后,我们修改距离变换的结果,让滤波后的区域不会出现局部最小值,这个操作叫做“强制最小(minima imposition)”,可以用imimposemin这个函数实现。
使用imextendedmin将会只在我们希望分割的区块中间产生小点。然后我们使用imshowpair来将模板叠加到原图上。
mask = imextendedmin(D,2);
imshowpair(bw,mask,'blend')
最后,我们我们修改距离变换的结果,让其只在想要的位置具有局部最小。然后进行watershed。这就是我们想要的结果了。
D2 = imimposemin(D,mask);
Ld2 = watershed(D2);
bw3 = bw;
bw3(Ld2 == 0) = 0;
imshow(bw3)