圖像處理系列-均值濾波和中值濾波
1.均值濾波與中值濾波介紹
在經典書籍《數字圖像處理第三版-岡薩雷斯》中介紹了濾波相關概念,并詳細講解了均值濾波與中值濾波的原理。如果本文有不詳盡之處,可查閱本書P93平滑空間濾波部分。
宏觀上,讓我們了解均值濾波和中值濾波在圖像進行中的位置。在數字圖像進行中,濾波是很重要的一部分,均值濾波和中值濾波是都屬于空間濾波(對于某一像素點,以該點為中心,通過對該像素點鄰域部分的像素進行處理,得到中心替代像素點的濾波方法)中的平滑濾波方法(還有銳化濾波等)。進一步,平滑濾波分為平滑線性濾波器和平滑非線性濾波器,而均值濾波屬于前者,中值濾波屬于後者。
應用上,均值濾波處理高斯噪聲效果較好,中值濾波處理椒鹽噪聲比較好,原因點選檢視。
2.原理說明
對于通用的權重平滑濾波器,計算公式由下式給出:
f ( x , y ) = ∑ s = − a a ∑ − b b w ( s , t ) f ( x + s , y + t ) ∑ s = − 1 a ∑ s = − b b w ( s , t ) f(x,y)=\frac{\sum_{s=-a}^{a}\sum_{-b}^{b} w(s,t)f(x+s,y+t)}{\sum_{s=-1}^{a}\sum_{s=-b}^{b}w(s,t)} f(x,y)=∑s=−1a∑s=−bbw(s,t)∑s=−aa∑−bbw(s,t)f(x+s,y+t)
其中f(x,y)為圖像上坐标為(x,y)的點的灰階值,a與b為以(x,y)為中心的矩形(視窗)的半長與半寬,w(s,t)為給點(s,t)所加的權重。
對于視窗大小為3的均值濾波器,化簡公式如下:
f ( x , y ) = 1 9 ∑ i = 1 9 Z i f(x,y)=\frac{1}{9}\sum_{i=1}^{9}Z_{i} f(x,y)=91i=1∑9Zi
其中,Zi為以點(x,y)為中心,3×3的正方形中的九個點的灰階值。同理,視窗大小為n時,正方形的邊長随之改變為n。可以看出,如果噪聲為高斯噪聲,測量值在真實值周圍波動,取得平均之後會得到相對準确的值。
對于視窗大小為3的中值濾波器,f(x,y)的值應為Zi組成的數列(長度為9)的中值。可以看出,如果噪聲為椒鹽噪聲,像素會出現劇烈跳動,而中值對極大值和極小值不敏感,取中值後可以很好過濾掉此類噪聲。
3.圖像邊界處理
由于在視窗滑動的過程中,圖像的邊界不能作為小視窗的中心,故需要對圖像邊界進行一些人為處理。常見的處理方法如下。
- 不做處理咳咳咳。
- 忽略掉圖像邊界點,輸出圖像的尺寸會減小。
- 忽略掉圖像邊界點,濾波計算完成後裁剪掉未濾波的像素點,再将裁剪後的圖像放大到原圖大小。
- 根據視窗大小,想邊界外填補一些像素,填充的像素灰階值與最近像素灰階值相同。
本文代碼才用的是第三個處理方案,使用雙線性插值法來放大。
4.效果
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SO3YmNxkDM2cTYhFWYxMzYzkzY5YjNyYmN4YDMwUWMx8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
5.代碼
github倉庫
clc;clear;
%% 參數輸入區,在此選擇視窗大小和濾波方式
filterSize = 7;
% filterMode = 'median';
filterMode = 'average';
I=imread('./circuit.jpg');
%% 開始運作
I = rgb2gray(I);
%%邊界,資料格式(圖像uint8,預設類型轉換)
switch filterMode
case 'average'
[h,w] = size(I);
imageOut = zeros(h, w);%為了擴充圖像而建立的臨時圖像
stepRange = (filterSize-1)/2;
%%外層兩個for循環用來定位視窗中心,内層兩個for用來視窗濾波計算
for pointRow = 1+stepRange : h-stepRange
for pointCol = 1+stepRange : w-stepRange
pixelSum = 0;
for i = pointRow-stepRange:pointRow+stepRange
for j = pointCol-stepRange:pointCol+stepRange
pixelSum = pixelSum + double(I(i, j));
end
end
pixelValue = pixelSum/filterSize^2;
imageOut(pointRow, pointCol) = uint8(pixelValue);
end
end
imageOut = uint8(imageOut); %double轉化為uint8格式
imageOut = imcrop(imageOut,[1+stepRange,1+stepRange,w-2*stepRange-1,h-2*stepRange-1]);
imageOut = imresize(imageOut, [h, w], 'bilinear');
case 'median'
[h,w] = size(I);
imageOut = zeros(h, w);%為了擴充圖像而建立的臨時圖像
stepRange = (filterSize-1)/2;
%%外層兩個for循環用來定位視窗中心,内層兩個for用來視窗濾波計算
for pointRow = 1+stepRange : h-stepRange
for pointCol = 1+stepRange : w-stepRange
pixelArray = zeros(1, filterSize^2);
ptrPA = 1;
for i = pointRow-stepRange:pointRow+stepRange
for j = pointCol-stepRange:pointCol+stepRange
pixelArray(ptrPA) = double(I(i, j));
ptrPA = ptrPA + 1;
end
end
imageOut(pointRow, pointCol) = uint8(median(pixelArray));
end
end
imageOut = uint8(imageOut); %double轉化為uint8格式
imageOut = imcrop(imageOut,[1+stepRange,1+stepRange,w-2*stepRange-1,h-2*stepRange-1]);
imageOut = imresize(imageOut, [h, w], 'bilinear');
end
subplot(121),imshow(I);
subplot(122),imshow(imageOut);
impixelinfo;