鄰域平均法和加權平均法在消除噪聲的同時,都不可避免地帶來平均化的缺憾,致使尖銳變化的邊緣或線條變得模糊。考慮圖像中目標物體和背景一般都具有不同的統計特性,即不同的均值和方差,為保留一定的邊緣信息,可采用選擇式掩膜平滑濾波,這樣可以得到較好的圖像細節。這種方法以盡量不模糊邊緣輪廓為目的。
1.基本原理
選擇式掩膜平滑方法取5×5的模板窗口,以中心像素為基准點,制作4個五邊形、4個六邊形、一個邊長為3的正方形共9個形狀的屏幕窗口,分別計算每個窗口內的平均值及方差。由於含有尖銳邊緣的區域,方差必定比平緩區域大,因此采用方差最小的屏蔽窗口進行平均化。這種方法在完成濾波操作的同時,又不破壞區域邊界的細節。這種采用9種形狀的屏蔽窗口,分別計算各窗口內的灰度值方差,並采用方差最小的屏蔽窗口進行平均化的方法,也稱為自適應平滑方法。下圖為9種屏蔽窗口的模板
均值的計算公式為:
計算方差的公式為:
式中,k=1,2,3,4·····,N N為各模板對應的像素個數。
算法實現:

1 void CImgEnhance::ChooseMask() 2 { 3 if(m_nBitCount!=8) 4 { 5 AfxMessageBox("只能處理8位灰度圖像!"); 6 return ; 7 } 8 int n,pixel[9],nmin; 9 float mean[9],var[9],bmin; 10 11 if(m_pImgDataOut!=NULL) 12 { 13 delete []m_pImgDataOut; 14 m_pImgDataOut=NULL; 15 } 16 //創建要復制的圖像區域 17 m_nBitCountOut=m_nBitCount; 18 int lineByteOut=(m_imgWidth*m_nBitCountOut/8+3)/4*4; 19 if (!m_pImgDataOut) 20 { 21 m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeight]; 22 } 23 24 memset(m_pImgDataOut,255,lineByteOut * m_imgHeight); 25 for(int j=2;j<=m_imgHeight-3;j++) 26 for(int i=2;i<=m_imgWidth-3;i++) 27 { 28 //求9種近鄰區域的均值及其方差 29 //第1近鄰區域 30 pixel[0]=m_pImgData[(j-1)*lineByteOut+(i-1)]; 31 pixel[1]=m_pImgData[(j-1)*lineByteOut+i]; 32 pixel[2]=m_pImgData[(j-1)*lineByteOut+(i+1)]; 33 pixel[3]=m_pImgData[j*lineByteOut+(i-1)]; 34 pixel[4]=m_pImgData[j*lineByteOut+i]; 35 pixel[5]=m_pImgData[j*lineByteOut+(i+1)]; 36 pixel[6]=m_pImgData[(j+1)*lineByteOut+(i-1)]; 37 pixel[7]=m_pImgData[(j+1)*lineByteOut+i]; 38 pixel[8]=m_pImgData[(j+1)*lineByteOut+(i+1)]; 39 mean[0]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6]+pixel[7]+pixel[8])/9; 40 var[0]=0; 41 for(n=0;n<=8;n++) 42 var[0]+=pixel[n]*pixel[n]-mean[0]*mean[0]; 43 //第2近鄰區域 44 pixel[0]=m_pImgData[(j-2)*lineByteOut+(i-1)]; 45 pixel[1]=m_pImgData[(j-2)*lineByteOut+i]; 46 pixel[2]=m_pImgData[(j-2)*lineByteOut+(i+1)]; 47 pixel[3]=m_pImgData[(j-1)*lineByteOut+(i-1)]; 48 pixel[4]=m_pImgData[(j-1)*lineByteOut+i]; 49 pixel[5]=m_pImgData[(j-1)*lineByteOut+(i+1)]; 50 pixel[6]=m_pImgData[j*lineByteOut+i]; 51 mean[1]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 52 var[1]=0; 53 for(n=0;n<=6;n++) 54 var[1]+=pixel[n]*pixel[n]-mean[1]*mean[1]; 55 //第3近鄰區域 56 pixel[0]=m_pImgData[(j-1)*lineByteOut+(i-2)]; 57 pixel[1]=m_pImgData[(j-1)*lineByteOut+(i-1)]; 58 pixel[2]=m_pImgData[j*lineByteOut+(i-2)]; 59 pixel[3]=m_pImgData[j*lineByteOut+(i-1)]; 60 pixel[4]=m_pImgData[j*lineByteOut+i]; 61 pixel[5]=m_pImgData[(j+1)*lineByteOut+(i-2)]; 62 pixel[6]=m_pImgData[(j+1)*lineByteOut+(i-1)]; 63 mean[2]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 64 var[2]=0; 65 for(n=0;n<=6;n++) 66 var[2]+=pixel[n]*pixel[n]-mean[2]*mean[2]; 67 //第4近鄰區域 68 pixel[0]=m_pImgData[j*lineByteOut+i]; 69 pixel[1]=m_pImgData[(j+1)*lineByteOut+(i-1)]; 70 pixel[2]=m_pImgData[(j+1)*lineByteOut+i]; 71 pixel[3]=m_pImgData[(j+1)*lineByteOut+(i+1)]; 72 pixel[4]=m_pImgData[(j+2)*lineByteOut+(i-1)]; 73 pixel[5]=m_pImgData[(j+2)*lineByteOut+i]; 74 pixel[6]=m_pImgData[(j+2)*lineByteOut+(i+1)]; 75 mean[3]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 76 var[3]=0; 77 for(n=0;n<=6;n++) 78 var[3]+=pixel[n]*pixel[n]-mean[3]*mean[3]; 79 //第5近鄰區域 80 pixel[0]=m_pImgData[(j-1)*lineByteOut+(i+1)]; 81 pixel[1]=m_pImgData[(j-1)*lineByteOut+(i+2)]; 82 pixel[2]=m_pImgData[j*lineByteOut+i]; 83 pixel[3]=m_pImgData[j*lineByteOut+(i+1)]; 84 pixel[4]=m_pImgData[j*lineByteOut+(i+2)]; 85 pixel[5]=m_pImgData[(j+1)*lineByteOut+(i+1)]; 86 pixel[6]=m_pImgData[(j+1)*lineByteOut+(i+2)]; 87 mean[4]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 88 var[4]=0; 89 for(n=0;n<=6;n++) 90 var[4]+=pixel[n]*pixel[n]-mean[4]*mean[4]; 91 //第6近鄰區域 92 pixel[0]=m_pImgData[(j-2)*lineByteOut+(i+1)]; 93 pixel[1]=m_pImgData[(j-2)*lineByteOut+(i+2)]; 94 pixel[2]=m_pImgData[(j-1)*lineByteOut+i]; 95 pixel[3]=m_pImgData[(j-1)*lineByteOut+(i+1)]; 96 pixel[4]=m_pImgData[(j-1)*lineByteOut+(i+2)]; 97 pixel[5]=m_pImgData[j*lineByteOut+i]; 98 pixel[6]=m_pImgData[j*lineByteOut+(i+1)]; 99 mean[5]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 100 var[5]=0; 101 for(n=0;n<=6;n++) 102 var[5]+=pixel[n]*pixel[n]-mean[5]*mean[5]; 103 //第7近鄰區域 104 pixel[0]=m_pImgData[(j-2)*lineByteOut+(i-2)]; 105 pixel[1]=m_pImgData[(j-2)*lineByteOut+(i-1)]; 106 pixel[2]=m_pImgData[(j-1)*lineByteOut+(i-2)]; 107 pixel[3]=m_pImgData[(j-1)*lineByteOut+(i-1)]; 108 pixel[4]=m_pImgData[(j-1)*lineByteOut+i]; 109 pixel[5]=m_pImgData[j*lineByteOut+(i-1)]; 110 pixel[6]=m_pImgData[j*lineByteOut+i]; 111 mean[6]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 112 var[6]=0; 113 for(n=0;n<=6;n++) 114 var[6]+=pixel[n]*pixel[n]-mean[6]*mean[6]; 115 //第8近鄰區域 116 pixel[0]=m_pImgData[j*lineByteOut+(i-1)]; 117 pixel[1]=m_pImgData[j*lineByteOut+i]; 118 pixel[2]=m_pImgData[(j+1)*lineByteOut+(i-2)]; 119 pixel[3]=m_pImgData[(j+1)*lineByteOut+(i-1)]; 120 pixel[4]=m_pImgData[(j+1)*lineByteOut+i]; 121 pixel[5]=m_pImgData[(j+2)*lineByteOut+(i-2)]; 122 pixel[6]=m_pImgData[(j+2)*lineByteOut+(i-1)]; 123 mean[7]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 124 var[7]=0; 125 for(n=0;n<=6;n++) 126 var[7]+=pixel[n]*pixel[n]-mean[7]*mean[7]; 127 //第9近鄰區域 128 pixel[0]=m_pImgData[j*lineByteOut+i]; 129 pixel[1]=m_pImgData[j*lineByteOut+(i+1)]; 130 pixel[2]=m_pImgData[(j+1)*lineByteOut+i]; 131 pixel[3]=m_pImgData[(j+1)*lineByteOut+(i+1)]; 132 pixel[4]=m_pImgData[(j+1)*lineByteOut+(i+2)]; 133 pixel[5]=m_pImgData[(j+2)*lineByteOut+(i+1)]; 134 pixel[6]=m_pImgData[(j+2)*lineByteOut+(i+2)]; 135 mean[8]=(float)(pixel[0]+pixel[1]+pixel[2]+pixel[3]+pixel[4]+pixel[5]+pixel[6])/7; 136 var[8]=0; 137 for(n=0;n<=6;n++) 138 var[8]+=pixel[n]*pixel[n]-mean[8]*mean[8]; 139 //求方差最小的近鄰區域nmin 140 bmin=var[0]; 141 nmin=0; 142 for(n=0;n<=8;n++) 143 { 144 if(bmin>var[n]) 145 { 146 bmin=var[n]; 147 nmin=n; 148 } 149 //把nmin的值四舍五入后作為顯示圖像的值 150 m_pImgDataOut[j*lineByteOut+i]=(int)(mean[nmin]+0.5); 151 } 152 } 153 }