邻域平均法

5.4  图像的平滑

图像的平滑方法是一种实用的图像处理技术,能减弱或消除图像中的高频率分量,但不影响低频率分量。因为高频率分量主要对应图像中的区域边缘等灰度值具有较大较快变化的部分,平滑滤波将这些分量滤去可减少局部灰度起伏,使图像变得比较平滑。实际应用中,平滑滤波还可用于消除噪声,或者在提取较大目标前去除过小的细节或将目标内的小间断连接起来。它的主要目的是消除图像采集过程中的图像噪声,在空间域中主要利用邻域平均法、中值滤波法和选择式掩模平滑法等来减少噪声;在频率域内,由于噪声主要存在于频谱的高频段,因此可以利用各种形式的低通滤波器来减少噪声。本节主要介绍几种常用的空间域图像平滑方法。

5.4.1  邻域平均法

1.基础理论

最简单的平滑滤波是将原图中一个像素的灰度值和它周围邻近8个像素的灰度值相加,然后将求得的平均值(除以9)作为新图中该像素的灰度值。它采用模板计算的思想,模板操作实现了一种邻域运算,即某个像素点的结果不仅与本像素灰度有关,而且与其邻域点的像素值有关。模板运算在数学中的描述就是卷积运算,这里不再赘述。邻域平均法也可以用数学公式表达:

设 为给定的含有噪声的图像,经过邻域平均处理后的图像为 ,则 ,M是所取邻域中各邻近像素的坐标, 是邻域中包含的邻近像素的个数。邻域平均法的模板为: ,中间的黑点表示以该像素为中心元素,即该像素是要进行处理的像素。在实际应用中,也可以根据不同的需要选择使用不同的模板尺寸,如3×3、5×5、7×7、9×9等。

邻域平均处理方法是以图像模糊为代价来减小噪声的,且模板尺寸越大,噪声减小的效果越显著。如果 是噪声点,其邻近像素灰度与之相差很大,采用邻域平均法就是用邻近像素的平均值来代替它,这样能明显消弱噪声点,使邻域中灰度接近均匀,起到平滑灰度的作用。因此,邻域平均法具有良好的噪声平滑效果,是最简单的一种平滑方法。

2.算法实现

CImgEnhance类中的成员函数AvgTemplate ()实现图像的邻域平均操作,程序中采用的是3×3的模板,即把当前图像 和它周围8个像素的灰度值相加,然后将求得的平均值(除以9)作为该点的像素值。在对灰度图像进行邻域平均时,直接调用AvgTemplate ()函数即可。以下是AvgTemplate ()函数的代码实现。

 /****************************************
******************************
*
* 函数名称:
*     AvgTemplate(int inputH, int inputW, int
inputX0, int inputY0, float
*
* pTemplate, float fCoef)
*
* 参数:
*     int inputH-模板的高度
*     int inputW-模板的宽度
*     int inputX0-模板的中心元素X坐标
*     int inputY0-模板的中心元素Y坐标
*     float *pTemplate-指向模板数组的指针
*     float f-模板系数
*
* 返回值:
*     void
*
* 说明:
*     该函数用指定的模板(任意大小)来对图像进行操作,
参数inputH指定模板
*     的高度,参数inputW指定模板的宽度,
参数inputX0和iinputY0指定模板的中心
*     元素坐标,参数pTemplate指定模板元素,f指定系数
*
********************************************
**************************/
void CImgEnhance::AvgTemplate(int inputH,
int inputW, int inputX0, int inputY0,
float *pTemplate, float f)
{
unsigned char *pSrc, *pDst;  
int i,j,k,l;
float 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);
}

//行处理(去掉边缘几行)
for (i = inputY0; i < m_imgHeight -
inputH + inputY0 + 1; i++)
{
//列处理(去掉边缘几列)
for (j = inputX0; j < m_imgWidth -
inputW + inputX0 + 1; j++)
{
//指向新DIB第i行第j列的像素的指针
pDst = m_pImgDataOut + lineByte *
(m_imgHeight - 1 - i) + j;

value=0;
//计算
for (k = 0; k < inputH; k++)
{
for (l = 0; l < inputW; l++)
{
pSrc = m_pImgData + lineByte *
(m_imgHeight - 1 - i
+ inputY0 - k) + j - inputX0 + l;
//计算加权平均,保存像素值
value += (*pSrc) * pTemplate[k * inputW + l];
}
}
//乘以系数
value*=f;
//取结果的绝对值
value=(float)fabs(value);
if (value > 255)
{
*pDst = 255; 
}
else
{
*pDst = (unsigned char)(value + 0.5);
}
}
}
}
}

3.函数调用

在视图类CDemoView中映射“均值平滑”事件的处理函数OnAveSmooth()。以下是CDemoView:: OnAveSmooth()函数的代码实现。

void CDemoView::OnAveSmooth() 
{
CDemoDoc *pDoc=GetDocument();
ImgCenterDib *pDib=pDoc->GetPDib();

if(pDib->m_nBitCount!=8&
::MessageBox(0,"只处理灰度图像",MB_OK,0);
return ;
}
AvgDialog *dlg=new AvgDialog();
dlg->DoModal();
int TempH, TempW, TempCX, TempCY;
float fCoef;
float Temp[81];
int i;
//设模板为平均模板
for (i = 0; i < 81; i++)
{
Temp[i]=1.0;
}
switch(dlg->m_nIndex)
{
case 0:
//初始化模板窗口
TempH=3;
TempW=3;
TempCX=1;
TempCY=1;
fCoef=(float)(1.0/9.0);
break;
case 1:
//初始化模板窗口
TempH=5;
TempW=5;
TempCX=2;
TempCY=2;
fCoef=(float)(1.0/25.0);
break;
case 2:
//初始化模板窗口
TempH=9;
TempW=9;
TempCX=4;
TempCY=4;
fCoef=(float)(1.0/81.0);
break;
default:
break;
}
CImgEnhance imgnoise(pDib->GetDimensions
(),pDib->m_nBitCount,
pDib->m_lpColorTable, pDib->m_pImgData);
imgnoise.AvgTemplate(TempH,TempW,
TempCX,TempCY,Temp,fCoef);

CMainFrame* pFrame = (CMainFrame *)
(AfxGetApp()->m_pMainWnd);
pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW);

CDemoView* pView=(CDemoView*)pFrame->
MDIGetActive()->GetActiveView();
CDemoDoc* pDocNew=pView->GetDocument();
ImgCenterDib *dibNew=pDocNew->GetPDib();

dibNew->ReplaceDib(imgnoise.GetDimensions
(),imgnoise.m_nBitCountOut,imgnoise.
m_lpColorTable, imgnoise.m_pImgDataOut);
pDocNew->SetModifiedFlag(TRUE);
pDocNew->UpdateAllViews(pView);

Invalidate();
return;
}

4.实验结果与分析

下面实验是对含有高斯噪声的图像5-3(a)分别利用邻域平均法的不同尺寸模板进行平滑后的实验结果,图5-3(b)、图5-3(c)、图5-3(d)显示的是分别使用了3×3、5×5、9×9模板平滑后的图像。从实验结果可以看出,当所用平滑模板尺寸增大时,对噪声的消除效果也有所增强,但同时会带来图像的模糊,边缘细节逐步减少,且运算量增大。在实际应用中,可以根据不同的应用场合选择合适的模板大小。

 
(点击查看大图)图5-3  不同模板的邻域平均法的平滑结果

你可能感兴趣的:(VC)