天天看點

圖像處理系列-均值濾波和中值濾波圖像處理系列-均值濾波和中值濾波

圖像處理系列-均值濾波和中值濾波

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=−bb​w(s,t)∑s=−aa​∑−bb​w(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)=91​i=1∑9​Zi​

其中,Zi為以點(x,y)為中心,3×3的正方形中的九個點的灰階值。同理,視窗大小為n時,正方形的邊長随之改變為n。可以看出,如果噪聲為高斯噪聲,測量值在真實值周圍波動,取得平均之後會得到相對準确的值。

對于視窗大小為3的中值濾波器,f(x,y)的值應為Zi組成的數列(長度為9)的中值。可以看出,如果噪聲為椒鹽噪聲,像素會出現劇烈跳動,而中值對極大值和極小值不敏感,取中值後可以很好過濾掉此類噪聲。

3.圖像邊界處理

由于在視窗滑動的過程中,圖像的邊界不能作為小視窗的中心,故需要對圖像邊界進行一些人為處理。常見的處理方法如下。

  • 不做處理咳咳咳。
  • 忽略掉圖像邊界點,輸出圖像的尺寸會減小。
  • 忽略掉圖像邊界點,濾波計算完成後裁剪掉未濾波的像素點,再将裁剪後的圖像放大到原圖大小。
  • 根據視窗大小,想邊界外填補一些像素,填充的像素灰階值與最近像素灰階值相同。

本文代碼才用的是第三個處理方案,使用雙線性插值法來放大。

4.效果

圖像處理系列-均值濾波和中值濾波圖像處理系列-均值濾波和中值濾波

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;
           

繼續閱讀