设为首页 加入收藏

TOP

5.4.4 中值滤波(1)
2013-10-07 00:25:24 来源: 作者: 【 】 浏览:68
Tags:5.4.4 滤波

5.4.4  中值滤波(1)

1.中值滤波的基础理论

中值滤波是由Tukey首先提出的一种典型的非线性滤波技术。它在一定的条件下可以克服线性滤波器如最小均方滤波、均值滤波等带来的图像细节模糊,而且对滤除脉冲干扰及图像扫描噪声非常有效。由于在实际运算过程中不需要图像的统计特征,因此使用方便。

传统的中值滤波一般采用含有奇数个点的滑动窗口,用窗口中各点灰度值的中值来代替指定点的灰度值。对于奇数个元素,中值是指按大小排序后中间的数值;对于偶数个元素,中值是指排序后中间两个元素灰度值的平均值。中值滤波也是一种典型的低通滤波器,主要用来抑制脉冲噪声,它能够彻底滤除尖波干扰噪声,同时又具有能较好地保护目标图像边缘的特点。

标准一维中值滤波器的定义为:

 
(5-4)


式中, 表示取中值操作。中值滤波的滤波方法是对滑动滤波窗口 内的像素做大小排序,滤波结果的输出像素值规定为该序列的中值。例如取3×3滑动窗口,中值为窗口内第5个最大的像素值。二维中值滤波的窗口形状和尺寸设计对滤波的效果影响较大,不同的图像内容和不同的应用要求,往往采用不同的形状和尺寸。常用的二维中值滤波窗口有线状、方形、圆形、十字形及圆环形等,窗口尺寸一般选为3,也可以根据滤波效果逐渐增大尺寸,直到获得满意的滤波效果。常用的滤波器为N×N中值滤波器、十字形中值滤波器和N×N最大值滤波器,其他类型的滤波器也可以根据此方法来类推。

中值的计算在于对滑动窗口内像素的排序操作。要进行排序,就必须对序列中的数据像素做比较和交换,数据元素之间的比较次数是影响排序速度的一个重要因素。传统的排序串行算法是基于冒泡排序法,若窗口内像素为m个,则每个窗口排序需要做m(m-2)/2次像素的比较操作,时间复杂度为 。此外,常规的滤波算法使窗口每移动一次,就要进行一次排序,这种做法实际上包含了大量重复比较的过程。若一幅图像的大小为 ,则整个计算需要 时间,当窗口较大时计算量很大,较费时。

2.快速并行中值滤波方法的基本理论

为进一步改进中值滤波方法的实现速度,针对3×3中值滤波,介绍一种快速的并行中值滤波方法,通过巧妙设计,避免了大量的重复比较操作,每一窗口排序需要 时间,整个计算需要 时间,易于在硬件处理器上实现并行处理。

快速算法及其实现:为便于说明,将3×3窗口内的各像素分别定义为 ,像素排列如表5-2所示。

表5-2  3×3窗口内像素排列

 

首先对窗口内的每一列分别计算最大值、中值和最小值,这样就得到3组数据,分别为最大值组、中值组和最小值组。计算过程表示如下:

 


公式中max表示取最大值操作,med表示取中值操作,min表示取最小值操作。

由此可以看到,最大值组中的最大值与最小值组中的最小值一定是9个像素中的最大值和最小值。除此,中值组中的最大值至少大于5个像素:本列中的最小值和其他两列中的中值和最小值;中值组中的最小值至少小于5个像素:本列中的最大值和其他两列中的最大值和中值。同样,最大值组中的中值至少大于5个像素,最小值组中的中值至少小于5个像素。即最大值组中的最小值为maxmin,中值组中的中值为medmed,最小值组中的最大值为minmax,则滤波结果的输出像素值winmed应该为maxmin、medmed、minmax中的中值。这一计算过程表示如下:

 

采用该方法,中值的计算仅需做17次比较,与传统算法相比,比较次数减少了近2倍,且该算法十分适用于在实时处理器上做并行处理。

3.算法实现

本算法程序是根据传统的3×3中值滤波方法编写的,采用冒泡排序法查找模板中像素的中值。改进的并行中值滤波方法原理上与传统方法类似,有兴趣的读者可以根据此程序自行编写。CImgEnhance类中的成员函数FindMedianValue()实现计算中值操作,函数MedianFilter()实现中值滤波操作。在对灰度图像进行邻域平均时直接调用MedianFilter()函数即可。以下是FindMedianValue()和MedianFilter()函数的代码实现。

/****************************************
******************************
*
* 函数名称:
*     FindMedianValue(unsigned char*
pTemplate,int templLen)
*
* 参数:
*     unsigned char* pTemplate-指向模板数组指针
*     int templLen-模板数组的长度
*
* 返回值:
*     unsigned char,中位值
*
* 说明:中值滤波中查找模板中像素中值的算法,利用冒泡排序
*    
*
****************************************
******************************/
unsigned char CImgEnhance::FindMedianValue
(unsigned char* pTemplate,int templLen)
{
int i,j;
unsigned char MedianValue;

for(j =0; j<templLen; j++)
{
for(i =0; i <templLen-j-1; i++)
{
if(pTemplate[i]>pTemplate[i+1])
{
MedianValue=pTemplate[i];
pTemplate[i]=pTemplate[i+1];
pTemplate[i+1]=MedianValue;
}

}
}
if ((templLen&1)>0)
{
MedianValue=pTemplate[(templLen+1)/2];
}
else
{
MedianValue=(pTemplate[templLen/2]+
pTemplate[templLen/2+1])/2;
}

return MedianValue;
}
/**************************************
********************************
*
* 函数名称:
*     MedianFilter(int windowH, int
windowW, int wX0, int wY0)
*
* 参数:
*     int windowH-模板窗口的高度       
*     int windowW-模板窗口的宽度
*     int wX0-模板中心元素的X坐标
*     int wY0-模板中心元素的Y坐标
*
* 返回值:
*     void
*
* 说明:中值滤波算法
*    
*
************************************
**********************************/
void CImgEnhance::MedianFilter(int
windowH, int windowW, int wX0, int wY0)
{
unsigned char *pSrc, *pDst;
int  i,j,k,l;
unsigned char* value;         //指向滤波器数组的指针

if(m_pImgDataOut != NULL)
{
delete []m_pImgDataOut;
m_pImgDataOut = NULL;
}
//计算图像每行的字节数
 int lineByte = (m_imgWidth *
m_nBitCount / 8 + 3) / 4 * 4;

if(m_nBitCount != 8)
{
AfxMessageBox("只能处理8位灰度图像!");
return ;
}
//分配内存,以保存新图像
m_nBitCountOut = m_nBitCount;
int lineByteOut = (m_imgWidth *
m_nBitCountOut / 8 + 3) / 4 * 4;
if (!m_pImgDataOut)
{
//为处理后的图像分配内存空间
m_pImgDataOut = new unsigned char
[lineByteOut * m_imgHeight];
}
int pixelByte = m_nBitCountOut / 8;
for(i =  0; i < m_imgHeight; i++){
for(j = 0; j < m_imgWidth * pixelByte; j++)
*(m_pImgDataOut + i * lineByteOut +j) = *
(m_pImgData + i * lineByteOut + j);
}
//暂时分配内存,以保存滤波器数组
value = new unsigned char[windowH * windowW];
for (i = wY0; i < m_imgHeight - windowH + wY0 + 1; i++)
{
for (j = wX0; j < m_imgWidth - windowW + wX0 + 1; j++)
{

pDst = m_pImgDataOut + lineByte *
(m_imgHeight - 1 - i) + j;
for (k = 0; k < windowH; k++)
{
for (l = 0; l < windowW; l++)
{
pSrc = m_pImgData + lineByte * (m_imgHeight - l - i
+ wY0 - k) + j - wX0 + l;
value[k * windowW + l] = *pSrc;
}
}
*pDst = FindMedianValue(value,windowW * windowH);
}
}
}
【责任编辑:夏书 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇5.4.4 中值滤波(2) 下一篇4.2.2 Java类库中的GregorianCale..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: