Matlab实现图像分割
目的
图像分割是数字图像处理中的一个重要课题,主要用于将图像分成不同的区域或物体,以便后续处理和分析。Matlab提供了强大的工具箱支持图像分割的实现。本文介绍了几种常见的图像分割方法,包括线检测、边缘检测、使用梯度的分水岭分割以及控制标记符的分水岭分割。
具体目标如下:
- 掌握线检测方法。
- 掌握常见的边缘检测方法。
- 学习如何使用梯度进行分水岭分割。
- 学习如何利用控制标记符优化分水岭分割。
内容
线检测
线检测是图像分割中的一个基本操作,通常用于提取图像中的线条或边缘。Matlab通过不同的滤波器来实现线检测,以下代码展示了如何利用自定义的滤波器进行线检测。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function B = pixeldup(A, m, n)
if nargin < 2
error('At least two inputs are required');
end
if nargin == 2
n = m;
end
u = 1:size(A, 1);
m = round(m);
u = u(ones(1, m), :);
u = u(:);
v = 1:size(A, 1);
n = round(n);
v = v(ones(1, n), :);
v = v(:);
B = A(u, v);
end
此函数 pixeldup
用于通过重复像素位置来放大图像,常用于增强图像细节。接下来的代码展示了如何通过自定义滤波器 w
对图像进行卷积,以检测线条。
clear all
clc
f = imread('D:\pic\DIP3E_CH10\Fig1005(a)(wirebond_mask).tif');
figure, imshow(f);
w = [2 -1 -1; -1 2 -1; -1 -1 2];
g = imfilter(double(f), w);
figure, imshow(g, []) % Figure 2
gtop = g(1:120, 1:120);
gtop = pixeldup(gtop, 4);
figure, imshow(gtop, []) % Figure 3
gbot = g(end-119:end, end-119:end);
gbot = pixeldup(gbot, 4);
figure, imshow(gbot, []) % Figure 4
g = abs(g);
figure, imshow(g, []) % Figure 5
T = max(g(:));
g = g >= T;
figure, imshow(g) % Figure 6
通过此代码,首先对图像进行线性滤波,之后进行图像放大、绝对值处理和阈值化操作,最后提取出图像中的线条区域。
边缘检测
边缘检测是图像分割的核心操作之一,它通过检测图像中像素值变化较大的部分来找到物体的边界。Matlab提供了多种边缘检测算法,其中 Sobel
、LoG
和 Canny
是最常用的算法。以下展示了如何使用这些方法进行边缘检测。
clear all
clc
f = imread('D:\pic\DIP3E_CH10\Fig1016(a)(building_original).tif');
figure, imshow(f);
[gv, t] = edge(f, 'sobel', 'vertical');
figure, imshow(gv);
t
gv = edge(f, 'sobel', 0.15, 'vertical');
figure, imshow(gv);
gboth = edge(f, 'sobel', 0.15);
figure, imshow(gboth);
w45 = [-2 -1 0; -1 0 1; 0 1 2];
g45 = imfilter(double(f), w45, 'replicate');
T = 0.3 * max(abs(g45(:)));
g45 = g45 >= T;
figure, imshow(g45);
此代码展示了使用 Sobel
算子进行垂直边缘检测,并通过设置阈值来控制边缘的检测精度。我们还可以使用其他算子(如 LoG
和 Canny
)对图像进行不同类型的边缘检测。
接下来的代码展示了不同边缘检测方法的比较:
clear all
clc
f = imread('D:\pic\DIP3E_CH10\Fig1016(a)(building_original).tif');
figure, imshow(f);
[g_sobel_default, ts] = edge(f, 'sobel');
figure, imshow(g_sobel_default);
[g_log_default, tlog] = edge(f, 'log');
figure, imshow(g_log_default);
[g_canny_default, tc] = edge(f, 'canny');
figure, imshow(g_canny_default);
[g_sobel_best, ts] = edge(f, 'sobel', 0.05);
figure, imshow(g_sobel_best);
[g_log_best, tlog] = edge(f, 'log', 0.003, 2.25);
figure, imshow(g_log_best);
[g_canny_best, tc] = edge(f, 'canny', [0.04 0.10], 1.5);
figure, imshow(g_canny_best);
通过上述代码,可以比较不同边缘检测方法在同一图像上的效果,并通过调整参数优化检测结果。
使用梯度的分水岭分割
分水岭算法是一种基于梯度的图像分割方法。它通过寻找图像的梯度信息,将图像分成不同的区域。以下是如何使用梯度进行分水岭分割的实现。
clear all
clc
f = imread('D:\pic\DIP3E_CH10\Fig1057(a)(small_blobs-original).tif');
figure, imshow(f);
h = fspecial('sobel');
fd = double(f);
g = sqrt(imfilter(fd, h, 'replicate').^2 + ...
imfilter(fd, h', 'replicate').^2);
figure, imshow(g);
L = watershed(g);
figure, imshow(L);
wr = L == 0;
g2 = imclose(imopen(g, ones(3, 3)), ones(3, 3));
figure, imshow(g2);
L2 = watershed(g2);
figure, imshow(L2);
wr2 = L2 == 0;
f2 = f;
f2(wr2) = 255;
figure, imshow(f2);
在这个例子中,首先计算图像的梯度值,接着应用分水岭算法进行图像分割。通过调整结构元素的大小(如 ones(3, 3)
)来优化分水岭分割的结果。
控制标记符的分水岭分割
分水岭算法通常容易受到噪声的影响,而通过控制标记符(markers)可以改进分水岭分割的效果。以下是如何使用标记符优化分水岭分割的实现。
clear all
clc
f = imread('D:\pic\DIP3E_CH10\Fig1057(a)(small_blobs-original).tif');
figure, imshow(f);
h = fspecial('sobel');
fd = double(f);
g = sqrt(imfilter(fd, h, 'replicate').^2 + imfilter(fd, h', 'replicate').^2);
L = watershed(g);
wr = L == 0;
rm = imregionalmin(g);
figure, imshow(rm);
im = imextendedmin(f, 2);
figure, imshow(im);
fim = f;
fim(im) = 175;
figure, imshow(fim);
Lim = watershed(bwdist(im));
figure, imshow(Lim);
em = Lim == 0;
g2 = imimposemin(g, im | em);
figure, imshow(g2);
L2 = watershed(g2);
figure, imshow(L2);
f2 = f;
f2(L2 == 0) = 255;
figure, imshow(f2);
在这个例子中,我们首先计算图像的梯度并应用分水岭算法,然后通过标记符来控制分水岭分割的过程,优化分割结果。
参考文献:
- [Rafael C. Gonzalez, Richard E. Woods, and Steven L. Eddins. 2003. Digital Image Processing Using MATLAB. Prentice-Hall, Inc., USA.]
- [阮秋琦. *数字图像处理(MATLAB版)[M]. 北京:电子工业出版社, 2014.]
- [冈萨雷斯. *数字图像处理(第三版)[M]. 北京:电子