1. 椒鹽噪聲(Salt And Pepper Noise)
椒鹽噪聲是一種因為信號脈沖強度引起的噪聲,信噪比(Signal NoiseRate)是衡量圖像噪聲的一個數字指標。
給一副數字圖像加上椒鹽噪聲的處理順序應該如下:
- 指定信噪比 SNR 其取值范圍在[0, 1]之間
- 計算總像素數目 SP,得到要加噪的像素數目 NP = SP * (1-SNR)
- 隨機獲取要加噪的每個像素位置P(i, j)
- 指定像素值為255或者0。
- 重復c, d兩個步驟完成所有像素的NP個像素
- 輸出加噪以后的圖像
int noise_num=(int)height*width*SNR/2; for(int i=0; i<noise_num; i++) { int row = (int)(rand()%height); int col = (int)(rand()%width); for(int j=0;j<nChannels;j++) { des[row * width* nChannels + col* nChannels+j]= 255; } } for(int i=0; i<noise_num; i++) { int row = (int)(rand()%height); int col = (int)(rand()%width); for(int j=0;j<nChannels;j++) { des[row * width* nChannels + col* nChannels+j]=0; } }
2. 高斯噪聲(Gaussian Noise)
高斯噪聲的密度取決於公式G(x, sigma) 其中X是代表平均值,sigma代表的標准方差,每個輸入像素 Pin,
一個正常的高斯采樣分布公式G(d), 得到輸出像素Pout.
Pout = Pin + XMeans + sigma *G(d)
其中d為一個線性的隨機數,G(d)是隨機數的高斯分布隨機值。
給一副數字圖像加上高斯噪聲的處理順序如下:
a. 輸入參數sigam 和 X mean
b. 以系統時間為種子產生一個偽隨機數
c. 將偽隨機數帶入G(d)得到高斯隨機數
d. 根據輸入像素計算出輸出像素
e. 重新將像素值防縮在[0 ~ 255]之間
f. 循環所有像素
g. 輸出圖像
采用了由Marsaglia和Bray在1964年提出的常用成熟的生成高斯分布隨機數序列的方法
double gaussrand(int M,int D) { static double V1, V2, S; static int phase = 0; double X; if ( phase == 0 ) { do { double U1 = (double)rand() / RAND_MAX; double U2 = (double)rand() / RAND_MAX; V1 = 2 * U1 - 1; V2 = 2 * U2 - 1; S = V1 * V1 + V2 * V2; } while(S >= 1 || S == 0) X = V1 * sqrt(-2 * log(S) / S); } else X = V2 * sqrt(-2 * log(S) / S); phase = 1 - phase; X=X*D+M; return(X); }
3.均勻噪聲
采用了經典的均勻噪聲序列生成:
double randomUniform(double dMinValue,double dMaxValue) { double pRandomValue = (double)(rand()/(double)RAND_MAX); pRandomValue = pRandomValue*(dMaxValue-dMinValue)+dMinValue; return pRandomValue; }
二、濾波器的原理與實現
1.修正的阿爾法均值濾波器
假設在領域內去掉g(s,t)最低灰度值的d/2和最高灰度值的d/2。令
代表剩下的mn-d個像素。由剩余這些像素的平均值形成的濾波器成為修正的阿爾法均值濾波器:
下面是核心的算法:
//Alpha trimmed mean filter void Alphatrimmedmeanfilter(unsigned char* des, const unsigned char* src, int width, int height, int nChannels) { // TODO: Add your command handler code here //processing int len=9; //定義模板大小為3*3 double* or=new double[len]; //將模板中強度記錄成序列待排序 int d=4; //定義d值 //將uint8型轉換為double型 //filtering for(int x=2;x<width-2;x++) for(int y=2;y<height-2;y++) for(int n=0;n<nChannels;n++) { or[0]=src[(y-1)*width*nChannels+(x-1)*nChannels + n]; or[1]=src[(y-1)*width*nChannels+x*nChannels + n]; or[2]=src[(y-1)*width*nChannels+(x+1)*nChannels + n]; or[3]=src[y*width*nChannels+(x-1)*nChannels + n]; or[4]=src[y*width*nChannels+x*nChannels + n]; or[5]=src[y*width*nChannels+(x+1)*nChannels + n]; or[6]=src[(y+1)*width*nChannels+(x-1)*nChannels + n]; or[7]=src[(y+1)*width*nChannels+x*nChannels + n]; or[8]=src[(y+1)*width*nChannels+(x+1)*nChannels + n]; orderN(or,9); //從小到大排序 double sum=0; //記錄剩余強度之和 for(int k=d/2;k<9-d/2;k++) { sum=sum+or[k]; } sum=sum/(9-d); des[y*width*nChannels+x*nChannels + n]=int(sum); } }
2.自適應中值濾波:
自適應中值濾波器的濾波方式和傳統的中值濾波器一樣,都使用一個矩形區域的窗口Sxy ,不同的是在濾波過程中,自適應濾波器會根據一定的設定條件改變,即增加濾窗的大小,同時當判斷濾窗中心的像素是噪聲時,該值用中值代替,否則不改變其當前像素值,這樣用濾波器的輸出來替代像素(x,y) 處(即目前濾窗中心的坐標的值。我們做如下定義:
Zmin是在Sxy濾窗內灰度的最小值;
Zmax是在Sxy濾窗內灰度的最大值;
Zmed是在Sxy濾窗內灰度的中值;
Zxy是坐標(x,y) 處的灰度值;
Smax指定Sxy所允許的最大值。
自適應中值濾波算法由兩個部分組成,稱為第一層(Level A) 和第二層(Level B) 。 主要算法如下:
Level A : A1 = Zmed - Zmin A2 = Zmed - Zmax
如果A1> 0 並且A2<0 ,轉到level B ,否則增加濾窗Sxy的尺寸。 如果濾窗Sxy≤Smax ,則重復執行Level A ,否則把Zxy作為輸出值。
Level B : B1 = Zxy - Zmin B2 = Zxy - Zmax
如果B1>0 並且B2<0 , 把Zxy作為輸出值, 否則把Zmed作為輸出值。
算法如下:
void Adaptivemedianfilter(unsigned char* des, const unsigned char* src, int width, int height, int nChannels) { // TODO: Add your command handler code here int s=5; //定義最大矩形框大小 int k=0; k=(s-1)/2; //filtering double medtemp=0; double maxtemp=0; double mintemp=0; double pxytemp=0; //定義濾波過程中的臨時變量 for(int i=2;i<width-2;i++) for(int j=2;j<height-2;j++) //逐點掃描 for(int n=0;n<nChannels;n++) { int len=3; while(len<=s) { double* or=new double[len*len]; //動態分配一維序列存放 int len2=0; len2=(len-1)/2; for(int x=0;x<len;x++) //將矩形框中的數據讀入or進行排序 for(int y=0;y<len;y++) { or[x*len+y]=src[(i-len2+x)*nChannels+(j-len2+y)*nChannels*width+n]; } orderN(or,len*len); medtemp=or[(len*len-1)/2]; maxtemp=or[len*len-1]; mintemp=or[0]; pxytemp=src[i*nChannels+j*nChannels*width+n]; if((maxtemp>medtemp)&(mintemp<medtemp)) { if((maxtemp>pxytemp)&(mintemp<pxytemp)) { des[i*nChannels+j*nChannels*width+n]=int(pxytemp); } else { des[i*nChannels+j*nChannels*width+n]=int(medtemp); } break; } else { len=len+2; } delete []or; } if(len>s) { des[i*nChannels+j*nChannels*width+n]=int(medtemp); } } }
三、結果分析:
1.15%的均勻噪聲和10%的椒鹽噪聲及對其進行修正的阿爾法濾波(d=4,mn=9)后的結果:
通過實驗,發現d的取值對結果影響比較大,在d=4是取得比較好的結果,但可以看出依然有一些噪聲點。
2.25%的椒鹽噪聲及對其自適應中值濾波后的結果:
可以看到自適應中值濾波對於椒鹽噪聲可以說具有非常漂亮的濾波效果,基本上看不出和原圖像的區別。但是細心觀察可以發現處理后的圖像景物的邊緣相對原圖像比較模糊。
3.20%的均值為0,方差900的高斯噪聲及其維納濾波后的效果: