更多MATLAB图像处理视频请点击 http://study.163.com/course/courseMain.htm?courseId=1003594013
数学形态学的数学基础是集合论,因此数学形态学有完备的数学基础,这位数学形态学用于图像分析和处理奠定了坚实的基础。数学形态学运算是由一组形态学的代数运算子组成,其基本思想是用具有一定形态的结构元素找到图像中的对应形状以达到图像分割识别的目的,基本的操作有膨胀、腐蚀、开启和关闭。基于这些基本操作可以推到出数学形态学的很多实用算法,从而进行进一步的图像处理。将数学形态学应用于图像处理可以简化图像数据,保持他们的基本形状。
目前形态学的应用几乎覆盖了图像处理的所有领域,包括医学图像处理、文字识别、图像编码压缩、材料科学、视觉检测以及计算机视觉等。
本章主要讲述MATLAB图像处理工具箱中的形态学操作函数。可以使用这些函数进行一般的图像处理任务。
1.腐蚀和膨胀
腐蚀和膨胀是数学形态学的基本操作,数学形态学的很多操作都是以膨胀和腐蚀为基础推导的算法。
1.1.理解膨胀和腐蚀
膨胀是指将像素加到图像中对象的边缘,而腐蚀是指删除图像中对像的边缘。增加或者删除的像素数目依赖于处理过程中使用的结构元素的大小和形状。而膨胀和腐蚀的形态学操作中,输出像素的任何状态都是输入图像中相应像素与领域像素执行膨胀或者腐蚀运算得到的。
膨胀和腐蚀的规则:
运算 规则
膨胀 输出像素的值是所有输入像素值中的最大值。在二值图像中,如果领域中有一个像素值为1,则输出像素值为1
腐蚀 输出像素的值是所有输入像素值中的最小值,在二值图像中,若果领域中有一个像素值为0,则输出像素值为0
下图说明了二值图像的腐蚀操作,注意,结构元素定义了感兴趣像素的领域。膨胀函数对领域中的像素应用了相应的规则,在输出图像中返回相应的像素值,在这幅图中,形态学膨胀函数把输出像素的值设为1,因为结构元素定义的领域中有像素值为1.
下面的图中说明了灰度图像的膨胀操作,该图说明了输入图像中特定像素的处理过程。注意,膨胀操作吧输入图像中结构元素定义的领域中最大的像素值作为输出像素值。
1.2 处理图像边界的像素
形态学操作函数把结构元素的中心对应输入图像指定的像素值,对于图像便界上的元素,结构元素定义的部分领域可以扩展到图像的便界以外。
为了处理图像边界的像素,形态学函数会给这些没有定义的像素指定一个值,就好像是函数已经用额外的行和列填充了图像一样,这些填充的像素值会因为膨胀或者腐蚀有所不同,下表列出了对于二值图像和灰度图像的膨胀和腐蚀的填充规则。
运算 规则
膨胀 图像边界外的像素值被指定为图像数据类型的最小值,对于二值图像,这些值设定为0,对于uint8类型的灰度图,这些值设定为0
腐蚀 图像边界外的像素值被指定为图像数据类型的最大值,对于二值图像,这些值设定为1,对于uint8类型的灰度图像,这些值设定为255
通过在膨胀操作中使用最小值,在腐蚀操作中使用最大值,在图像处理中避免了边界效应。边界效应是指输出图像中边界元素的值的分布不像图像中的其他部分那样均一。
例如,如果腐蚀操作中使用最小值填充边界,腐蚀图像将会在图像边界产生一个黑色的边框,因为这些边界的像素值为0,这就就是所谓的边界效应。
1.3 理解结构元素
膨胀和腐蚀操作的核心内容是结构元素。一般来说结构元素是由元素为1或者0的矩阵组成。结构元素为1的区域定义了图像的领域,领域内的像素在进行膨胀和腐蚀等形态学操作时要进行考虑。
一般来说,二维或者平面结构的结构元素要比处理的图像小得多。结构元素的中心像素,即结构元素的原点,与输入图像中感兴趣的像素值(即要处理的像素值)相对应。
三维的结构元素使用0和1来定义x-y平面中结构元素的范围,使用高度值定义第三维。
(1)结构元素的原点
形态学操作中使用下面的公式来得到任意形状和维数的结构元素的原点坐标:
origin=floor((size(nhood)+1)/2)
其中,nhood是定义的结构元素的邻域。
例:
(2)创建结构元素
MATLAB图像处理工具箱中的strel函数可以生成任意维数和形状的结构元素,strel函数当然支持生成一般的形状,例如直线、菱形、圆盘、球形等的结构元素。
在图像处理中可以选用跟输入图像同样大小和形状的结构元素。例如为了发现图像中的直线,可以创建一个直线结构元素。
strel函数的常见调用方法如下:
se=strel('arbitrary',NHOOD):根据矩阵NHOOD创建一个平面结构元素,NHOOD中值为1的元素定义了结构元素的邻域
se=strel('arbitrary',NHOOD,HEIGHT):创建一个非平面的结构元素,其中,NHOOD规定了邻域,HEIGHT为与NHOOD同样大小的矩阵,其值为NHOOD中每个元素的高度值
se=strel('ball',R,H,N) :创建一个球形的结构元素,R为x-y平面上的半径,H为其高度,N为非负数
se=strel('diamond',R):创建一个菱形的结构元素,R为菱形的中心与其边界的最长距离
se=strel('disk',R,N): 创建一个圆盘的结构元素,R为圆盘的半径,N可以取值为:0,4,6,8,默认值为4
se=strel('line',LEN,DEG):创建一个线形的结构元素,LEN为长度,DEG为角度
se=strel('octagon',R):创建一个八边形的结构元素,其中R为八边形的中心到八边形边缘的最大距离,必须为3的倍数
se=strel('pair',OFFSET):创建一个成对的结构元素,其中一个元素在原点,另一个元素又OFFSET来决定,OFFSET为二维结构的数组
se=strel('periodicline',P,V):创建一个周期出现的结构元素。其中2*P+1为结构元素的周期数,V规定了两个周期之间的偏移
se=strel('rectangle',MN):创建一个矩形的结构元素,其中MN为二维数组,规定了矩形的行数和列数
se=strel('square',W):创建一个方形的结构元素,其中W为方形结构的宽度
例 :创建一个菱形的结构元素
se=strel('diamond',3)
se =
Flat STREL object containing 25 neighbors.
Decomposition: 3 STREL objects containing a total of 13 neighbors
Neighborhood:
0 0 0 1 0 0 0
0 0 1 1 1 0 0
0 1 1 1 1 1 0
1 1 1 1 1 1 1
0 1 1 1 1 1 0
0 0 1 1 1 0 0
0 0 0 1 0 0 0
我们可以看到数值为1的矩阵构成了一个菱形。
(3)结构元素分解
为了增强行数的性能,strel函数经常把结构元素分解成小块,这种技术称为结构元素的分解。例如,使用以11x11的结构元素对目标进行膨胀,等同于先使用一个1x11的结构元素进行膨胀,然后使用11x1的结构元素进行膨胀。这个方法理论上会使膨胀操作的速度提高5.5倍,但实际上速度提高没有那么多。
对于‘disk’或者‘ball’形状的结构元素,结构元素分解的结果是近似的,对于其他形状的结构元素分解的结果是精确的。只有结构元素的领域都是1组成的平面结构时,可以用于任意元素的分解。
使用getsequence函数可以查询到结构元素分解后的序列。该函数返回一个结构元素数组,每个元素为分解后的结构元素,它的常见调用方法如下:
seq=getsequence(se)
其中:
se是指要分解的结构元素
seq是分解后返回的结构元素。
例:将菱形结构元素分解,并创建新的结构元素
se=strel('diamond',4)
se =
Flat STREL object containing 41 neighbors.
Decomposition: 3 STREL objects containing a total of 13 neighbors
Neighborhood:
0 0 0 0 1 0 0 0 0
0 0 0 1 1 1 0 0 0
0 0 1 1 1 1 1 0 0
0 1 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 0
0 0 1 1 1 1 1 0 0
0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 0 0
>> seq=getsequence(se)
seq =
3x1 array of STREL objects
>> seq(1)
ans =
Flat STREL object containing 5 neighbors.
Neighborhood:
0 1 0
1 1 1
0 1 0
>> seq(2)
ans =
Flat STREL object containing 4 neighbors.
Neighborhood:
0 1 0
1 0 1
0 1 0
>> seq(3)
ans =
Flat STREL object containing 4 neighbors.
Neighborhood:
0 0 1 0 0
0 0 0 0 0
1 0 0 0 1
0 0 0 0 0
0 0 1 0 0
从结果可以看出这个菱形结构被分解成了三个比较小的结构元素
1.4 图像膨胀
对图像进行膨胀可以使用MATLAB图像处理工具箱中的imdilate函数,imdilate函数主要接收两个输入参数,一个是要处理的图像(灰度图像或者二值图像),另外一个是strel函数返回的结构元素对象,或者是定义了结构元素邻域的二值矩阵。
imdilate函数的常见调用方法如下:
IM2=imdilate(IM,SE)
IM2=imdilate(IM,NHOOD)
IM2=imdilate(....,shape)
其中:
IM是输入的要处理的二值图像或者灰度图像
SE是strel函数返回的结构元素
NHOOD是一个元素值只有0或者1的矩阵,规定了结构元素的邻域
shape规定了输出图像的形状,有两种选择,一种为‘same’,即跟输入图像相同大小,一种为‘full’,是全膨胀后的结果
IM2是返回的膨胀后的图像
例:对一个含有矩形块的图像进行了膨胀操作
BW=zeros(9,10);
>> BW(4:6,4:7)=1
BW =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
>> %为了扩展前景目标的所有边,使用3x3的方形结构元素
>> SE=strel('square',3)
SE =
Flat STREL object containing 9 neighbors.
Neighborhood:
1 1 1
1 1 1
1 1 1
>> BW2=imdilate(BW,SE)
BW2 =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0
0 0 1 1 1 1 1 1 0 0
0 0 1 1 1 1 1 1 0 0
0 0 1 1 1 1 1 1 0 0
0 0 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
>> %可以明显的看出,膨胀后的图像与膨胀前的图像相比,其边缘加了一圈1,也就是
>> %说膨胀的效果是使目标变得更大, 这正是膨胀两个字的意思。
例:对一个二值图像使用垂直线结构元素进行膨胀
bw=imread('text.png');
>> se=strel('line',11,90);%生成线形的结构元素,长度11,角度90(垂直线)
>> bw2=imdilate(bw,se);%对图像进行膨胀
>> subplot(121),imshow(bw),title('原始图像');
>> subplot(1,2,2),imshow(bw2),title('膨胀后的图像');
坐边图像为原图像text,右边图像为膨胀后的图像,其中垂直方向的字符因为膨胀连接起来,而水平方向的字母没有连接起来。
例:对一幅灰度图像使用球形的结构元素进行膨胀
I=imread('cameraman.tif');
>> se=strel('ball',5,5);%生成球形的结构元素,x-y平面上的半径5,高为5
>> I2=imdilate(I,se);%对图像进行膨胀
>> subplot(121),imshow(I),title('原始图像');
>> subplot(122),imshow(I2),title('膨胀后的图像');
左边图像为原图像cameraman,右边图像为膨胀后的图像。我们可以看到这幅灰度图像中人物的像素值较低,而周围背景的像素值较高,因此是背景像素值在增大,而人物像素值在减小。
在这种情况下,我们先对图像取反,任何进行膨胀操作,完成膨胀操作之后再取反就可以得到摄影师目标膨胀后的图像,如下例所示
例:灰度图像的膨胀(图像先取反后膨胀)
I=imread('cameraman.tif');
>> I1=256-I;%对图像进行取反操作
>> se=strel('ball',5,5);%生成球形的结构元素,x-y平面半径5,高度值5
>> I2=imdilate(I1,se);%对图像进行膨胀
>> I3=256-I2;%对膨胀后的图像取反
>> subplot(121),imshow(I),title('原始图像');
>> subplot(122),imshow(I3),title('膨胀后的图像');
因此,在图像膨胀过程中,要先区分要膨胀的目标元素,然后确定是不是需要取反操作来达到膨胀的目的。
1.5 图像腐蚀
MATLAB图像处理工具箱中使用imerode函数来对图像进行腐蚀。imerode函数与imdilate函数的用法类似,它主要接收两个输入参数,一个参数是要处理的图像,可以为灰度图像或者二值图像,另外一个参数是由strel函数返回的结构元素,或者定义结构元素邻域的二值矩阵。
imerode函数的常见调用方法如下:
IM2=imerode(IM,SE)
IM2=imerode(IM,NHOOD)
IM2=imerode(....,shape)
其中:
IM是输入的要处理的二值图像或者灰度图像
SE是strel函数返回的结构元素
NHOOD是一个元素值只有0或者1的矩阵,规定了结构元素的领域
shape规定了输出图像的形状,有两种选择,一种为‘same’,即与输入图像相同大小,一种为‘full’,是全腐蚀的结果
IM2是返回的腐蚀后的图像
各个参数的含义与imdilate函数的参数含义相同,只不过imdilate函数对输入图像执行的是膨胀操作,而imerode函数对输入图像执行的是腐蚀操作。
例:对一幅二值图像使用圆盘结构元素进行腐蚀操作
I=imread('circles.png');
>> se=strel('disk',11);%生成圆盘形的结构元素,半径11
>> I2=imerode(I,se);%对图像进行腐蚀
>> subplot(121),imshow(I),title('原始图像');
>> subplot(122),imshow(I2),title('腐蚀后的图像');
左边为原图像,右边为腐蚀后的图像,可以看到腐蚀后的图像中的圆形目标变小,也就是说腐蚀是指使目标对象被“腐蚀”,从而使目标对象变小,这与膨胀的效果正好相反。
例:对灰度图像进行腐蚀操作
I=imread('cameraman.tif');
>> se=strel('ball',5,5);%生成球形的结构元素,x-y平面半径5,高度值5
>> I2=imerode(I,se); %对图像进行腐蚀操作
>> subplot(121),imshow(I),title('原始图像');
>> subplot(122),imshow(I2),title('腐蚀后的图像');
可以发现腐蚀后的图像与先取反在进行膨胀操,然后再取反得到的图像类似,因此我们可以得出这样一个结论,对一幅图像先取反再进行膨胀操作,然后取反得到的图像与直接对图像进行腐蚀得到的效果是类似的。
1.6. 开运算和关运算
膨胀和腐蚀操作经常被一起使用来对图像进行处理。例如,形态学的开运算就是先对一幅图像进行腐蚀。然后再使用相同的结构元素进行膨胀操作。而关运算恰恰相反,关运算是先对一幅图像进行膨胀,然后再使用相同的结构元素对图像进行腐蚀操作。
(1)图像的开运算
下面使用imdilate函数和inerode函数进行形态学的开运算,开运算的效果是去除图像中的小目标而保持大目标的形状和大小不变。
例:二值图像的开运算
W1=imread('circbw.tif');
>> subplot(131),imshow(BW1),title('元素图像');
>> SE=strel('rectangle',[40 30]);
>> %生成矩形结构元素
>> BW2=imerode(BW1,SE);%对图像进行腐蚀
>> subplot(132),imshow(BW2),title('腐蚀后的图像');
>> BW3=imdilate(BW2,SE);%再对图像进行膨胀
>> subplot(133),imshow(BW3),title('先腐蚀后膨胀的图像');
程序中结构元素很大,因此可以去除图像中的线性结构,但不足以去除图像中的矩形块结构。可以看到腐蚀后的图像中去除了小的线性结构,同时矩形块结构也变小了,二膨胀之后则使图像中的举行块结构变大了。
MATLAB中也提供了专门的函数队图像进行开运算,即imopen,它的常见调用方法如下:
IM2=imopen(IM,SE)
IM2=imopen(IM,NHOOD)
其中:
IM是指要处理的图像,可以为二值图像或者灰度图像
SE是指strel函数返回的结构元素
NHOOD为只含有0和1的矩阵,规定了结构元素的邻域
IM2是返回的执行开运算后的图像。
例:利用imopen函数进行开运算
BW1=imread('circbw.tif');
>> subplot(121),imshow(BW1),title('原始图像');
>> SE=strel('rectangle',[40 30]);%生成矩形结构元素
>> BW2=imopen(BW1,SE);%对图像直接进行开运算
>> subplot(122),imshow(BW2),title('开运算后的图像');
从图中可以看出来,直接使用imopen函数得到的结果与先使用imerode函数再使用imdilate函得到的结果是相同的。
(2)图像的关运算
MATLAB中使用imclose函数进行关运算,它的常见调用方法与imopen函数的常见调用方法类似,其用法如下:
IM2=imclose(IM,SE)
IM2=imclose(IM,NHOOD)
其中,各个参数的含义与imopen函数的参数类似,这里就就不再赘述,下面通过一个例子来看一下imclose函数对图像进行关运算
例:二值图像的关运算
BW=imread('circles.png');
subplot(121),imshow(BW),title('原始图像');
SE=strel('disk',10);%创建圆盘形状的结构元素,半径为10
>> BW2=imclose(BW,SE);%关运算
>> subplot(122),imshow(BW2),title('关运算后的图像');
可以看到关运算可以填补图像中原有的空隙。
1.7 以膨胀和腐蚀为基础的其他操作
除了开和关运算外,MATLAB图像处理工具箱还提供了其他以膨胀和腐蚀为基础的形态学操作,例如bwmorph、bwperim等函数
(1)骨架提取
为了把图像中的目标缩减为直线而不改变图像的主要结构,可以使用bwmorph函数来提取图像中目标的骨架,它常见调用方法如下:
BW2=bwmorph(BW,‘skel’)
BW2=bwmorph(BW,‘skel’,n)
其中:
BW是输入的二值图像
skel是专门的形态学操作
n是指该形态学操作执行的次数,可以为无限次,直到图像不发生变化为止
BW2是返回的提取骨架后的图像
例:对一幅图像进行骨架提取
W1=imread('circbw.tif');
>> BW2=bwmorph(BW1,'skel',Inf);
>> subplot(121),imshow(BW1),title('原始图像');
>> subplot(122),imshow(BW2),title('骨架提取后的图像');
从右图中可以看到图像的骨架
(2)边缘检测
对于二值图像来说,如果它的像素值为1,而邻域中至少有一个像素值为0则称其为边界像素,MATLAB图像处理工具箱中使用bwperim函数来检测图像的边界,它的常见调用方法如下:
BW2=bwperim(BW1)
BW2=bwperim(BW1,conn)
其中:
BW1是指输入的二值图像
conn规定了连通性,对于二维图像来说,conn可以为4或者8,默认为4,对于三维图像来说,conn可以为6,18或者26,默认值为6.
BW2是返回的边界图像
例:图像的边缘检测
BW1=imread('circbw.tif');
>> BW2=bwperim(BW1,8);
>> subplot(121),imshow(BW1),title('原始图像');
>> subplot(122),imshow(BW2),title('边缘检测后的图像');
2.数学形态学重建
图像重建是指两幅图像和一个结构元素的形态学变换,一幅图像为标记图像,是变换的开始点,另一幅图像是掩模图像,是来约束变换过程。
数学形态学重建在概念上可以理解为对标记图像进行重复膨胀,直到标记图像的轮廓适合掩模图像为止。在形态学重建中,标记图像的极值点被展开,即膨胀。
形态学的重建是以膨胀运算为基础,需要指出的是他有下面的特性
(1)重建以两幅图像为基础,其中一幅是标记图像,一幅是掩模图像,而不是以一个图像和一个结构元素为基础
(2)重建基于连通性,而不是结构元素
(3)重建知道图像不再变化的时候停止。
2.1 理解标记图像和掩模图像
形态学重建根据掩模图像的性质对标记图像进行处理,处理是从亮点或者标记的点开始的,直到图像不再发生变化为止。
为了表示形态学重建,下面将用一幅简单图像为掩模图像进行说明。它包含两主要的区域,其中一个是像素值为14的图像块,另一个是像素值为18的图像块,背景元素主要是10,少数像素值为11.
Mask =[
10 10 10 10 10 10 10 10 10 10
10 14 14 14 10 10 11 10 11 10
10 14 14 14 10 10 10 11 10 10
10 14 14 14 10 10 11 10 11 10
10 10 10 10 10 10 10 10 10 10
10 11 10 10 10 18 18 18 10 10
10 10 10 11 10 18 18 18 10 10
10 10 11 10 10 18 18 18 10 10
10 11 10 11 10 10 10 10 10 10
10 10 10 10 10 10 11 10 10 10 ];
按照下面的步骤,对这幅图像进行形态学重建。
(1)创建一个标记图像。就像膨胀和腐蚀操作中的结构元素一样,标记图像的特征决定了形态学重建的处理过程。标记图像的峰值确定了掩模图像中需要强调的目标位置。
创建标记图像的一个方法是使用imsubtract函数冲掩模图像中减去一个常亮。
marker=imsubtract(Mask,2)
marker =
8 8 8 8 8 8 8 8 8 8
8 12 12 12 8 8 9 8 9 8
8 12 12 12 8 8 8 9 8 8
8 12 12 12 8 8 9 8 9 8
8 8 8 8 8 8 8 8 8 8
8 9 8 8 8 16 16 16 8 8
8 8 8 9 8 16 16 16 8 8
8 8 9 8 8 16 16 16 8 8
8 9 8 9 8 8 8 8 8 8
8 8 8 8 8 8 9 8 8 8
(2)调用imreconstruct函数对图像进行形态学重建。在输出图像中,注意到除了亮度峰值以外的所有亮度被动被去除了。
recon=imreconstruct(marker,Mask)
recon =
10 10 10 10 10 10 10 10 10 10
10 12 12 12 10 10 10 10 10 10
10 12 12 12 10 10 10 10 10 10
10 12 12 12 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 16 16 16 10 10
10 10 10 10 10 16 16 16 10 10
10 10 10 10 10 16 16 16 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
下图显示了一维的形态学重建,每个连续的膨胀受限于掩模图像的像素值,必须位于掩模图像的下方,当进一步膨胀而图像没有变化时,重建过程就停止。最后得到的膨胀图像即为重建后的图像。
2.2 像素连通性
形态学的处理操作从标记图像的极值开始,然后以像素的连通性为基础扩展到图像的其他部分。连通性定义了像素之间的链接情况,即哪些像素是相连的。
例如,下面的二值图像包含了一个前景对象,它的像素值为1。如果前景是4连通的,则图像只有一个背景块,其所有像素值为0,如果背景是8连通的,则背景形成一个回路,并且图像又两个分离的背景,即回路里面的背景和回路外面的背景,可见选取不同的像素连通性会有不同的背景对象。
2.3 填充操作
MATLAB图像处理工具箱中使用imfill函数对二值图像或者灰度图像进行填充操作,它常见调用方法如下:
BW2=imfill(BW,location)
BW2=imfill(BW,‘holes’)
I2=imfill(I)
BW2=imfill(BW,location,conm)
其中:
BW是指二值图像
location规定了填充操作的起始点
holes规定了填充二值图像中的孔洞
I是指灰度图像,即此函数可以填充灰度图像
conn规定了连通性,其值对于二维图像来说可以为4或者8
对于二值图像和灰度图像,imfill函数规定的连通性决定了其处理过程中的边界。注意,imfill函数与其他基于目标对象操作的函数不同,它对背景像素进行操作。当用imfill函数指定连通性的时候,指定的是背景像素的连通性,而不是前景像素的连通性。
连通性的含义可以用下面的矩阵来解释
BW =0 0 0 0 0 0 0 0];
如果背景是4连通的,则二值图像包含两个分离的背景部分,回路里面的部分和回路外面的部分。如果背景是8连通的,像素沿对角进行连接,则只包含一个背景部分。
对于二值图像,通过指定坐标位置或者用鼠标交互式操作可以规定填充的起点。例如,如果调用imfill函数,指定像素BW(4,3)作为起始点,imfill函数只能填充了回路里面,因为默认的背景是4连通的。
BW=logical(BW);
>> imfill(BW,[4,3])
ans =
0 0 0 0 0 0 0 0
0 1 1 1 1 1 0 0
0 1 1 1 1 1 0 0
0 1 1 1 1 1 0 0
0 1 1 1 1 1 0 0
0 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
如果使用同样的起始点,但使用8连通的背景,则imfill函数将对整个图像进行填充。
imfill(BW,[4 3],8)
ans =
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
填充操作的一个用途就是对图像中的孔洞进行填充。例如,对于一幅二值图像或者灰度图像,前景对象代表球体。在图像中,这些对象应该是实心的,但是由于原始照片中存在反射现象而呈圆环状态。在这幅图像做下一步的处理前,可以先用imfill函数填充图像中的孔洞。
由于填充孔洞是一个很常用的操作。因此imfill函数提供了特别的调用方法来支持对二值或者灰度图像进行填充。在这种用法中,只需要给出‘holes’参数即可,而不必规定每一个孔的初始位置。
例:下面以一副灰度图像为例来说明图像的孔洞填充操作
BW=imread('coins.png');
>> BW=im2bw(BW);%灰度图像转化为二值图像
>> BW1=imfill(BW,'holes');%对图像进行填充
>> subplot(121),imshow(BW),title('原始图像');
>> subplot(122),imshow(BW1),title('填充后的图像');
2.4寻找最大值和最小值
灰度图像可以认为是三维的,x轴和y轴代表了像素的位置,z轴代表了像素值的强度。在这种理解中,像素值的强度就像地形图上的山峰和山谷一样,是很重要的形态学特征,因为他们经常表示相关的图像对象。
例如,在一个包含有几个球形对象的图像中,像素值大的点可能代表对象的顶部。在作形态学处理时,用这些最大值可以识别图像中的对象。
本节包括下面几个主题
理解最大值和最小值函数
发现高亮度区和低亮度区
抑制最大值和最小值
强调显示最小值
(1)理解最大值和最小值函数
常见的最大值和最小值术语列如下表所示。
在一幅图像中,可以有很多局部极大值和局部极小值,而全局最大值和全局最小值只有一个。确定图像的峰值和谷值可用用来创建标记图像,该图像用于数学形态学重建。
术语 定义
局部极大值 在这个像素的周围区域,像素值都比这个像素值要小
局部极小值 在这个像素的周围区域,像素值都比这个像素值要大
全局最大值 在所有局部极大值中的最大值
全局极小值 在所有极小值中的最小值
(2)发现高亮度区和低亮度区
可以使用MATLAB图像处理工具箱中的函数来确定图像的高亮度区和低亮度区。
imregionalmax函数和imregionalmin函数确定所有的极大值和极小值
imextendedmax函数和imextendedmin函数确定大于某阈值的极大值和小于某阈值的极小值
这些函数把灰度图像作为输入参数,而把二值图像作为输出参数。在输出的二值图像中,局部极大值和局部极小值设为1,其他值设为0.
imregionalmax函数的常见调用方法如下:
BW=imregionalmax(I)
BW=imregionalmax(I,conn)
其中:
I是输入的图像
conn规定了连通性,二值图像默认值为8
BW是返回的二值图像,跟I的维数相同,值为1的位置即为局部极大值的位置。
imregionalmin函数的常见调用方法与imregionalmax函数的类似,只不过imregionalmin函数返回的是局部极小值的位置。
例如下面的图像包含两个主要的局部极大值,其中一块的像素值为13,另一块的像素值为18,还有一些像素值为11的较小的局部极大值。
10 10 10 10 10 10 11 10 10 10 ];
imregionalmax函数返回的二值图像确定了局部极大值的点和位置。
B=imregionalmax(A)
B =
0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 0 1 0 1 0
0 1 1 1 0 0 0 1 0 0
0 1 1 1 0 0 1 0 1 0
0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 1 1 1 0 0
0 0 0 1 0 1 1 1 0 0
0 0 1 0 0 1 1 1 0 0
0 1 0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
如果只是想要确定图像中那些像素值变化比较大的区域,也就是说像素值的差异大于或者小于某个阈值,可以使用imextendedmax函数,它的常见调用方法如下:
BW=imextendedmax(I,H)
BW=imextendedmax(I,H,conn)
其中:
I是输入的图像
H是阈值,即该像素值和邻域像素值之间的差异大于阈值才为极值
conn规定了连通性,对于二值图像其默认值为8
BW是返回的二值图像,跟I的维数相同
imextendedmin函数的常见调用方法和imextendedmax函数的类似。
对于上面的矩阵,如果加入阈值2,其返回矩阵中只有2个极大值区域
B=imextendedmax(A,2)
B =
0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
例:显示一幅图像的局部极小值
I=imread('glass.png');
>> BW=imextendedmin(I,50);%求取图像的极小值的二值图像,阈值为50
>> subplot(121),imshow(I),title('原始图像');
>> subplot(122),imshow(BW),title('极小值的二值图像');
原图像中黑色为像素值比较小的区域,而白色为像素值比较大的区域,该函数去图像的极小值,因此返回的二值图像中极小值为1,显示为白色,其他区域为0,显示为黑色。
(3)抑制最小值和最大值
在一幅图像中,像素值的小的波动可能会呈现出局部极大值或极小值。然而,很多时候,这些由背景纹理引起的很小的局部极大值或者极小值我们并不关心,我们感兴趣的是很显著的局部极大值和局部极小值。
为了去除那些不明显的局部极大值而保留那些明显的局部极值,可以使用MATLAB图像处理工具箱中的imhmax函数和imhmin函数。使用这些函数,可以规定对比准则和阈值h,来抑制那些小于h的极大值或者大于h的极小值。
imhmax函数的常见调用方法如下:
I2=imhmax(I,h)
I2=imhmax(I,h,coon)
其中:
I是输入图像
h是一个标量,I中小于h的局部极大值被抑制
I2是返回的跟I同样大小的矩阵
例:下面的图像包含两个主要的局部极大值,其中一块的像素值为14,另一块的像素值为18,还有些像素值为11的局部极小值。
A=[
10 10 10 10 10 10 10 10 10 10
10 14 14 14 10 10 11 10 11 10
10 14 14 14 10 10 10 11 10 10
10 14 14 14 10 10 11 10 11 10
10 10 10 10 10 10 10 10 10 10
10 11 10 10 10 18 18 18 10 10
10 10 10 11 10 18 18 18 10 10
10 10 11 10 10 18 18 18 10 10
10 11 10 11 10 10 10 10 10 10
10 10 10 10 10 10 11 10 10 10 ];
为了去除比较小的极大值而保留两个明显的局部极大值,可以使用imhmax函数,阈值h设为2。注意imhmax函数只影响极大值,其他值保持不变,两个明显的局部极大值保留下来,但其像素值比原来少2。 B=imhmax(A,2)
B =
10 10 10 10 10 10 10 10 10 10
10 12 12 12 10 10 10 10 10 10
10 12 12 12 10 10 10 10 10 10
10 12 12 12 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 16 16 16 10 10
10 10 10 10 10 16 16 16 10 10
10 10 10 10 10 16 16 16 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
下图以A中第二行为例来显示imhmax函数是如何改变图像轮廓的
imhmin函数的常见调用方法与imhmax的类似,只不过imhmin函数求的是极小值。
例如下面的图像a包含两个明显的局部极小值,其中一块像素值为7,另一块的像素值为2,如果选取阈值为4,则像素值为7的像素块与周围像素的差值为3,小于阈值,因此不会显示,而返回的图像中只显示像素值为2的图像块,不过其像素值为原来像素值加4.
a =10 10 10 10 10 10 10 10 10 10]
b=imhmin(a,4)
b =
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 6 6 6 10 10
10 10 10 10 10 6 6 6 10 10
10 10 10 10 10 6 6 6 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
(4)强调显示最小值
可以使用MATLAB图像处理工具箱中的imimposemin函数来强调专门的极小值,它的常见调用方法如下:
I2=imimposemin(I,BW)
I2=imimposemin(I,BW,coon)
其中:
I是输入的图像
BW是二值图像,一般为标记图像,用来确定最小值的位置
conn规定了连通性,对于二值图像其默认值为8
I2是返回的强调显示最小值的图像
下面的代码创建了一幅图像,包含两个明显的局部极小值和一些不太明显的极小值,使用这个图像来阐述强调显示最小值的过程。
mask=uint8(10*ones(10,10));
>> mask(6:8,6:8)=2;
>> mask(2:4,2:4)=7;
>> mask(3,3)=5;
>> mask(2,9)=9;
>> mask(3,8)=9;
>> mask(9,2)=9;
>> mask(8,3)=9;
>> mask
mask =
10 10 10 10 10 10 10 10 10 10
10 7 7 7 10 10 10 10 9 10
10 7 5 7 10 10 10 9 10 10
10 7 7 7 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 2 2 2 10 10
10 10 10 10 10 2 2 2 10 10
10 10 9 10 10 2 2 2 10 10
10 9 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
为了得到只包含两个最小值的局部极小值的图像,需要创建一个标记图像来标明两个局部极小值,可以通过明确地设定某些像素值或者使用其他形态学来创建标记图像,以提取掩模图像中需要强调的特征。
下面使用imextendedmin函数得到一个二值图像来显示两个最小的极小值的位置。
marker=imextendedmin(mask,1) %阈值1
marker =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
下面使用imimposemin函数来创建掩模图像中由标记图像标识的新的最小值。注意imimposemin函数将把标记图像标识的像素值设定为该图像类型的最小值,同时会改变剩下的像素值以去除其他最小值
I=imimposemin(mask,marker)
I =
11 11 11 11 11 11 11 11 11 11
11 8 8 8 11 11 11 11 11 11
11 8 0 8 11 11 11 11 11 11
11 8 8 8 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 0 0 0 11 11
11 11 11 11 11 0 0 0 11 11
11 11 11 11 11 0 0 0 11 11
11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11
3.距离变换
距离变换提供了图像中分离的点之间的量度,MATLAB图像处理工具箱中的bwdist函数可以计算0像素值与最近的非0像素值之间的距离。
bwdist函数的常见调用方法如下:
D=bwdist(BW)
[D,L]=bwdist(BW)
[D,L]=bwdist(BW,method)
其中:
BW是输入的二值图像
method规定了求距离时使用的方法,默认为欧式距离
D是返回的跟BW同样维数的距离矩阵
L是返回的标签矩阵,与BW同样维数,L的值即为BW中最近的非零值的索引。
method的取值如下表
例:计算一个简单图像的欧式距离
bw=zeros(5,5);
bw(2,2)=1;
bw(4,4)=1; %设定像素值为1
>> bw
bw =
0 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 1 0
0 0 0 0 0
>> [D,L]=bwdist(bw) %计算欧式距离
D =
1.4142 1.0000 1.4142 2.2361 3.1623
1.0000 0 1.0000 2.0000 2.2361
1.4142 1.0000 1.4142 1.0000 1.4142
2.2361 2.0000 1.0000 0 1.0000
3.1623 2.2361 1.4142 1.0000 1.4142
L =
7 7 7 7 7
7 7 7 7 19
7 7 7 19 19
7 7 19 19 19
7 19 19 19 19
其中,L中的7是指矩阵的第7个像素值(即第二行第二列),而19是指矩阵的第19个像素值(即第4行第四列),这两个像素值为1.
4.对象的标记和测量
在对图像进行进一步的处理之前,往往首先需要对图像的目标区域进行标记,获取目标区域的相关属性。MATLAB图像处理工具箱中提供了相关的函数,包括bwlabel(连通区域的标记)、bwselect(选择对象)、bwarea(计算对象面积)和bweuler(欧拉数)等。
4.1连通区域的标记
MATLAB图像处理工具箱中的bwlabel函数和bwlabeln函数可以确定二值图像中对象的个数,并且对这些对象进行标记,bwlabel函数只支持二维的输入,而bwlabeln函数可以支持任何维的输入。
bwlabel函数的常见调用方法如下:
L=bwlabel(BW,n)
[L,num]=bwlabel(BW,n)
其中:
BW是输入的二值图像
n规定了连通性,可以为4或者8,默认值为8
L是返回的跟BW同样大小的矩阵,称为标注矩阵,其中的元素大于或者等于0,0指背景,1指第一个对象,2指第二个对象,依次类推
num是二值图像中对象的数目
bwlabe函数和bwlabeln函数把输入图像中不同的对象以不同的整数值标注。二值图像中对象的像素值为1,这些像素称为前景,显示的颜色为白色;而像素值为0的像素则构成了图像的背景,显示的颜色为黑色。
例:本例说明了bwlabel函数如何确定二值图像中的对象,在输入的二值图像BW中,值为1的像素构成了图像的对象,值为0的像素构成了图像的背景。
在输出的标注矩阵X中,bwlabel函数寻找输入图像中的每一个对象,并且根据寻找到的顺序用不同的数字标注他们。因此,第二个寻找到的目标,像素值设为2,而第三寻找到的目标,其像素值设为3,而背景像素保持不变为0.
BW =[
0 0 0 0 0 0 0 0;
0 1 1 0 0 1 1 1;
0 1 1 0 0 0 1 1;
0 1 1 0 0 0 0 0;
0 0 0 1 1 0 0 0;
0 0 0 1 1 0 0 0;
0 0 0 1 1 0 0 0;
0 0 0 0 0 0 0 0 ];
X=bwlabel(BW,4)
X =
0 0 0 0 0 0 0 0
0 1 1 0 0 3 3 3
0 1 1 0 0 0 3 3
0 1 1 0 0 0 0 0
0 0 0 2 2 0 0 0
0 0 0 2 2 0 0 0
0 0 0 2 2 0 0 0
0 0 0 0 0 0 0 0
由bwlabel函数和bwlabeln函数返回的标注矩阵是double类型,而不是二值图像。要查看此图像,有一种方法是使用label2rgb函数把它显示为伪彩色索引图像。在伪彩色索引图像中,标注矩阵中用来确定对象的每个数字作为索引值与颜色映射矩阵相连。
label2rgb函数的常见调用方法如下:
RGB=label2rgb(L)
RGB=label2rgb(L,map)
RGB=label2rgb(L,map,zerocolor)
其中:
L是由bwlabel函数或者bwlabeln函数返回的标注矩阵
map是颜色映射矩阵,可以为一个nx3的矩阵,也可以为“@jet”,“@gray”等
zerocolor是标注矩阵中值为0的像素所显示的颜色,‘b’即蓝色,‘k’即黑色,也可以根据不同需要显示其他颜色
RGB是返回的彩色图像
下面使用label2rgb函数对上面求得标注矩阵进行显示。该函数使用标准的颜色映射表jet,第三个参数‘k’指定背景颜色为黑色
RGB=label2rgb(X,@jet,'k');
imshow(RGB,'InitialMagnification','fit')
4.2 选择二值图像中的对象
可以使用MATLAB图像处理工具箱中的bwselect函数来选择二值图像中的单个对象,bwselect函数的常见调用方法如下:
BW2=bwselect(Bw,c,r,n)
其中:
BW是输入的二值图像
(r,c)确定了像素值的坐标
n规定了连通性,可以为4或者8,默认值为8
BW2是返回的二值图像,包含了(r,c)确定的对象
例:对象的选择
BW1=imread('text.png');
>> c=[43 185 212];%规定了对象的列数
>> r=[38 68 181];%规定了对象的行数
>> BW2=bwselect(BW1,c,r,4);%选择对象,连通性为4
>> subplot(121),imshow(BW1),title('原图像');
>> subplot(122),imshow(BW2),title('选择的对象');
4.3 计算二值图像的欧拉数
MATLAB图像处理工具箱中的bweuler函数返回一幅二值图像中的欧拉数。欧拉数是图像拓扑结构的一种测量,它定义为对象的总个数与对象中孔洞的个数的差。
bweluer函数的常见调用方法如下:
eul=bweuler(BW)
eul=bweuler(BW,n)
其中:
BW是输入的二值图像
n规定了连通性,可以为4或者8,默认值为8
例:计算二值图像中的欧拉数
BW=imread('circles.png');
imshow(BW),title('原图');
>> eul=bweuler(BW) %计算欧拉数
eul =
-3 %因为图像中只有一个对象,而有4个孔洞,因此欧拉数1-4=-3、
小结:
形态学操作是基于形状的图像处理技术。本章首先从形态学的基本操作膨胀和腐蚀入手,对以这两种操作为基础的其他形态学操作,如图像的开关和闭合操作做了详细是描述。然后对数学形态学重建,距离变换、基于对象的操作做了介绍。
更多MATLAB图像处理视频请点击 http://study.163.com/course/courseMain.htm?courseId=1003594013