分水岭变换
% 使用分水岭变换分割来分离接触对象
% 分水岭变换分割将图像中的“分水岭流域”和“分水岭脊线”
% 视为一个亮像素高、暗像素低的曲面
% 如果可以识别或“标记”前景对象和背景位置、效果更好
% 分水岭变换分割遵循以下基本程序:
%% 步骤1: 读取图片、转为灰度图
rgb = imread('pears.png');
I = rgb2gray(rgb);
imshow(I)
%% 步骤2: 使用梯度幅度作为分割函数
% 计算梯度大小。梯度在对象边界处较高,而在对象内部较低(大部分情况下)。
gmag = imgradient(I);
imshow(gmag,[])
title('梯度幅度')
% 不能用分水岭变换直接在梯度幅度上分割图像
L = watershed(gmag);
Lrgb = label2rgb(L);
imshow(Lrgb)
title('直接在梯度幅度上分割图像')
% 如果不进行预处理,例如下面的标记计算
% 直接使用分水岭变换通常会导致“过度分割”
%% 步骤3: 标记前景对象
% 可以应用各种程序来查找前景标记
% 只要这些标记能连接每个前景对象内的像素块
% 此处使用形态学开操作和闭操作来“清理”图像
% 在每个对象内创建平面最大值
% 首先使用imopen
se = strel('disk',20);
Io = imopen(I,se);
imshow(Io)
title('开操作')
% 然后利用IMERODE腐蚀、imreconstruct重建
Ie = imerode(I,se);
Iobr = imreconstruct(Ie,I);
imshow(Iobr)
title('腐蚀&重建')
% 闭操作可以去除暗点
Ioc = imclose(Io,se);
imshow(Ioc)
title('闭操作')
% 利用IMERODE膨胀、imreconstruct重建
Iobrd = imdilate(Iobr,se);
Iobrcbr = imreconstruct(imcomplement(Iobrd),imcomplement(Iobr));
Iobrcbr = imcomplement(Iobrcbr);
imshow(Iobrcbr)
title('开闭重建')
% 从IOBRCBR与IOC的比较中可以看出
montage({Iobrcbr,Ioc}, 'Size', [2 1]);
% 基于重建的开操作和关闭比标准的开操作和闭操作更有效
% 可以在不影响对象整体形状的情况下消除小瑕疵
% 计算出IOBRCBR的区域最大值
% 得到良好的前景标记
fgm = imregionalmax(Iobrcbr);
imshow(fgm)
title('区域最大值')
% 将前景标记图像叠加到原始图像上、效果明显
I2 = labeloverlay(I,fgm);
imshow(I2)
title('前景标记图像叠加')
% 一些被遮挡和阴影下的对象没有被标记
% 这些对象在最终结果中不会被正确分割
% 一些对象中的前景标记靠近对象的边缘
% 可以清理标记块的边缘,将其缩小一点
% 先关操作然后腐蚀
se2 = strel(ones(5,5));
fgm2 = imclose(fgm,se2);
fgm3 = imerode(fgm2,se2);
% 会留下一些必须删除的杂散孤立像素
% 可以使用bwAreaOpen来删除二进制图像中像素小于p的所有连接组件
fgm4 = bwareaopen(fgm3,20);
I3 = labeloverlay(I,fgm4);
imshow(I3)
title('原始图像上叠加修正过的区域最大值')
%% 步骤4: 标记背景
% 在清理后的图像中,黑色像素属于背景
% 可以从阈值操作开始
bw = imbinarize(Iobrcbr);
imshow(bw)
title('阈值操作')
% 理想情况下,我们不希望背景标记太靠近我们要分割的对象的边缘
% 通过计算前景的“阴影骨架”来“细化”背景(欧氏距离变换bwdist)
% 可以通过计算距离变换的分水岭变换、然后寻找结果的分水岭线来实现
D = bwdist(bw);
DL = watershed(D);
bgm = DL == 0;
imshow(bgm)
title('分水岭线')
%% 步骤5: 计算分割函数的分水岭变换
% 使用imimposemin修改渐变幅度图像
% 使其唯一的区域最小值出现在前景和背景标记像素上
gmag2 = imimposemin(gmag, bgm | fgm4);
% 最后,我们准备好计算基于分水岭的分割
L = watershed(gmag2);
%% 步骤6: 结果可视化
% 一种可视化技术是在原始图像上叠加前景标记、背景标记和分割的对象边界
% 对象边界位于l==0的位置
% 二进制前景和背景标记被缩放为不同的整数值,以便它们被分配不同的标签
labels = imdilate(L==0,ones(3,3)) 2*bgm 3*fgm4;
I4 = labeloverlay(I,labels);
imshow(I4)
title('分割结果可视化')
% 另一种有用的可视化技术是将标签矩阵显示为彩色图像
% 可以使用label2rgb转换为TrueColor图像进行可视化
Lrgb = label2rgb(L,'jet','w','shuffle');
imshow(Lrgb)
title('TrueColor分割结果可视化')
% 可以使用透明度将此伪彩色标签矩阵叠加到原始强度图像的上层
figure
imshow(I)
hold on
himage = imshow(Lrgb);
himage.AlphaData = 0.3;
title('伪彩色标签矩阵叠加')
相关文件为matlab自带