算法分析
-
對原圖像矩陣邊界填充(填充的行列根據濾波器模板大小來設置),這里使用3*3的模板,所以向外擴充一圈,行和列增加2,這里使用的是復制邊界的填充方式'replicate'(直接調用的padarray函數),也可以直接通過矩陣賦值的方法實現邊界填充
-
遍歷原圖像每個通道的每個像素點,取擴充邊界后圖像中濾波器大小的像素點個數,求得中值,將中值賦給當前遍歷的像素點
-
輸出圖像的大小是新開辟的和原圖像大小相等的矩陣,求得的中值應該賦值給新矩陣中每個元素
function outputimg = mymedfilt2(A)
% 利用中值濾波去噪
% 參數A是加噪的圖像矩陣
% outputimg是輸出中值濾波后的圖像
[H,W,CH] = size(A);
N = 3; %設置中值濾波器的大小為3*3
M = zeros(H+2,W+2,CH);
%對彩色圖的每一個通道都進行邊界填充
for i = 1 : CH
%直接調用padarray,在原圖的每一維度的第一個元素和最后一個元素后,以復制邊界的方式進行填充
M(:,:,i) = padarray(A(:,:,i),[1,1],'replicate');
end
%矩陣賦值法,復制邊界型填充
% M(2:height+1,2:width+1) = A(1:height,1:width);%原矩陣直接復制到新矩陣中心
% %使用直接復制最邊界的層
% M(1,2:width+1) = A(1,:); %將M的第一行
% M(height + 2,2:width+1) = A(height,:); %M的最后一行
% M(2:height+1,1) = A(:,1); %M的第一列
% M(2:height+1,width+2) = A(:,width); %M的最后一列
outputimg = zeros(H,W,CH);
for k = 1 : CH
for i = 1 : H
for j = 1 : W
c = M(i:i + (N-1),j:j + (N-1),k); %在C中從頭取模板大小的塊賦給c
e = c(1,:); %e中存放是c矩陣的第一行
for u = 2:N % 將c中的其他行元素取出來接在e后使e為一個行矩陣
e = [e,c(u,:)];
end
med = median(e); %n*n這幾個像素點的中值
outputimg(i,j,k) = med; %將模板各元素的中值賦給模板中心位置的元素
end
end
end
outputimg = uint8(outputimg);
end
實驗結果
% 調用示例:
I = imread('cameraman.tif');
M = imnoise(I,'salt & pepper');
B = mymedfilt2(I);
subplot(1,2,1),imshow(M),title('加椒鹽噪聲');
subplot(1,2,2),imshow(B),title('中值濾波');
% 調用示例:
I = imread('cameraman.tif');
M = imnoise(I,'gaussian',0,0.02);
B = mymedfilt2(M);
subplot(1,2,1),imshow(M),title('加高斯噪聲');
subplot(1,2,2),imshow(B),title('中值濾波');
實驗分析
-
由實驗結果可見,中值濾波是一個非線性濾波。它對椒鹽噪聲這類隨機出現的噪點有比較好的平滑效果,但對於線性的噪聲(如高斯噪聲)效果不佳
-
如下圖,使用Matlab自帶的中值濾波函數medfilt2,生成的圖像的四個邊緣會有黑點,原因是直接調用,默認是邊界0填充,當加入椒鹽噪聲時,會因求得的中值還是0,而得到黑點
B = medfilt2(M);
- 解決辦法,增加參數PADOPT控制邊界填充的方式,如果PADOPT為' 0 ',則填充邊界處都是0。如果PADOPT是‘symmetric’,則是對稱地在邊界上擴展的。如果PADOPT為'indexed',如果A是雙值,則用1填充;否則它被0填充
B = medfilt2(M,[3,3],'symmetric');