8.2.5 仿真与调试结果
1.sort_1d验证 对于一维排序的验证,同时例化2个尺寸分别为3×3和5×5的一维 排序模块,输出中值,再例化2个尺寸为3×3的一维排序模块,分别输 出最大值和最小值。生成随机数进行验证,Testbench如下:
/*sort 1d test*/
generate
if(sort_1d_en != 0)begin :sort_1d_operation
reg [local_dw-1:0]sort_1d_din;
wire sort_1d_din_valid;
wire[local_dw-1:0]sort_1d_dout;
wire sort_1d_dout_valid;
//尺寸3*3 中值输出(默认)
assign sort_1d_din_valid = cap_dvalid;
sort_1d sort_1d_ins(
.clk(cap_clk),
.rst_n(reset_l),
.din_valid(sort_1d_din_valid),.din(sort_1d_din),
.dout_valid(sort_1d_dout_valid),
.dout(sort_1d_dout)
);
wire[local_dw-1:0]sort_1d_5_dout;
wire sort_1d_5_dout_valid;
//尺寸5*5 中值输出(默认)
sort_1d sort_1d_5_ins(
.clk(cap_clk),
.rst_n(reset_l),
.din_valid(sort_1d_din_valid),
.din(sort_1d_din),
.dout_valid(sort_1d_5_dout_valid),
.dout(sort_1d_5_dout)
);
defparam sort_1d_5_ins.KSZ = 5;
wire[local_dw-1:0]sort_max_1d_dout;
wire sort_max_1d_dout_valid;
//尺寸3*3 最大值输出
sort_1d sort_max_1d_ins(
.clk(cap_clk),
.rst_n(reset_l),
.din_valid(sort_1d_din_valid),
.din(sort_1d_din),
.dout_valid(sort_max_1d_dout_valid),
.dout(sort_max_1d_dout)
);defparam sort_max_1d_ins.KSZ = 3;
defparam sort_max_1d_ins.OUT_ID = 0;
//尺寸3*3 最小值输出
wire[local_dw-1:0]sort_min_1d_dout;
wire sort_min_1d_dout_valid;
sort_1d sort_min_1d_ins(
.clk(cap_clk),
.rst_n(reset_l),
.din_valid(sort_1d_din_valid),
.din(sort_1d_din),
.dout_valid(sort_min_1d_dout_valid),
.dout(sort_min_1d_dout)
);
defparam sort_min_1d_ins.KSZ = 3;
defparam sort_min_1d_ins.OUT_ID = 2;
//生成随机数
always @(reset_l or posedge cap_clk)
begin
if ((~(reset_l)) == 1'b1)
sort_1d_din <= {local_dw{1'b0}};
else
if(cap_dvalid == 1'b1)
sort_1d_din <= {$random} % 50;
end
end
endgenerate
截取的仿真图如图8-8所示。
经过简单的计算就不难验证,仿真结果与实际计算值完全吻合。 特别需要注意的是,我们在图中列出了5×5窗口的排序和结果 cmp_sum_5*5,这5个计算和值就代表了当前输入5个数据的排序序列, 很明显,这5个序列值在同一时刻任何两个值都是不同的,从仿真图中 我们也可以验证。 我们还注意到,3×3的输出延时为6个时钟,而5×5的输出延时为 9个时钟,这是出于提高系统工作频率的考虑,将输入和输出多打了一 拍,同时加法电路用多个时钟完成的缘故。具体的时序细节,请读者 阅读参考代码。 2.sort_2d验证 对于二维的排序运算的验证,会直接采用一幅经过椒盐噪声污染 的图像,分别用尺寸为3×3的中值输出,最大值输出和最小值输出对原始图像进行滤波,由此来验证设计代码的正确性。 图8-9(a)所示为原始经过椒盐噪声污染的图像,图8-9(b)所 示为经过中值滤波后的输出图像。
由图8-9可见,中值滤波有效地去除了输入图像的椒盐噪声。 接着将输出参数OUT_ID改为2和0,以实现最大值和最小滤波,结 果分别如图8-10和图8-11所示。
由于最大值滤波是取局部最大值,因此盐噪声将会得到扩充,图 像会变亮;而最小值滤波是取局部最小值,因此椒噪声会得到扩充, 图像会变暗。
第9章 形态学滤波
9.1 形态学滤波简介
数学形态学是一门建立在集论基础上的学科,是几何形态学分析 和描述的有力工具。数学形态学的历史可回溯到19世纪。1964年法国 的Matheron和Serra在积分几何的研究成果上,将数学形态学引入图像 处理领域,并研制了基于数学形态学的图像处理系统。
1982年出版的 专著Image Analysis and Mathematical Morphology是数学形态学发 展的重要里程碑,表明数学形态学在理论上趋于完备及应用上不断深 入。数学形态学蓬勃发展,由于其并行快速,易于硬件实现,已引起 了人们的广泛关注。目前,数学形态学已在计算机视觉、信号处理与 图像分析、模式识别、计算方法与数据处理等方面得到了极为广泛的 应用。 数学形态学可以用来解决抑制噪声、特征提取、边缘检测、图像 分割、形状识别、纹理分析、图像恢复与重建、图像压缩等图像处理 问题。下文将主要对数学形态学的基本理论及其在图像处理中的应用 进行综述。
1.数学形态学的定义 数学形态学是以形态结构元素为基础对图像进行分析的数学工 具,它的基本思想是,用具有一定形态的结构元素度量和提取图像中的对应形状,以达到对图像分析和识别的目的。数学形态学的应用可 以简化图像数据,保持它们基本的形状特征,并除去不相干的结构。 数学形态学的基本运算有4个:膨胀、腐蚀、开运算和闭运算。它们在 二值图像中和灰度图像中各有特点。基于这些基本运算还可以推导和 组合成各种数学形态学实用算法。
2.分类 1)二值形态学 数学形态学中二值图像的形态变换是一种针对集合的处理过程。 其形态算子的实质是表达物体或形状的集合与结构元素间的相互作 用,结构元素的形状就决定了这种运算所提取的信号的形状信息。形 态学图像处理是在图像中移动一个结构元素,然后将结构元素与下面 的二值图像进行交、并等集合运算。 二值形态膨胀与腐蚀可转化为集合的逻辑运算,算法简单,适于 并行处理,且易于硬件实现,适于对二值图像进行图像分割、细化、 抽取骨架、边缘提取、形状分析。但是,在不同的应用场合,结构元 素的选择及其相应的处理算法是不一样的,对不同的目标图像需设计 不同的结构元素和不同的处理算法。结构元素的大小、形状选择合适 与否,将直接影响图像的形态运算结果。因此,很多学者结合自己的 应用实际,提出了一系列的改进算法。如梁勇提出的用多方位形态学 结构元素进行边缘检测算法,既有较好的边缘定位能力又有很好的噪 声平滑能力;许超提出的以最短线段结构元素构造准圆结构元素或序 列结构元素生成准圆结构元素相结合的设计方法,用于骨架的提取, 可大大减少形态运算的计算量,并可同时满足尺度、平移及旋转相容 性,适于对形状进行分析和描述。 2)灰度数学形态学 二值数学形态学可方便地推广到灰度图像空间。只是灰度数学形 态学的运算对象不是集合而是图像函数。灰度数学形态学中开启和闭合运算的定义与在二值数学形态学中的定义一致。 3)模糊数学形态学 将模糊集合理论用于数学形态学就形成了模糊形态学。模糊算子 的定义不同,相应的模糊形态运算的定义也不相同,模糊性由结构元 素对原图像的适应程度来确定。模糊形态学是传统数学形态学从二值 逻辑向模糊逻辑的推广,与传统数学形态学有相似的计算结果和相似 的代数特性。模糊形态学重点研究n维空间目标物体的形状特征和形态 变换,主要应用于图像处理领域,例如模糊增强、模糊边缘检测和模 糊分割等。
9.2 形态学滤波的基本应用
本节主要介绍形态学滤波的一些基本应用。 1.膨胀与腐蚀 膨胀与腐蚀是形态学滤波的两个基本运算,能实现多种多样的功 能,主要功能如下: (1)消除噪声。 (2)分割出独立的图像元素。 (3)在图像中连接相邻的元素。 (4)寻找图像中明显的极大值和极小值区域。 (5)求出图像的梯度。 1)膨胀 膨胀(dilate)就是求局部最大值的操作。从数学角度上来说, 膨胀和腐蚀就是将图像(或图像的一部分区域,称之为A)与核(称之 为B)进行卷积的一个过程。
需要注意的是,核可以是任意的形状和大小,它拥有一个单独定 义出来的参考点,我们称之为锚点(anchorpoint)。在多数情况下, 核是一个小的中间带有参考点的十字形、实心矩形(一般是正方形) 或者圆盘。其实,可以把核视为模板或者掩码。 膨胀就是求局部最大值的操作。核B与图像卷积,即计算核B覆盖 的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像 素,如图9-1所示。这样就会使图像中的高亮区域逐渐增长,也就是对 图像中高亮的部分进行膨胀,类似于“领域扩张”。可以预见的是, 效果图将会拥有比原图更大的高亮区域,亮度会有所增加,同时可以 连通相邻的高亮度区域。通过膨胀我们可以将图像中的裂缝得到填 补,例如,一个破镜子的照片,通过膨胀处理,可以恢复出完整的样 子。
注:在本节中,公式中的各个元素定义如下。 (x,y)表示输入图像的行列坐标; I(x,y)表示坐标为(x,y)处的输入图像像素值; g(x,y)表示坐标为(x,y)处的滤波结果输出; Db 表示运算核的作用域,以当前像素为中心的矩形窗 将(x,y)从图像左上角到右下角依次进行像素遍历,即可得到整幅 图像的滤波结果(公式中不考虑边界)。 根据膨胀操作的数学定义,我们给出膨胀操作的C代码如下:
/*全局参数*/
DWORD m_dwWidth,m_dwHeight;/*待处理图像的宽度和高度*/
WORD MorphRadius;/*矩形处理窗的半径*/
/*边界不作处理*/
void Morph_Dialate(BYTE *p_InputImg,BYTE
*p_DialateResult)
/* 输 入 图 像 放 在 p_InputImg 中 , 处 理 结 果 图 像 存 放 在
p_DialateResult 中*/
{
int max=0;
int i,j,k,m=0;
for( i= MorphRadius; i<m_dwHeight- MorphRadius; i++)
for( j= MorphRadius; j<m_dwWidth - MorphRadius; j++)/*
遍历整幅图像*/{
max =p_InputImg[i*m_dwWidth+j];
for (m=- MorphRadius;m<= MorphRadius;m++)/*遍历整
个窗口寻找最大值*/
for (k=- MorphRadius;k<= MorphRadius;k++)
{
if(p_InputImg[(i+m)*m_dwWidth+j+k]>max)
max=p_InputImg[(i+m)*m_dwWidth+j+k];
}
p_DialateResult [i*m_dwWidth+j]=max;//膨胀
}
}
假 设一个有缺陷的圆形,在该圆形的右上方有一个黑色的斑点和 一些线缺陷,如图9-2所示。 选取核B为5×5的矩形窗,对图9-2进行膨胀操作,结果如图9-3所 示。
正如我们所预料的一样,膨胀操作有效去除了尺寸比核B小的黑色 缺陷及线缺陷。 图9-4为另一幅测试图片。 以尺寸为9×9的矩形窗对齐进行膨胀操作,得到结果如图9-5所 示。 由图9-5可以看出,膨胀操作可有效连通相邻的高亮区域。2)腐蚀 腐蚀(erode)和膨胀是一对对立的操作,因此,腐蚀就是求局部 的最小值。腐蚀的操作实例如图9-6所示。 通过腐蚀,图像中的高亮区域被腐蚀掉了,类似于“领域被蚕 食”。可以预见的是腐蚀过后的图像将会拥有比原图更小的高亮区 域,亮度会有所下降。同时,腐蚀操作还会连通相邻的比较暗的区 域。
根据腐蚀操作的数学定义,这里给出腐蚀操作的C代码如下:
/*边界不作处理*/
void Morph_Erode(BYTE *p_InputImg,BYTE *p_ErodeResult)
/* 输 入 图 像 存 放 在 p_InputImg 中 , 处 理 结 果 图 像 存 放 在
p_ErodeResult 中*/
{
int min=0;
int i,j,k,m=0;
for( i= MorphRadius; i<m_dwHeight- MorphRadius; i++)
for( j= MorphRadius; j<m_dwWidth - MorphRadius; j++)/*
遍历整幅图像*/
{
min =p_InputImg[i*m_dwWidth+j];
for (m=- MorphRadius;m<= MorphRadius;m++)/*遍历整
个窗口寻找最小值*/
for (k=- MorphRadius;k<= MorphRadius;k++)
{
if(p_InputImg[(i+m)*m_dwWidth+j+k]<min)min=p_InputImg[(i+m)*m_dwWidth+j+k];
}
p_ErodeResult [i*m_dwWidth+j]=min;//腐蚀结果
}
}
对图9-4进行相同尺寸的腐蚀处理,如图9-7所示。
可见,比B核尺寸小的高亮区域都被腐蚀掉了。同时,较大尺寸的 高亮区域也被腐蚀掉一部分,这无疑对小尺寸的高亮区域识别是有益 的。 2.开运算与闭运算 1)开运算 开运算(Opening Operation)其实就是先腐蚀后膨胀的过程。其 数学表达式如下:
根据开运算的数学定义,我们给出开运算的C代码如下:
/*边界不作处理*/
void Morph_Open(BYTE *p_InputImg ,BYTE *p_OpenResult)
/* 输 入 图 像 存 放 在 p_InputImg 中 , 处 理 结 果 图 像 存 放 在
p_OpenResult 中*/
{
BYTE *p_Erode = NULL;
p_Erode = (BYTE *)malloc(m_dwWidth*m_dwHeight);/*申请中
间结果内存*/
Morph_Erode(p_InputImg ,p_Erode); /*先进行腐蚀操作*/
Morph_Dialate(p_Erode,p_OpenResult); /*再进行膨胀操作*/
free(p_Erode); /*释放中间结果内存*/
}
开 运算一般使对象的轮廓变得光滑,断开狭窄的间断和消除细小 的凸起物。因此,我们常常用开运算来消除小物体,在纤细点处分离 物体。 对图9-8进行尺寸为5×5的矩形开运算,结果如图9-9所示。
由运算结果可以看出,左上方和右下方的细小亮点已经被消除。