加入噪声:
原理: 将图片灰度化,然后将图片像素归一化到[0,1]之间,然后添加均值为0,方差为0.1的高斯噪声,乘以255映射回图片原来的灰度级,用max(0,min(t1,255))操作将超出[0,255]的纠正。效果如图:
随机变量最简单的统计量是均值和方差,这些适当的参数是自适应局部滤波器的基础。均值给出了计算均值的区域中灰度平均值的度量,而方差给出了这个区域的平均对比度的度量。
主函数:
clear;clc;
%% 导入原图像,并添加高斯噪声
image=imread("1.jpg");
image=rgb2gray(image); %灰度化
[m,n,~]=size(image);
% y=0+0.2*randn(m,n/2); %只添加一半
y=0+0.2*randn(m,n); %全范围加上噪声
%先将其double化,再除以255 便于后面计算
t1=double(image)/255;
%加上噪声
% t1(:,(n/2+1):n)=t1(:,(n/2+1):n)+y;
t1(:,:)=t1(:,:)+y;
t1 = max(0,min(t1,1)); %处理到[0,1]
% t1(:,:)=t1(:,:)+y2;
%将像素范围扩大至0--255
t1=t1*255;
%转换为uint8类型 包含噪声的图片
t2=uint8(t1);
figure("color",[1,1,1])
subplot(1,2,1),imshow(image),title('原图');
subplot(1,2,2),imshow(t2),title('加入均值为0,标准差为0.2的高斯噪声后');
%% 计算噪声方差
t2_reshape=reshape(t1,1,1,length(t1(:)));
global_means=mean(t2_reshape);
global_vars=var(t2_reshape,1);
%% 自适应均值滤波器
image_with_noise=t1;
image_expand=padarray(image_with_noise, [3 3]); %扩展周围一圈
image1=double(image);
image_init=padarray(image1, [3 3]);
%扩展周围一圈,因为滤波器为7x7,可以有镜像扩充、对称扩充、常数扩充等等
imagemean=image_expand; %存储每个位置的局部均值
imagevar=image_expand; %存储每个位置的局部方差
[width,height,z]=size(image_expand);
s=7; %滤波器阶数
for i=1:width-s+1
for j=1:height-s+1
box=image_expand(i:i-1+s,j:j-1+s);
boxs=reshape(box,1,1,length(box(:)));
means=mean(boxs); %求均值
imagemean(i+(s-1)/2,j+(s-1)/2)=means;
vars=var(boxs,1); %求方差
imagevar(i+(s-1)/2,j+(s-1)/2)=vars;
end
end
image_expand=image_expand(3+1:width-3,3+1:height-3);
imagemean=imagemean(3+1:width-3,3+1:height-3); %去掉扩充的边缘
imagevar=imagevar(3+1:width-3,3+1:height-3); %去掉扩充的边缘
noise = mean2(imagevar);%估计全局噪声方差
%% 书上公式计算得到的滤波结果
image_new=image_expand-(noise./imagevar.*(image_expand-imagemean));
image_new = max(0,min(image_new,255)); %处理到[0,255]
image_new=uint8(image_new);
%% matlab源码做了改进,效果差距不是很大
image_new_default=imagemean + (max(0, imagevar - noise) ./max(imagevar, noise)) .* (image_expand - imagemean);
image_new_default=uint8(image_new_default);
%% 画图
figure("color",[1,1,1])
subplot(2,2,1);
imshow(image);
imshow(t2);
title('原图像');
output=mean_filter(image_expand,7);
subplot(2,2,2);
imshow(output);
title('均值滤波处理后结果');
subplot(2,2,3);
imshow(image_new);
title('自适应均值滤波处理后结果');
subplot(2,2,4);
imshow(image_new_default);
title('修改后的自适应均值滤波处理后结果');
% figure("color",[1,1,1])
% image_global_var=image_expand-(global_vars./imagevar.*(image_expand-imagemean));
% image_global_var = max(0,min(image_global_var,255)); %处理到[0,255]
% image_global_var=uint8(image_global_var);
% imshow(image_global_var);
% title('global var自适应均值滤波处理后结果');
子函数:
%自编写均值滤波器
function output=mean_filter(image,n)
%输入image为原始图像,n为滤波器规模n*n,输出为滤波后的图像output
[h,w]=size(image);
imaged=double(image); %转换为double类型
imagedd=imaged; %初始化滤波结果的规模
a=ones(n,n);
for i=1:h-n+1
for j=1:w-n+1
pattern=imaged(i:i+n-1,j:j+n-1).*a;
means=sum(sum(pattern));
imagedd(i+(n-1)/2,j+(n-1)/2)=means/(n*n);
end
end
output=uint8(imagedd);
end
主程序:
gray=imread('5.png');
gray=rgb2gray(gray); %灰度化
%% 加入噪声
gray_noise=imnoise(gray,'salt & pepper',0.5);
%% 中值滤波
M1 = medfilt2(gray_noise,[3,3]);
%% 自适应中值滤波
f1 = adaptive_median_filter(gray_noise,11);
%%
figure("color",[1,1,1]);
subplot(131)
imshow(gray_noise)
title("gray with noise")
subplot(132)
imshow(M1)
title("中值滤波")
subplot(133)
imshow(f1)
title("自适应中值滤波")
子函数:
function f = adaptive_median_filter (g, Smax)
%% 判断邻域是否合理
if (Smax <= 1) || (Smax/2 == round(Smax/2)) || (Smax ~= round(Smax))
error ('SMAX must be an odd integer > 1.')
end
%%
f = g;
f(:) = 0;
%% 标记是否已处理过
alreadyProcessed = false (size(g));
%% 开始自适应滤波
for k = 3:2:Smax
zmin = ordfilt2(g, 1, ones(k, k),'symmetric');
zmax = ordfilt2(g, k * k, ones(k, k), 'symmetric');
zmed = medfilt2(g, [k k], 'symmetric');
%% 判断是否进入进程B
processUsingLevelB = (zmed > zmin) & (zmax > zmed) & ~alreadyProcessed;
%% 若g不是脉冲,保留原值
zB = (g > zmin) & (zmax > g);
outputZxy = processUsingLevelB & zB;
%% 若是脉冲,用Zmed替换
outputZmed = processUsingLevelB & ~zB;
f (outputZxy) = g(outputZxy);
f (outputZmed) = zmed(outputZmed);
%% 已处理记录
alreadyProcessed = alreadyProcessed | processUsingLevelB;
%% 是否退出
if all (alreadyProcessed (:))
break;
end
end
%% 大于窗口尺寸后,Zxy替换成Zmed输出
f (~alreadyProcessed) = zmed (~alreadyProcessed);
end