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】