分水岭算法
分水岭算法(Watershed)基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形成分水岭。分水岭的概念和形成可以通过模拟浸入过程来说明。在每一个局部极小值表面,刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢向外扩展,在两个集水盆汇合处构筑大坝,即形成分水岭,最后很容易得到图像的分割边界。
%matlab分水岭程序实现
clc;clear all;close all;
%1.读入彩色图像,并转换成灰度图显示
%rgb = imread('pears.png');
rgb = imread('depth/depth_balloons_1.bmp');
if ndims(rgb)==3
l = rgb2gray(rgb);
else
l = rgb;
end
figure('units','normalized','position',[0 0 1 1]);
subplot(1,2,1);imshow(rgb);title('原图');
subplot(1,2,2);imshow(l);title('灰度图');
%2.将梯度幅值作为分割函数,进行分割图像
%采用sobel边缘算子对图像进行水平和垂直方向滤波,然后求取模值,sobel算子滤波后的图像在边界处会显示比较大的值,在没有边界处的值会很小。
hy = fspecial('sobel');
hx = hy';
ly = imfilter(double(l),hy,'replicate');
lx = imfilter(double(l),hx,'replicate');
gradmag = sqrt(lx.^2+ly.^2);
figure('units','normalized','position',[0 0 1 1]);
subplot(1,2,1);imshow(l,[]);title('灰度图像');
subplot(1,2,2);imshow(gradmag,[]);title('梯度幅值图像');
%可否直接对梯度幅值图像使用分水岭算法?
%直接使用分水岭算法对梯度幅值图像分割,结果往往存在过度分割现象;因此,需要对前景和背景进行标记,以获得更好的分割效果
L = watershed(gradmag);
Lrgb = label2rgb(L);
figure('units','normalized','position',[0 0 1 1]);
subplot(1,2,1);imshow(gradmag,[]);title('梯度幅值图像');
subplot(1,2,2);imshow(Lrgb,[]);title('梯度幅值做分水岭变换');
%3.标记前景目标对象
%有多种方法可以应用在这里获得前景标记,这些标记必须是前景对象内部的连接斑点像素。本代码使用形态学技术‘基于开的重建’和‘基于闭的重建’来清理图像。
%开运算和闭运算:先腐蚀后膨胀称为开ÿ