图像分割

图像分割


整体等于部分之和
—–欧几里德


图像分割把图像细分为它的组成要素或物体,细分的水平取决于要解决的问题。
单色分割的分割算法通常是基于图像亮度值的两个基本特征:不连续性和相似性。第一类,方法是基于亮度的突变来分割一幅图像,比如边缘;第二类,主要方法是根据事先定义好的准则把图像分割成相似的区域

点、线和基本边缘检测

背景知识

  1. 边缘像素是图像中灰度突变的像素,边缘是连接的边缘像素的集合
  2. 一条线可以视为一条边缘线段,该线段两侧的背景灰度要么远亮于该线像素的灰度,要么远暗于该线像素的灰度。孤立点可视为一条线,只是长度和宽度都是一个像素
  3. 局部变化检测可以用微分(一阶微分和二阶微分)
    • 对于一阶导数的任何近似,约定:
      • 在恒定灰度区域必须为0
      • 在灰度台阶和或斜坡开始处必须不为0
      • 在沿灰度斜坡点处也必须不为0
    • 类似的对于二阶导数的近似
      • 在恒定灰度区域必须为0
      • 在灰度台阶或斜坡开始除和结束处必须不为0
      • 沿灰度斜坡必须为0
    • 一维函数展开为关于x的泰勒级数,结果差分
      $$ \frac{\partial f}{\partial x}=f’(x)=f(x+1)-f(x)$$
      二阶导数
      $$ \frac{\partial ^2 f}{\partial ^2 x}=f’’(x)=f(x+1)+f(x-1)-2f(x)$$
      • 可以得出结论:
        • 一阶导数通常在图像中产生较粗的边缘
        • 二阶导数对精细细节,如细线、孤立点和噪声有较强的响应
        • 二阶导数在灰度斜坡和灰度台阶过渡处会产生双边缘响应
        • 二阶导数的符号可用于确定边缘的过程是从亮到暗还是从暗到亮
      • 计算图像中每个像素位置的一阶导数和二阶导数的可选择方法是空间滤波器。模板在该区域中心点处的响应为
        $$R = w_1z_1 + w_2z_2 + … + w_9z_9 = \sum_{k=1}^{9}w_kz_k$$
$w_1$ $w_2$ $w_3$
$w_4$ $w_5$ $w_6$
$w_7$ $w_8$ $w_9$

这是一个普通的3×3空间滤波器掩模

孤立点检测

  • 点的检测应以二阶导数为基础,这意味着使用laplace
    $$\triangledown ^2f(x,y) = \frac{\partial ^2 f}{\partial x^2} + \frac{\partial ^2 f}{\partial y^2}$$
    偏微分之后可求得laplace为
    $$\triangledown ^2f(x,y) = f(x+1,y)+f(x-1,y)+f(x,y+1)+f(x,y-1)-4f(x,y)$$
    点检测laplace模板
1 1 1
1 -8 1
1 1 1

如果在某点处的该模板的响应的绝对值超过了一个指定的阈值,那么就说在模板中心位置(x,y)处的该点已经被检测到。在输出图像中,这样的点被标注为1,所有其他点被标注为0
$$g(x,y)=\begin{cases}
1,\quad |R(x,y)| \geqq T\
0, \quad 其他
\end{cases}
$$

  • MATLAB实现
f = imread('moon.jpg');

f = rgb2gray(f);

w = [-1 -1 -1; -1 8 -1; -1 -1 -1];

g = abs(imfilter(f, w));

T = max(g(:));

g = g >= T;

figure(1);

subplot(1,2,1)

imshow(f)

subplot(1,2,2)

imshow(g)

结果:

线检测

可以预期,二阶导数将导致更强的响应,并产生比一阶导数更细的线

线检测模板

  • 水平
-1 -1 -1
2 2 2
-1 -1 -1
  • +45度
2 - -1 -1
-1 2 -1
-1 -1 2
  • 垂直
-1 2 -1
-1 2 -1
-1 2 -1
  • -45度
-1 -1 2
-1 2 -1
2 -1 -1

对于恒定的背景,当线通过模板的中间一行时可能产生更大的响应。
每个模板的系数之和为0,这表示在恒定亮度区域内,模板的响应为0.

  • MATLAB实现检测指定方向上的线
clc

clear

f = imread('11111.jpg');

f = rgb2gray(f);

figure(1);

subplot(2,3,1)

imshow(f);

w = [-1, 2, -1; -1 2 -1; -1 2 -1];

% g = imfilter(tofloat(f),w);

g = imfilter(f,w);

subplot(2,3,2)

imshow(g, [ ]);

gtop = g(1:120, 1:120);

% gtop = pixeldup(gtop, 4);

subplot(2,3,3)

imshow(gtop, [ ]);

gbot = g(end - 119:end, end - 119:end);

% gbot = pixeldup(gbot, 4);

subplot(2,3,4)

imshow(gbot, [ ]);


g = abs(g);

subplot(2,3,5)

imshow(g, [])


T = max(g(:));

g = g >= T;

subplot(2,3,6);

imshow(g)

结果:

可能会用到的M函数pixeldup

function B=pixeldup(A,m,n)%pixeldup用来重复像素的,在水平方向复制m倍,在垂直方向复制n倍,m,n必须为整数,n没有赋值默认为m%检查输入参数个数
if nargin<2
    error('At least two inputs are required.');
    end
if nargin==2
    n=m;
    end
u=1:size(A,1);%产生一个向量,其向量中元素的个数为A的行数%复制向量中每个元素m次m=round(m);%防止m为非整数u=u(ones(1,m),:);
u=u(:);%在垂直方向重复操作
v=1:size(A,2);
n=round(n);
v=v(ones(1,n),:);
v=v(:);
B=A(u,v);

慎用tofloat函数

基本边缘检测

边缘模型

  • 台阶模型
    在一个像素的距离上发生两次灰度级间理想的过渡
  • 斜坡模型
    数字图像存在被模糊或有噪声的边缘,这时的边缘被建模成一个更接近灰度斜坡的剖面,斜坡的斜度与边缘的模糊程度成反比
  • 屋顶模型
    通过一个区域的线的模型,屋顶边缘的基底(宽度)由该线的宽度和尖锐度决定

结合前面提到的一阶导数和二阶导数的性质,可以得出结论:

  1. 一阶导数的幅值可用于检测图像中的某个点处是否存在一个边缘
  2. 二阶导数的符号可用于确定一个边缘像素位于该边缘的暗的一侧还是亮的一侧
  3. 对图像的每个边缘,二阶导数生成两个值
  4. 二阶导数的零交叉点可用于定位粗边缘的中心
  • 执行边缘检测的三个步骤:
    1. 为降噪对图像进行平滑处理
    2. 边缘点的检测
    3. 边缘定位

梯度

梯度概念

梯度是一个可以确定图像f的(x,y)位置处的边缘方向和强度的工具,用 $\triangledown f$来表示,用 向量来定义

$$\triangledown f = \begin{bmatrix} g_x \ g_y \ \end{bmatrix} = \begin{bmatrix} \frac{\partial f}{\partial x} \ \frac{\partial f}{\partial x} \end{bmatrix}$$

梯度性质
  1. 梯度向量大小。
    $\triangledown f$的大小为M(x,y)
    $$\triangledown f = mag(\triangledown f)=[g_x^2+g_y^2]^{
    1/2}= [(\partial f/\partial x)^2+(\partial f/\partial y)^2]^{1/2}$$
    这是梯度向量方向变化率的值。其中$g_x$,$g_y$和M(x,y)都是和原图像大小相同的图像。称M(x,y)为梯度图像。

  2. 梯度向量的方向
    $$\alpha (x,y) = tan^{-1}(\frac{g_x}{g_y})$$
    同理, $\alpha(x,y)$也是由$g_x$和$g_y$阵列创建的尺寸相同的图像。
    任意点(x,y)处的一个边缘的方向与该点处梯度向量的方向$\alpha(x,y)$正交。
    梯度向量有时也称为边缘法线

  3. 梯度指出f在(x,y)处的最大变化率的方向

梯度算子
一维模板

$$g_x = \frac{\partial f(x,y)}{\partial x} = f(x+1,y) - f(x,y)$$

$$g_y = \frac{\partial f(x,y)}{\partial y} = f(x,y+1)-f(x,y)$$

二维模板

罗伯特交叉梯度算子(Roberts),ROberts算子以求对角像素之差为基础:
$$g_x = \frac{\partial f}{\partial x} = (z_9 - z_5)$$

$$g_y = \frac{\partial f}{\partial y} = (z_8 - z_6)$$

3×3模板
  1. Prewitt算子
    $$g_x = (z_7 + z_8 + z_9)-(z_1 + z_2 + z_3)$$

    $$g_y = (z_3 + z_6 + z_9) - (z_1 + z_4 + z_7)$$

  2. Sobel算子

$$g_x = (z_7 + 2z_8 + z_9)-(z_1 +2 z_2 + z_3)$$

$$g_y = (z_3 + 2z_6 + z_9) - (z_1 +2 z_4 + z_7)$$

在中心位置处使用2可以平滑图像

注意:所有模板中的系数之和为0,这意味着恒定灰度的响应为0.

使用函数edge的边缘检测

  • 语法
[g,t] = edge(f, 'method', parameters);

f是输入图像,method是边缘检测方法,parameters是附加参数

边缘检测算子

图像邻域如下图所示:

$z_1$ $z_2$ $z_3$
$z_4$ $z_5$ $z_6$
$z_7$ $z_8$ $z_9$
Sobel边缘检测算子
  • Sobel边缘检测算子模板
-1 -2 -1
0 0 0
1 2 1

$$g_x=(z_7+2z_8+z_9)-(z_1+2z_2+z_3)$$

-1 0 1
-2 0 2
-1 0 1

$$g_y = (z_3+2z_6+z_9)-(z_1+2z_4+z_7)$$
每一行和每一列的中心像素用2来加权以提供平滑

  • MATLAB语法
[g, t] = edge(f, 'sobel', T, dir);

f是输入的图像,T是指定的阀值,dir是指定的检测边缘的首选方向:’horizontal’,’vertical’,’both’(默认值)
t是可选的,T未指定,则t自动设置

Prewitt边缘检测算子
  • Prewitt边缘检测算子模板
-1 -1 -1
0 0 0
1 1 1

$$g_x = (z_7 + z_8 + z_9)-(z_1 + z_2 + z_3)$$

-1 0 1
-1 0 1
-1 0 1

$$g_y = (z_3 + z_6 + z_9) - (z_1 + z_4 + z_7)$$

  • MATLAB语法
[g, t] = edge(f, 'prewitt', T ,dir);

计算简单,但容易产生噪声

Roberts边缘检测算子
  • Roberts边缘检测算子模板
-1 0
0 1

$$g_x = z_9 - z_5$$

0 1
1 0

$$g_y = z_8 - z_6$$

  • MATLAB语法
[g, t] = edge(f, 'roberts', T , dir);
LoG检测算子
  • LoG

考虑高斯函数
$$G(x,y) = e^{-\frac{x^2 + y^2}{2\sigma ^2}}$$
$\sigma$是标准差。这是平滑函数,如果和图像卷积,会使图像变模糊,模糊程度由$\sigma$决定
这个函数的Laplace算法是:
$$\triangledown^2G(x,y) = \frac{\partial ^2 G(x,y)}{\partial x^2}+\frac{\partial ^2 G(x,y)}{\partial y^2} = [\frac{x^2 + y^2-2\sigma ^2}{\sigma ^4}]^{e^{-\frac{x^2 + y^2}{2\sigma ^2}}}$$

用$\triangledown ^2G(x,y)$卷积(滤波)这幅图像与先用平滑函数对图像卷积,再对结果进行Laplace变换的结果是一样的
用$\triangledown ^2G(x,y)$卷积图像,可以得到两个效果:平滑图像(因而减少了噪声);计算Laplace,从而产生双边缘图像,然后在双边缘之间定位由发现的零交叉组成的边缘

  • MATLAB语法
[g, t] = edge(f, 'log', T , sigma);

sigma默认值是2

零交叉检测算子
  • 基于LoG,卷积使用特殊的滤波函数H来完成
  • MATLAB语法
[g, t] = edge(f, 'zerocross', T , H);
Canny检测算子
  • edge函数中最强的边缘检测算子
  • MATLAB语法
[g, t] = edge(f, 'canny', T , sigma);

MATLAB实现

  • 几种边缘检测算法的比较(Sobel,LoG,Canny)
f = imread('timg1.jpg'); 
imshow(f),title('currect image');
f = rgb2gray(f);
%Default Output
[gSobel_default,ts] = edge(f, 'sobel');
[gLoG_default, tlog] = edge(f, 'log');
[gCanny_default, tc] = edge(f,'canny');

%Best Output

gSobel_best = edge(f,'sobel',0.165);
gLoG_best = edge(f,'log',0.008, 2.25);
gCanny_best = edge(f,'canny',[0.05, 0.4], 1.5);


figure,imshow(f),title('Gary images');
figure,imshow(gSobel_default),title('gSobel default');
figure,imshow(gSobel_best),title('gSobel best');
figure,imshow(gLoG_default),title('gLoG default');
figure,imshow(gLoG_best),title('gLoG best');
figure,imshow(gCanny_default),title('gCanny default');
figure,imshow(gCanny_best),title('gCanny best');

其中最佳输出的阀值是根据得到的ts,tlog,tc的值来确定的
结果:








综合结果来看,Canny边缘检测算子可以得到最好的结果


   转载规则


《图像分割》 GeekOcean 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录