第十章 图像分割(1至3节)

1. 点、线和边缘检测

1.1 点检测

嵌在常数区域(或图像中亮度基本不变的区域)中的孤立点的检测,在原理上相当直接。下面显示了一幅图像。

这里写图片描述

在该图像东北象限的暗灰色区域中有一个几乎看不见的黑点。我们可以按如下方式找到该点的位置:

w=[-1 -1 -1;-1 8 -1;-1 -1 -1];
g=abs(imfilter(double(f),w));
T=max(g(:));
g=g>=T;
figure,imshow(g);

效果如下:

这里写图片描述

其中,f是一个输入图像,w是一个合适的点检测掩膜,函数imfilter会将其输出转换为输入的类,若输入是uint8类,且abs操作不接受整数数据,则我们可以在滤波操作中使用double(f)来防止过早的截断。若输出图像是logical类,则它的值是0和1。通过T来选择已滤波图像g中的最大值,然后在g中查找所有大于等于T的点,从而识别这些有着最大响应的点。
点检测的另一种方法是在大小为m*n的所有的邻域中找一些点,这些点的最大值和最小值之差超过了T。可以使用第三章学过的ordfilt2来实现:

g=imsubtract(ordfilt2(f,2*2,ones(2,2)),... 
ordfilt2(f,1,ones(2,2)));
g=g>=T;

前面的公式要比3*3的掩膜更具灵活性。

1.2 线检测

与点检测相比,线检测要更复杂一些。考虑下图中的掩膜,若第一个掩膜在图上四处移动,则它会更强烈地响应(一个像素宽的)水平线。对于不变的背景,当该水平线通过掩膜的中间行时,会出现最大的响应。

代码实例:

g=imfilter(double(b),w);
>> subplot(3,2,1),imshow(b);
>> title('原图像');
>> subplot(3,2,2),imshow(g,[]);
>> title('使用-45度检测器后的结果');
>> gtop=g(1:120,1:120);
>> gtop=pixeldup(gtop,4);
>> subplot(3,2,3),imshow(gtop,[]);
>> title('左上角的放大图');
>> gbot=g(end-119:end,end-119:end);
>> gbot=pixeldup(gbot,4);
>> subplot(3,2,4),imshow(gbot,[]);
>> title('右下角的放大图');
>> g=abs(g);
>> subplot(3,2,5),imshow(g,[]);
>> title('第二张的绝对值图');
>> T=max(g(:));
>> g=g>=T;
>> subplot(3,2,6),imshow(g);
>> title('满足大于等于T的所有点');

效果如下:

这里写图片描述

第一张图显示了一张二值图像,假设我们希望找到所有宽度为一个像素的线,且其方向为-45度。第二张图中,灰色阴影对应于负值。在-45度方向,存在两个主要的部分,一个在左上方,一个在右下方。其中第四张图的直线部分要比第三张的部分亮得多,原因是,右下方的成分只有一个像素宽,左上方的成分则不是如此。

1.3 使用edge函数的边缘检测

边缘检测的基本意图是使用如下两个基本准则之一在图像中找到亮度快速变化的地方:
1. 找到亮度的一阶导数在幅度上比指定的阈值大的地方。
2. 找到亮度的二阶导数有零交叉的地方。
IPT函数edge提供了几个导数估计器。对一些估计器来说,是有可能指定边缘检测器是否对水平或垂直边缘敏感的。该函数的基本语法为

[g,t]=edge(f,'method',parameters)

这里面f是输入图像,method就是可用的边缘检测器,可参照下表:

这里写图片描述

首先使用Sobel检测器来提取边缘
代码实例如下:

f=imread('image\TIM图片20170628190507.png');
f=rgb2gray(f);
[gv,t]=edge(f,'sobel','vertical');

效果如下:

这里写图片描述

从第二张图可以看到,结果中的主要边缘是垂直边缘(倾斜的边缘有垂直分量和水平分量,所以也能被检测到)。现在可以指定一个较高的阈值,为了把弱的一些边缘去掉。

gv=edge(f,'sobel','vertical',0.15);

效果如下:

这里写图片描述

若不限定边缘的方向,效果如下:

这里写图片描述

可看到,使用相同的T值后,它突出显示了垂直边缘和水平边缘。但函数edge不能计算正负45度的Sobel边缘。要计算这些边缘,我们需要指定掩模并使用函数imfilter。

代码实例:

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;
imshow(g45);

效果如下:

这里写图片描述

可看到最强边缘是方向为45度的边缘。因此,如果想得到-45度的最强边缘,可使用掩模[0 1 2;-1 0 1;-2 -1 0],以及相同的命令序列。在函数edge中使用’prewitt’和’roberts’的过程,类似于Sobel边缘检测器的过程。

效果如下:

这里写图片描述

以上是关于Sobel边缘检测器的一些使用,然后我们再来比较下它和Log,Canny边缘检测器的比较。如下图,左边的一列显示了使用默认的选项’sobel’,‘log’,’canny’得到的边缘图像。右列交互地显示原图像的主要特征所得到的结果。

代码如下:

[sobel,ts]=edge(f,'sobel');
[log,tlog]=edge(f,'log');
[canny,tc]=edge(f,'canny');
sobel_best=edge(f,'sobel',0.05);
log_best=edge(f,'log',0.003,2.25);
canny_best=edge(f,'canny',[0.04 0.10],1.5);

效果如下:

这里写图片描述

2. 使用Hough变换的线检测

计算Hough变换的函数为sparse。

基本用法为:

A=[0 0 0 5
0 2 0 0
1 3 0 0
0 0 4 0];
>> S=sparse(A)
S =

   (3,1)        1
   (2,2)        2
   (3,2)        3
   (4,3)        4
   (1,4)        5

该输出列出了S中的非零元素及其行和列索引。元素按列排序。还有一种更常用的语法如下:

>> S=sparse([3 2 3 4 1],[1 2 2 3 4],[1 2 3 4 5],4,4)

S =

   (3,1)        1
   (2,2)        2
   (3,2)        3
   (4,3)        4
   (1,4)        5

其中前两个参数r和c分别是我们希望转换为稀疏矩阵的矩阵中非零元素的行和列索引向量。第三个参数s是一个向量,它包含有相应于索引对(r,c)的值,m和n是结果矩阵的行维数和列维数。然后根据这个稀疏矩阵,我们还可以用full函数来获得完整的矩阵。用法如下:

A=full(S)

A =

     0     0     0     5
     0     2     0     0
     1     3     0     0
     0     0     4     0

为了在MATLAB中探讨Hough变换的线检测,我们用一幅简单的二值图像来说明。首先建立一幅在一些位置存在孤立前景像素的图像。

f=zeros(101,101);
f(1,1)=1;f(101,1)=1;f(1,101)=1;
f(101,101)=1;f(51,51)=1;
imshow(f);
H=hough(f);
figure,imshow(H);
subplot(1,3,1),imshow(f);
subplot(1,3,2),imshow(H);
title('Hough 变换');

效果如图:

这里写图片描述

2.1使用Hough变换做峰值检测

使用Hough变换进行线检测和链接的第一步是峰值检测。在Hough变换中找到一组有意义的明显峰值是一种挑战。因为数字图像的空间中的量化、Hough变换的参数空间中的量化以及典型图像的边缘都不是很直这个事实,Hough变换的峰值一般都位于多个Hough变换单元中。克服这个问题的一个策略如下:
1. 找到包含有最大值的Hough变换单元并记下它的位置。
2. 把第一步中找到的最大值点的邻域中的Hough变换单元设为零。
3. 重复该步骤,直到找到需要的峰值数时为止,或者达到一个指定的阈值时为止。

2.2 使用Hough变换做线检测和链接

一旦在Hough变换中识别出了一组候选的峰被,则它们还要留待确定是否存在与这些峰值相关的线段以及它们的起始和结束位置。对每一个峰值来说,第一步是找到图像中影响到峰值的每一个非零值点的位置。我们使用Hough变换做线检测和链接。

代码如下:

[H,theta,rho]=hough(f,0.5);
imshow(theta,rho,H,[],'notruesize'),axis on,axis normal 
xlabel('\theta'),ylabel('\rho')

接下来,使用函数houghpeaks找到5个看起来很明显的Hough变换峰值。

[r,c]=houghpeaks(H,5);
hold on
plot(theta(c),rho(r),'linestyle','none',... 
'marker','s','color','w')

最后使用函数houghlines来查找并链接线段,并使用函数imshow,hold on和plot在原始的二值图像中叠加这些线段。
代码如下:

lines=houghlines(f,theta,rho,r,c)
figure,imshow(f),hold on
for k=1:length(lines)
xy=[lines(k).point1;lines(k).point2];
plot(xy(:,2),xy(:,1),'LineWidth',4,'Color',[.6 .6 .6]);
end

3. 阈值处理

3.1 全局阈值处理

工具箱提供了一个称为graythresh的函数,该函数使用Otsu方法来计算阈值。首先取一幅图像,计算它的直方图,找到最大化方差平方的阈值。阈值返回为0.0和1.0之间的归一化值。调用语法为:

T=graythresh(f)

其中,f是输入图像,T是产生的阈值。为了分割图像,我们在函数im2bw中使用阈值T,因为阈值已被归一化到范围【0 1】内,因此必须在使用阈值之前将其缩放到合适的范围。

3.2 局部阈值处理

全局阈值处理方法在背景照明不均匀时有可能无效。在这种情况下,一种常用的处理方法是针对照明问题做预处理已补偿图像,然后再对预处理后的图像采用全局阈值处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值