Main Content

本页的翻译已过时。点击此处可查看最新英文版本。

activecontour

使用主动轮廓 (snake) 区域增长方法将图像分割成前景和背景

说明

主动轮廓方法,也称为 snake,是一种迭代式区域增长图像分割算法。使用主动轮廓算法,您可以在图像上指定初始曲线,然后使用 activecontour 函数使曲线向对象边界演化。

示例

BW = activecontour(A,mask) 使用主动轮廓将图像 A 分割成前景(对象)和背景区域。

mask 参数是一个指定主动轮廓初始状态的二值图像。mask 中对象区域(白色)的边界定义轮廓演化的初始轮廓位置,以用于分割图像。输出图像 BW 是一个二值图像,前景为白色(逻辑 true),背景为黑色(逻辑 false)。

要获得更快、更准确的分割结果,请指定靠近所需对象边界的初始轮廓位置。

BW = activecontour(A,mask,n) 通过最多迭代 n 次的轮廓演化来分割图像。

示例

BW = activecontour(A,mask,method) 将用于分割的主动轮廓方法指定为 'Chan-Vese''edge'。对于 RGB 图像,该方法必须为 'Chan-Vese'

BW = activecontour(A,mask,n,method) 使用指定的 method,通过最多迭代 n 次的轮廓演化来分割图像。

BW = activecontour(___,Name,Value) 指定控制分割各个方面的名称-值对组参数。

示例

全部折叠

读取并显示灰度图像。

I = imread('coins.png');
imshow(I)
title('Original Image')

Figure contains an axes. The axes with title Original Image contains an object of type image.

指定关注对象周围的初始轮廓。显示该轮廓。

mask = zeros(size(I));
mask(25:end-25,25:end-25) = 1;
imshow(mask)
title('Initial Contour Location')

Figure contains an axes. The axes with title Initial Contour Location contains an object of type image.

使用 activecontour 函数分割图像。默认情况下,该函数通过 100 次迭代进行分割演化。

bw = activecontour(I,mask);

显示结果。经过 100 次迭代后,对象并未从背景中完全分割出来,因为原始轮廓没有接近对象边界。

imshow(bw)
title('Segmented Image, 100 Iterations')

Figure contains an axes. The axes with title Segmented Image, 100 Iterations contains an object of type image.

要继续进行分割演化,请增加迭代次数。经过 300 次迭代,对象从背景中完全分割出来。

bw = activecontour(I,mask,300);
imshow(bw)
title('Segmented Image, 300 Iterations')

Figure contains an axes. The axes with title Segmented Image, 300 Iterations contains an object of type image.

读取并显示灰度图像。

I = imread('toyobjects.png');
imshow(I)

使用 drawrectangle 函数在关注的对象附近绘制初始轮廓。绘制轮廓后,使用 createMask 函数创建掩膜。

r = drawrectangle;

mask = createMask(r);

使用 'edge' 方法和 200 次迭代来分割图像。

bw = activecontour(I,mask,200,'edge');

以红色显示原始图像上的最终轮廓。

hold on;
visboundaries(bw,'Color','r'); 

显示对原始图像进行分割的结果。前景中的对象具有蓝色。

figure
imshow(labeloverlay(I,bw));

加载三维体图像数据,删除单一维度。

D = load('mri.mat');
A  = squeeze(D.D);

为初始种子点创建二维掩膜。

seedLevel = 10;
seed = A(:,:,seedLevel) > 75;
figure
imshow(seed)

Figure contains an axes. The axes contains an object of type image.

创建一个空的三维种子掩膜,并将种子点放入其中。

mask = zeros(size(A));
mask(:,:,seedLevel) = seed;

使用主动轮廓执行分割,指定种子掩膜。

bw = activecontour(A,mask,300);

显示三维分割后的图像。

figure;
p = patch(isosurface(double(bw)));
p.FaceColor = 'red';
p.EdgeColor = 'none';
daspect([1 1 27/128]);
camlight; 
lighting phong

Figure contains an axes. The axes contains an object of type patch.

输入参数

全部折叠

要分割的图像,指定为二维数值矩阵或三维数值数组。

数据类型: single | double | int8 | int16 | int32 | uint8 | uint16 | uint32

分割开始演化时的初始轮廓,指定为与 A 大小相同的二值图像。对于二维和三维灰度图像,mask 的大小必须与图像 A 的大小相匹配。对于彩色图像和多通道图像,mask 必须为二维逻辑数组,其中前两个维度与图像 A 的前两个维度相匹配。

您可以使用 ROI 对象以交互方式创建掩膜。例如,使用 drawpolygon 函数绘制一个多边形 ROI,然后使用 createMask 函数从该 ROI 创建掩膜。

数据类型: logical

分割演化中要执行的最大迭代次数,指定为正整数。当主动轮廓达到最大迭代次数时,activecontour 停止主动轮廓的演化。如果当前迭代中的轮廓位置与最近五次迭代之一中的轮廓位置相同,activecontour 也会停止演化。

如果初始轮廓位置(由 mask 指定)远离对象边界,请指定较大的 n 值以获得所需的分割结果。

数据类型: double

分割所使用的主动轮廓方法,指定为 'Chan-Vese''edge'[1] 中介绍了基于 Chan-Vese 区域的能源模型。[2] 中介绍了基于边缘的模型,该模型类似于测地线主动轮廓。

对于 RGB 图像,该方法必须为 'Chan-Vese'

数据类型: char | string

名称-值对组参数

指定可选的、以逗号分隔的 Name,Value 对组参数。Name 为参数名称,Value 为对应的值。Name 必须放在引号中。您可采用任意顺序指定多个名称-值对组参数,如 Name1,Value1,...,NameN,ValueN

示例: 'SmoothFactor',1.5

分割区域边界的平滑度或规则性,以逗号分隔的对组形式指定,其中包含 'SmoothFactor' 和一个正数。值越高,生成的区域边界越平滑,但也可能会平滑掉较细微的细节。值越低,生成的区域边界越不规则(平滑处理越少),但可以捕获较细微的细节。'Chan-Vese' 方法的默认平滑度值为 0'edge' 方法的默认平滑度值为 1

示例: 'SmoothFactor',1.5

数据类型: single | double | int8 | int16 | int32 | uint8 | uint16 | uint32

轮廓向外扩展或向内收缩的趋势,指定为以逗号分隔的对组,其中包含 'ContractionBias' 和数值标量。正值使轮廓偏向内缩(收缩)。负值使轮廓偏向外张(扩张)。此参数无法保证轮廓收缩(或扩展)。即使此参数为正值,轮廓实际上也可能会扩张。但是,与无偏差轮廓相比,指定偏差可以减缓扩展。此参数的值通常介于 -1 和 1 之间。'Chan-Vese' 方法的默认收缩偏差为 0'edge' 方法的默认收缩偏差为 0.3

示例: 'ContractionBias',0.4

数据类型: single | double | int8 | int16 | int32 | uint8 | uint16 | uint32

输出参数

全部折叠

分割后的图像,以与输入图像 A 大小相同的二值图像形式返回。前景是白色(逻辑 true),背景是黑色(逻辑 false)。

提示

  • activecontour 使用 mask 中区域的边界作为演化开始时轮廓的初始状态。掩膜上的孔洞可能会导致不可预测的结果。请使用 imfill 填充 mask 区域中的孔洞。

  • 如果某个区域触及图像边界,则 activecontour 在进一步处理之前,会从该区域中删除单像素层,以便该区域不会触及图像边界。

  • 要获得更快、更准确的结果,请指定靠近所需对象边界的初始轮廓位置,特别是对于 'edge' 方法。

  • 对于 'edge' 方法,主动轮廓会自然内缩(收缩)。在没有任何图像梯度的情况下,主动轮廓会自行收缩。相反,在 'Chan-Vese' 方法中,轮廓是无偏差的,轮廓可以根据图像特征自由收缩或扩展。

  • 要使用 'edge' 方法实现精确分割,请指定位于对象边界之外的初始轮廓。默认情况下,使用 'edge' 方法的主动轮廓会偏向收缩。

  • 如果对象区域具有明显不同的灰度强度,则 'Chan-Vese' 方法 [1] 可能不会分割图像中的所有对象。例如,如果图像同时包含比背景亮的对象和比背景暗的对象,'Chan-Vese' 方法通常只会分割出暗的对象或分割出亮的对象。

算法

activecontour 使用稀疏场水平集方法(类似于 [3] 中所述的方法)来实现主动轮廓演化。

参考

[1] T. F. Chan, L. A. Vese, Active contours without edges. IEEE Transactions on Image Processing, Volume 10, Issue 2, pp. 266-277, 2001.

[2] V. Caselles, R. Kimmel, G. Sapiro, Geodesic active contours. International Journal of Computer Vision, Volume 22, Issue 1, pp. 61-79, 1997.

[3] R. T. Whitaker, A level-set approach to 3d reconstruction from range data. International Journal of Computer Vision, Volume 29, Issue 3, pp. 203-231, 1998.

在 R2013a 中推出