设为首页 加入收藏

TOP

5.4.3 选择式掩模平滑
2013-10-07 00:23:20 来源: 作者: 【 】 浏览:61
Tags:5.4.3 选择 平滑

5.4.3  选择式掩模平滑

1.基本理论

邻域平均法和加权平均法在消除噪声的同时,都存在平均化带来的缺陷,使尖锐变化的边缘或线条变得模糊。考虑到图像中目标物体和背景一般都具有不同的统计特性,即具有不同的均值和方差,为保留一定的边缘信息,可采用一种自适应的局部平滑滤波方法,这样可以得到较好的图像细节,它的优势是以尽量不模糊边缘轮廓为目的。

选择式掩模平滑法也是以模板运算为基础的,这里取5×5的模板窗口。在窗口内以中心像素 为基准点,制作4个五边形、4个六边形、一个边长为3的正方形共9种形状的屏蔽窗口,分别计算每个窗口内的平均值及方差。由于含有尖锐边沿的区域,方差必定较平缓区域大,因此采用方差最小的屏蔽窗口进行平均化,这种方法在完成滤波操作的同时,又不破坏区域边界的细节。这种采用9种形状的屏蔽窗口,分别计算各窗口内的灰度值方差,并采用方差最小的屏蔽窗口进行平均化方法,也叫做自适应局部平滑方法。如图5-5所示为9种屏蔽窗口的模板。

 
(点击查看大图)图5-5  9种屏蔽窗口的模板

根据上面9种模板分别计算各模板作用下的均值及方差。

均值的计算公式为:

方差的计算公式为:


式中,N为各掩模对应的像素个数。

将计算得到的 进行排序,最小方差 所对应的掩模的灰度级均值 作为平滑的结果输出。将5×5的窗口在整个图像上滑动,利用上述方法就能实现对每个像素的平滑。

2.算法实现

CImgEnhance类中的成员函数ChooseMask()实现图像的选择式掩模平滑操作,程序中采用9个掩模的均值及方差来选择屏蔽窗口进行平滑。在对灰度图像进行邻域平均时直接调用ChooseMask()函数即可。以下是ChooseMask()函数的代码实现。

/*************************************
*********************************
*
* 函数名称:
*     ChooseMask
*
* 参数:
*     void
*
* 返回值:
*     void
*
* 说明:用9个掩模的均值及方差来选择屏蔽窗口进行平滑
*    
***********************************
***********************************/
void CImgEnhance::ChooseMask()
{
if(m_nBitCount!=8)
{
AfxMessageBox("只能处理8位灰度图像!");
return ;
}
int n,ji[9],nmin;
float mean[9],bunsan[9],bmin;

if(m_pImgDataOut!=NULL)
{
delete []m_pImgDataOut;
m_pImgDataOut=NULL;
}
 //创建要复制的图像区域
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];
}

memset(m_pImgDataOut,255,lineByteOut
* m_imgHeight);
for(int j=2;j<=m_imgHeight-3;j++)
for(int i=2;i<=m_imgWidth-3;i++)
{
//求9种近邻区域的均值及其方差
//第1近邻区域
ji[0]=m_pImgData[(j-1)*lineByteOut+(i-1)];
ji[1]=m_pImgData[(j-1)*lineByteOut+i];
ji[2]=m_pImgData[(j-1)*lineByteOut+(i+1)];
ji[3]=m_pImgData[j*lineByteOut+(i-1)];
ji[4]=m_pImgData[j*lineByteOut+i];
ji[5]=m_pImgData[j*lineByteOut+(i+1)];
ji[6]=m_pImgData[(j+1)*lineByteOut+(i-1)];
ji[7]=m_pImgData[(j+1)*lineByteOut+i];
ji[8]=m_pImgData[(j+1)*lineByteOut+(i+1)];
mean[0]=(float)(ji[0]+ji[1]+ji[2]+ji[3]+ji
[4]+ji[5]+ji[6]+ ji[7]+ji[8])/9;
bunsan[0]=0;
for(n=0;n<=8;n++)
bunsan[0]+=ji[n]*ji[n]-mean[0]*mean[0];
//第2近邻区域
ji[0]=m_pImgData[(j-2)*lineByteOut+(i-1)];
ji[1]=m_pImgData[(j-2)*lineByteOut+i];
ji[2]=m_pImgData[(j-2)*lineByteOut+(i+1)];
ji[3]=m_pImgData[(j-1)*lineByteOut+(i-1)];
ji[4]=m_pImgData[(j-1)*lineByteOut+i];
ji[5]=m_pImgData[(j-1)*lineByteOut+(i+1)];
ji[6]=m_pImgData[j*lineByteOut+i];
mean[1]=(float)(ji[0]+ji[1]+ji[2]+ji[3]
+ji[4]+ji[5]+ji[6])/7;
bunsan[1]=0;
for(n=0;n<=6;n++)
bunsan[1]+=ji[n]*ji[n]-mean[1]*mean[1];
//第3近邻区域
ji[0]=m_pImgData[(j-1)*lineByteOut+(i-2)];
ji[1]=m_pImgData[(j-1)*lineByteOut+(i-1)];
ji[2]=m_pImgData[j*lineByteOut+(i-2)];
ji[3]=m_pImgData[j*lineByteOut+(i-1)];
ji[4]=m_pImgData[j*lineByteOut+i];
ji[5]=m_pImgData[(j+1)*lineByteOut+(i-2)];
ji[6]=m_pImgData[(j+1)*lineByteOut+(i-1)];
mean[2]=(float)(ji[0]+ji[1]+ji[2]+ji[3]
+ji[4]+ji[5]+ji[6])/7;
bunsan[2]=0;
for(n=0;n<=6;n++)
bunsan[2]+=ji[n]*ji[n]-mean[2]*mean[2];
//第4近邻区域
ji[0]=m_pImgData[j*lineByteOut+i];
ji[1]=m_pImgData[(j+1)*lineByteOut+(i-1)];
ji[2]=m_pImgData[(j+1)*lineByteOut+i];
ji[3]=m_pImgData[(j+1)*lineByteOut+(i+1)];
ji[4]=m_pImgData[(j+2)*lineByteOut+(i-1)];
ji[5]=m_pImgData[(j+2)*lineByteOut+i];
ji[6]=m_pImgData[(j+2)*lineByteOut+(i+1)];
mean[3]=(float)(ji[0]+ji[1]+ji[2]+ji[3]
+ji[4]+ji[5]+ji[6])/7;
bunsan[3]=0;
for(n=0;n<=6;n++)
bunsan[3]+=ji[n]*ji[n]-mean[3]*mean[3];
//第5近邻区域
ji[0]=m_pImgData[(j-1)*lineByteOut+(i+1)];
ji[1]=m_pImgData[(j-1)*lineByteOut+(i+2)];
ji[2]=m_pImgData[j*lineByteOut+i];
ji[3]=m_pImgData[j*lineByteOut+(i+1)];
ji[4]=m_pImgData[j*lineByteOut+(i+2)];
ji[5]=m_pImgData[(j+1)*lineByteOut+(i+1)];
ji[6]=m_pImgData[(j+1)*lineByteOut+(i+2)];
mean[4]=(float)(ji[0]+ji[1]+ji[2]+ji
[3]+ji[4]+ji[5]+ji[6])/7;
bunsan[4]=0;
for(n=0;n<=6;n++)
bunsan[4]+=ji[n]*ji[n]-mean[4]*mean[4]; 
//第6近邻区域
ji[0]=m_pImgData[(j-2)*lineByteOut+(i+1)];
ji[1]=m_pImgData[(j-2)*lineByteOut+(i+2)];
ji[2]=m_pImgData[(j-1)*lineByteOut+i];
ji[3]=m_pImgData[(j-1)*lineByteOut+(i+1)];
ji[4]=m_pImgData[(j-1)*lineByteOut+(i+2)];
ji[5]=m_pImgData[j*lineByteOut+i];
ji[6]=m_pImgData[j*lineByteOut+(i+1)];
mean[5]=(float)(ji[0]+ji[1]+ji[2]+ji
[3]+ji[4]+ji[5]+ji[6])/7;
bunsan[5]=0;
for(n=0;n<=6;n++)
bunsan[5]+=ji[n]*ji[n]-mean[5]*mean[5];
//第7近邻区域
ji[0]=m_pImgData[(j-2)*lineByteOut+(i-2)];
ji[1]=m_pImgData[(j-2)*lineByteOut+(i-1)];
ji[2]=m_pImgData[(j-1)*lineByteOut+(i-2)];
ji[3]=m_pImgData[(j-1)*lineByteOut+(i-1)];
ji[4]=m_pImgData[(j-1)*lineByteOut+i];
ji[5]=m_pImgData[j*lineByteOut+(i-1)];
ji[6]=m_pImgData[j*lineByteOut+i];
mean[6]=(float)(ji[0]+ji[1]+ji[2]+ji
[3]+ji[4]+ji[5]+ji[6])/7;
bunsan[6]=0;
for(n=0;n<=6;n++)
bunsan[6]+=ji[n]*ji[n]-mean[6]*mean[6];
//第8近邻区域
ji[0]=m_pImgData[j*lineByteOut+(i-1)];
ji[1]=m_pImgData[j*lineByteOut+i];
ji[2]=m_pImgData[(j+1)*lineByteOut+(i-2)];
ji[3]=m_pImgData[(j+1)*lineByteOut+(i-1)];
ji[4]=m_pImgData[(j+1)*lineByteOut+i];
ji[5]=m_pImgData[(j+2)*lineByteOut+(i-2)];
ji[6]=m_pImgData[(j+2)*lineByteOut+(i-1)];
mean[7]=(float)(ji[0]+ji[1]+ji[2]+ji
[3]+ji[4]+ji[5]+ji[6])/7;
bunsan[7]=0;
for(n=0;n<=6;n++)
bunsan[7]+=ji[n]*ji[n]-mean[7]*mean[7];
//第9近邻区域
ji[0]=m_pImgData[j*lineByteOut+i];
ji[1]=m_pImgData[j*lineByteOut+(i+1)];
ji[2]=m_pImgData[(j+1)*lineByteOut+i];
ji[3]=m_pImgData[(j+1)*lineByteOut+(i+1)];
ji[4]=m_pImgData[(j+1)*lineByteOut+(i+2)];
ji[5]=m_pImgData[(j+2)*lineByteOut+(i+1)];
ji[6]=m_pImgData[(j+2)*lineByteOut+(i+2)];
mean[8]=(float)(ji[0]+ji[1]+ji[2]+ji
[3]+ji[4]+ji[5]+ji[6])/7;
bunsan[8]=0;
for(n=0;n<=6;n++)
bunsan[8]+=ji[n]*ji[n]-mean[8]*mean[8];
//求方差最小的近邻区域nmin
bmin=bunsan[0];
nmin=0;
for(n=0;n<=8;n++)
{
if(bmin>bunsan[n])
{
bmin=bunsan[n];
nmin=n;
}
//把nmin的值四舍五入后作为显示图像的值
m_pImgDataOut[j*lineByteOut+i]=
(int)(mean[nmin]+0.5);
}    
}
}

3.函数调用

在视图类CDemoView中映射“选择式掩模平滑”事件的处理函数OnChooseMask()。以下是CDemoView::OnChooseMask()函数的代码实现。

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

if(pDib->m_nBitCount!=8){
::MessageBox(0,"只处理灰度图像",MB_OK,0);
return ;
}

CImgEnhance imgSmooth(pDib->GetDimensions(),
pDib->m_nBitCount,
pDib->m_lpColorTable, pDib->m_pImgData);
imgSmooth.ChooseMask();

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(imgSmooth.GetDimensions
(),imgSmooth.m_nBitCountOut,imgSmooth.
m_lpColorTable, imgSmooth.m_pImgDataOut);
pDocNew->SetModifiedFlag(TRUE);
pDocNew->UpdateAllViews(pView);

Invalidate();
}

4.实验结果与分析

图5-6显示的是分别利用邻域平均法、加权平均法和选择式掩模法3种平滑方法对同一幅图像进行平滑的实验结果对比。由图5-6可以看出,邻域平均法虽然能够消除部分噪声干扰,但对图像的模糊效应非常明显;加权平均法通过改变距离掩模中心像素的权值,能够相对减少其他像素对图像平滑的影响,从而降低图像的模糊效应;选择式掩模平滑根据物体与背景的不同统计特性,选择方差最小的屏蔽窗口进行平均化处理,这样在完成滤波操作的同时又能较好地保留图像的边缘细节信息,尽量避免了边缘轮廓的模糊现象,比前两种方法具有更好的滤波效果。

 
(点击查看大图)图5-6  3种平滑方法的平滑效果对比
【责任编辑:夏书 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇5.2.3 编程实现信噪比的计算 下一篇5.1.1 图像增强类的定义

评论

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