分水岭算法(watershed)是一种借鉴了形态学理论的分割方法,在该方法中,将一幅图像看成一个拓扑地形图,其中灰度值f(x,y)对应地形高度值。高灰度值对应的山峰,低灰度值对应山谷。水总是朝地势低的地方流动,直到某一局部低洼处才停下来,这个低洼处被称为吸水盆地。最终所有的水分会分聚在不同的吸水盆地,吸水盆地之间的山脊被称为分水岭。水从分水岭留下时,朝不同的吸水盆地流动的可能性是相等的。使用这种想法用于图像分割,就是要在灰度图像中找出不同的“吸水盆地”和“分水岭”。
分水岭阈值选择算法可以看作一种自适应的多阈值分割算法,在图像梯度图上进行阈值选择时,经常遇到的问题是如何恰当的选择阈值。若阈值选得太高,则许多边缘会丢失或出现破碎现象;若阈值选得太低,则容易产生虚假边缘,而且边缘变厚导致定位不精确。分水岭法可以避免这个问题。
matlab中提供的watershed函数用于实现分水岭分割图像,其调用格式如下。
L=watershed(A):输入参数A为待分割的图像;输出参数L为与A维数相同的非负整数矩阵,标记分割结果。矩阵元素值为对应位置上像素点所属区域编号,0元素表示对该像素点是分水岭像素,不属于任何一个区域。
L=watershed(A,conn):参数conn用于指定算法中使用的元素的连通方式。(二维连通:conn取 4或8;三维conn可取4、8或16)
watershed函数不仅适用于图像分割,也可以用于对任意维区域进行分割,A是对这个区域的描述,可以是任意维的数组,每一个元素可以是任意实数。
clear all
%产生一个包含两个重叠的圆形图案的二值图像
center1 = -10;
center2 = -center1;
dist = sqrt(2*(2*center1)^2);
radius = dist/2 * 1.4;
lims = [floor(center1-1.2*radius) ceil(center2+1.2*radius)];
[x,y]=meshgrid(lims(1):lims(2));
bw1 = sqrt((x-center1).^2+(y-center1).^2) <=radius;
bw2 = sqrt((x-center2).^2+(y-center2).^2) <=radius;
bw = bw1 | bw2;
subplot(131);imshow(bw,'InitialMagnification','fit');xlabel('(a)二值图像');
%对二值图像进行变换,得到一个包含两个“盆地”的图像
D=bwdist(~bw);
subplot(132);imshow(D,[],'InitialMagnification','fit');
xlabel('(b)分割前的等高线');
%补充距离变换
D=-D;
D(~bw) =-Inf;
%进行watershed分割并将分割结果以标记图形式绘出
L=watershed(D);
rgb = label2rgb(L,'jet',[.5 .5 .5]);
subplot(133);imshow(rgb,'InitialMagnification','fit');
xlabel('(c)D的分水岭变换')
结果图如下:
三维不作解释,差不多道理。还请多多指教。