灰度圖像--圖像增強 平滑之均值濾波、高斯濾波
???????
目錄(?)[+]
開篇廢話均值濾波 數學效果代碼 高斯濾波 數學效果代碼 總結
學習DIP第30天
轉載請標明本文出處:http://blog.csdn.net/tonyshengtan,歡迎大家轉載,發現博客被某些論壇轉載后,圖像無法正常顯示,無法正常表達本人觀點,對此表示很不滿意。有些網站轉載了我的博文,很開心的是自己寫的東西被更多人看到了,但不開心的是這段話被去掉了,也沒標明轉載來源,雖然這并沒有版權保護,但感覺還是不太好,出于尊重文章作者的勞動,轉載請標明出處!!!!
文章代碼已托管,歡迎共同開發:https://github.com/Tony-Tan/DIPpro
開篇廢話
? ? 今天的廢話是,我早上來了開始寫博客,寫了大概和下文差不多的內容,寫了很多,就在發表以后,我震驚了,博客是空的,沒有內容,我就表示呵呵了,不知道是網速的問題還是CSDN的問題,總之,我就不說啥了。
? ? 今天的內容是是平滑,先介紹均值和高斯平滑,高斯平滑是均值平滑的一個擴展,或者是一個進化版本。均值的原理是,一個規定的鄰域內,所有像素的平局值作為最終計算的結果,每個像素的權值相同,為總像素的倒數,而高斯平滑是上述的升級版本,鄰域內每個像素的權值不同,而權值是由高斯函數確定的。
? ? 均值平滑和高斯平滑都是線性的,也就是,一旦參數給定,模板就確定下來,不會因為位置和像素分布不同而改變,而線性模板的基本運算是卷積。
? ? 線性模板的另一個性質就是可以進行頻域分析,比如高斯平滑的頻域仍然是高斯的,而且是低通的,這與前面講到的平滑是消除尖銳的噪聲(高頻)的操作相互證明了其正確性,均值平滑是一個盒狀濾波器,其頻域為sinc函數,也是一個近似的低通,但sinc函數有旁瓣,所以,模板寬度選擇不好可能會有一些不好的效果,比如有些高頻會被保留,這一點也比較好理解。
? ? 比較下兩種均值(加權和不加權)。比如一維的一個序列{0,0,0,0,0,1000,0,0,0,0},明顯1000是個邊緣,如果使用3個寬度的均值平滑,結果是{0,0,0,0,333,333,333,0,0,0},邊緣被完全模糊掉了。但如果使用{1,2,1}的近似高斯平滑模板,結果是{0,0,0,0,250,500,250,0,0,0},邊緣被保留。所以,加權平均(高斯)可以保留一定的細節。
? ? 對于設計的線型濾波器,其效果可以先是由傅里葉變換,到頻域進行觀察,便可大致推測出其效果,測試圖片(灰度輸入):
均值濾波
數學
? ? 基本數學原理公式,以3x3為例: ? ? 得到濾波模板: ? ? ?應用于圖像的計算公式: ? ? ?上式中的w(s,t)恒等于1。 效果
? ? ?觀察下用3x3,5x5和7x7的均值模板與圖像卷積的結果: 3x3模板:
5x5模板:
7x7模板:
? ? 可以得出結論,均值濾波的模板越大,圖像越模糊。 代碼
[cpp] view plaincopyprint?
void?MeanMask(double?*mask,int?width,int?height){??????double?w=width;??????double?h=height;??????double?meanvalue=1.0/(w*h);??????for(int?i=0;i<width*height;i++)??????????mask[i]=meanvalue;??????????}??void?MeanFilter(IplImage?*src,IplImage?*dst,int?width,int?height){??????double?*?pixarry=(double?*)malloc(sizeof(double)*src->width*src->height);??????double?*?dstarry=(double?*)malloc(sizeof(double)*src->width*src->height);??????double?*?mask=(double?*)malloc(sizeof(double)*width*height);??????for(int?j=0;j<src->height;j++){??????????for(int?i=0;i<src->width;i++){??????????????pixarry[j*src->width+i]=cvGetReal2D(src,?j,?i);??????????}??????}??????MeanMask(mask,?width,?height);??????RealRelevant(pixarry,dstarry,mask,src->width,src->height,width,height);??????for(int?j=0;j<src->height;j++){??????????for(int?i=0;i<src->width;i++){??????????????cvSetReal2D(?dst,j,i,dstarry[j*src->width+i]);??????????}??????}??????free(pixarry);??????free(dstarry);??????free(mask);??}?? void MeanMask(double *mask,int width,int height){double w=width;double h=height;double meanvalue=1.0/(w*h);for(int i=0;i<width*height;i++)mask[i]=meanvalue;}
void MeanFilter(IplImage *src,IplImage *dst,int width,int height){double * pixarry=(double *)malloc(sizeof(double)*src->width*src->height);double * dstarry=(double *)malloc(sizeof(double)*src->width*src->height);double * mask=(double *)malloc(sizeof(double)*width*height);for(int j=0;j<src->height;j++){for(int i=0;i<src->width;i++){pixarry[j*src->width+i]=cvGetReal2D(src, j, i);}}MeanMask(mask, width, height);RealRelevant(pixarry,dstarry,mask,src->width,src->height,width,height);for(int j=0;j<src->height;j++){for(int i=0;i<src->width;i++){cvSetReal2D( dst,j,i,dstarry[j*src->width+i]);}}free(pixarry);free(dstarry);free(mask);
}
? ? 這個代碼并不是最快速的,只是為了和高斯平滑相互保持一致。所以,如果要使用,需要先優化。 高斯濾波
? ? 高斯平滑,就是一種加權的均值,權值由高斯函數確定。 數學
? ? 高斯函數: ? ? 在三維中的形狀如下:
生成上圖的matlab代碼: [python] view plaincopyprint?
%?公式:?p(z)?=?exp(-(z-u)^2/(2*d^2)/(sqrt(2*pi)*d)??X?=?0?:?1?:?100;??Y?=?0?:?1:?100;????%?方差??d=?49;??Z?=?zeros(101,?101);??for?row?=?1?:?1?:?101??????for?col?=?1?:?1?:?101??????????Z(row,?col)?=?(X(row)?-?50)?.*?(X(row)-50)?+?(Y(col)?-?50)?.*?(Y(col)?-?50);??????end??end??Z?=?-Z/(2*d);??Z?=?exp(Z)?/?(sqrt(2*pi)?*?sqrt(d));??surf(X,?Y,?Z);?? % 公式: p(z) = exp(-(z-u)^2/(2*d^2)/(sqrt(2*pi)*d)
X = 0 : 1 : 100;
Y = 0 : 1: 100;% 方差
d= 49;
Z = zeros(101, 101);
for row = 1 : 1 : 101for col = 1 : 1 : 101Z(row, col) = (X(row) - 50) .* (X(row)-50) + (Y(col) - 50) .* (Y(col) - 50);end
end
Z = -Z/(2*d);
Z = exp(Z) / (sqrt(2*pi) * sqrt(d));
surf(X, Y, Z);
? ? 當坐標(u,v)遠離原點時,函數值越小。這與概率的知識相符,越遠離中心(原點)的像素灰度值,對中心像素灰度值的相關性越小,所以被賦予的權值越小。
效果
? ? ? 觀察效果,使用不同標準差,和模板大小的結果:
? ? ? ? 結論: - 同等模板大小,標準差越大越模糊
- 標準差相同,模板越大圖像越模糊。
代碼
[cpp] view plaincopyprint?
void?GaussianMask(double?*mask,int?width,int?height,double?deta){??????double?deta_2=deta*deta;??????int?center_x=width/2;??????int?center_y=height/2;??????double?param=1.0/(2*M_PI*deta_2);??????for(int?i=0;i<height;i++)??????????for(int?j=0;j<width;j++){??????????????double?distance=Distance(j,?i,?center_x,?center_y);??????????????mask[i*width+j]=param*exp(-(distance*distance)/(2*deta_2));????????????}??????double?sum=0.0;??????for(int?i=0;i<width*height;i++)??????????sum+=mask[i];??????for(int?i=0;i<width*height;i++)??????????mask[i]/=sum;??}??????void?GaussianFilter(IplImage?*src,IplImage?*dst,int?width,int?height,double?deta){??????double?*?pixarry=(double?*)malloc(sizeof(double)*src->width*src->height);??????double?*?dstarry=(double?*)malloc(sizeof(double)*src->width*src->height);??????double?*?mask=(double?*)malloc(sizeof(double)*width*height);??????for(int?j=0;j<src->height;j++){??????????for(int?i=0;i<src->width;i++){??????????????pixarry[j*src->width+i]=cvGetReal2D(src,?j,?i);??????????}??????}??????GaussianMask(mask,?width,?height,?deta);??????RealRelevant(pixarry,dstarry,mask,src->width,src->height,width,height);??????for(int?j=0;j<src->height;j++){??????????for(int?i=0;i<src->width;i++){??????????????cvSetReal2D(?dst,j,i,dstarry[j*src->width+i]);??????????}??????}??????free(pixarry);??????free(dstarry);??????free(mask);??}?? void GaussianMask(double *mask,int width,int height,double deta){double deta_2=deta*deta;int center_x=width/2;int center_y=height/2;double param=1.0/(2*M_PI*deta_2);for(int i=0;i<height;i++)for(int j=0;j<width;j++){double distance=Distance(j, i, center_x, center_y);mask[i*width+j]=param*exp(-(distance*distance)/(2*deta_2));}double sum=0.0;for(int i=0;i<width*height;i++)sum+=mask[i];for(int i=0;i<width*height;i++)mask[i]/=sum;
}void GaussianFilter(IplImage *src,IplImage *dst,int width,int height,double deta){double * pixarry=(double *)malloc(sizeof(double)*src->width*src->height);double * dstarry=(double *)malloc(sizeof(double)*src->width*src->height);double * mask=(double *)malloc(sizeof(double)*width*height);for(int j=0;j<src->height;j++){for(int i=0;i<src->width;i++){pixarry[j*src->width+i]=cvGetReal2D(src, j, i);}}GaussianMask(mask, width, height, deta);RealRelevant(pixarry,dstarry,mask,src->width,src->height,width,height);for(int j=0;j<src->height;j++){for(int i=0;i<src->width;i++){cvSetReal2D( dst,j,i,dstarry[j*src->width+i]);}}free(pixarry);free(dstarry);free(mask);
}
總結
之前寫了很多結論,現在都忘完了,因為理論很簡單,主要是觀察結果,線性平滑基本就介紹這些,下篇介紹非線性的。
總結
以上是生活随笔為你收集整理的灰度图像--图像增强 平滑之均值滤波、高斯滤波的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。