要求是:自适应中值滤波器和自适应均值滤波器的设计,分别使用python和matlab去实现
1.自适应中值滤波器
①生成椒盐噪声
利用rand()函数生成[0,1]的随机数,将随机数作逻辑判断,小于n值(n为椒盐密度)的为逻辑1,其余为逻辑0,再将这些逻辑值通过逻辑与、非等操作赋予像素点0或255值,得到椒盐噪声。
②设计中值滤波
中值滤波器的设计过程为:取出当前n*n阶滤波器对应的像素点,对其中像素作排序,取出中位数,赋予当前的中间位置像素点,放至结果矩阵中,输出。
③设计自适应中值滤波器
设计过程:以整个矩阵为整体进行操作。取出当前的n阶像素点,取出中位数、最小值、最大值并存储到新矩阵。将这三个新矩阵进行自适应中值滤波器的A、B过程的比较,并按照要求将符合的结果放至结果矩阵中,输出。
2.自适应局部滤波器
①生成高斯噪声
按照上次作业的原理设计出高斯噪声,并添加到原图像中。
②设计均值滤波器
设计过程为:取出当前n*n阶滤波器对应的像素点,求其均值,并将结果放至结果矩阵中,输出。
③设计自适应均值滤波器
设计过程为:求噪声方差;以矩阵为整体运算,求出n阶滤波器对应的像素点像素的均值,方差;将局部方差与噪声方差进行比较,按照规则计算新的像素,并存在结果矩阵中,输出。
①自适应中值滤波器,对灰度图像进行处理
%自适应中值滤波器,对灰度图像进行处理
function output=adp_median(image,nmin,nmax)
%输入为:image原图像,nmin滤波器的最小阶数,nmax滤波器的最大阶数
%image=rgb2gray(image); %灰度图像
%image=imnoise(image,'salt & pepper',0.5);
[h,w,~]=size(image);
imaged=double(image);
imagedd=imaged;
imagemid=imaged;
imagemin=imaged;
imagemax=imaged;
for k=nmin:2:nmax
for i=1:h-k+1
for j=1:w-k+1
pattern=imaged(i:i+k-1,j:j+k-1); %取出n*n的像素点值
patterns=reshape(pattern,1,length(pattern(:))); %将n*n矩阵转换为行向量
middle=median(patterns); %对行向量取中位数
mini=min(patterns); %对行向量取最小值
maxi=max(patterns);%对行向量取最大值
imagemid(i+(k-1)/2,j+(k-1)/2)=middle;
imagemin(i+(k-1)/2,j+(k-1)/2)=mini;
imagemax(i+(k-1)/2,j+(k-1)/2)=maxi;
end
end
pa=(imagemax>imagemid)&(imagemid>imagemin);%A步骤的判断(对整个矩阵判断)
pb=(image>imagemin)&(imagemax>image);%B步骤的判断
zxy=pa&pb; %满足A,B条件的记在zxy位置
zmed=pa&~pb;%满足A条件,不满足B条件的记在zmed位置
imagedd(zxy)=image(zxy);%输出zxy
imagedd(zmed)=imagemid(zmed);%输出zmed
if k==nmax %超过最大窗口尺寸的,输出zmed
zmedd=~pa;
imagedd(zmedd)=imagemid(zmedd);
end
end
imagedd=uint8(imagedd); %转换为图片格式
output=imagedd;%输出
End
②自适应中值滤波器,对彩图进行处理
%自编写自适应中值滤波器处理三通道彩色图像
function output=adpmedian(image,nmin,nmax)
[h,w,~]=size(image);
imaged=double(image);
imaged1=imaged(:,:,1);
imaged2=imaged(:,:,2);
imaged3=imaged(:,:,3);
imagedd=imaged;
imagedd1=imaged(:,:,1);
imagedd2=imaged(:,:,2);
imagedd3=imaged(:,:,3);
imagemid=imaged;
imagemid1=imaged(:,:,1);
imagemid2=imaged(:,:,2);
imagemid3=imaged(:,:,3);
imagemin=imaged;
imagemin1=imaged(:,:,1);
imagemin2=imaged(:,:,2);
imagemin3=imaged(:,:,3);
imagemax=imaged;
imagemax1=imaged(:,:,1);
imagemax2=imaged(:,:,2);
imagemax3=imaged(:,:,3);
alreadyProcessed1=false(size(imaged1));
alreadyProcessed2=false(size(imaged2));
alreadyProcessed3=false(size(imaged3));
for k=nmin:2:nmax
for i=1:h-k+1
for j=1:w-k+1
pattern1=imaged1(i:i+k-1,j:j+k-1); %取出n*n的像素点值
pattern2=imaged2(i:i+k-1,j:j+k-1);
pattern3=imaged3(i:i+k-1,j:j+k-1);
patterns1=reshape(pattern1,1,length(pattern1(:))); %将n*n矩阵转换为行向量
patterns2=reshape(pattern2,1,length(pattern2(:)));
patterns3=reshape(pattern3,1,length(pattern3(:)));
middle1=median(patterns1); %对行向量取中位数
middle2=median(patterns2);
middle3=median(patterns3);
mini1=min(patterns1);
mini2=min(patterns2);
mini3=min(patterns3);
maxi1=max(patterns1);
maxi2=max(patterns2);
maxi3=max(patterns3);
imagemid1(i+(k-1)/2,j+(k-1)/2)=middle1;
imagemid2(i+(k-1)/2,j+(k-1)/2)=middle2;
imagemid3(i+(k-1)/2,j+(k-1)/2)=middle3;
imagemin1(i+(k-1)/2,j+(k-1)/2)=mini1;
imagemin2(i+(k-1)/2,j+(k-1)/2)=mini2;
imagemin3(i+(k-1)/2,j+(k-1)/2)=mini3;
imagemax1(i+(k-1)/2,j+(k-1)/2)=maxi1;
imagemax2(i+(k-1)/2,j+(k-1)/2)=maxi2;
imagemax3(i+(k-1)/2,j+(k-1)/2)=maxi3;
end
end
pa1=(imagemax1>imagemid1)&(imagemid1>imagemin1)&(~alreadyProcessed1);
pa2=(imagemax2>imagemid2)&(imagemid2>imagemin2)&(~alreadyProcessed2);
pa3=(imagemax3>imagemid3)&(imagemid3>imagemin3)&(~alreadyProcessed3);
pb1=(imaged1>imagemin1)&(imagemax1>imaged1);
pb2=(imaged2>imagemin2)&(imagemax2>imaged2);
pb3=(imaged3>imagemin3)&(imagemax3>imaged3);
zxy1=pa1&pb1;
zxy2=pa2&pb2;
zxy3=pa3&pb3;
zmed1=pa1&~pb1;
zmed2=pa2&~pb2;
zmed3=pa3&~pb3;
imagedd1(zxy1)=imaged1(zxy1);
imagedd2(zxy2)=imaged2(zxy2);
imagedd3(zxy3)=imaged3(zxy3);
imagedd1(zmed1)=imagemid1(zmed1);
imagedd2(zmed2)=imagemid2(zmed2);
imagedd3(zmed3)=imagemid3(zmed3);
alreadyProcessed1=alreadyProcessed1|pa1;%处理过的像素
alreadyProcessed2=alreadyProcessed2|pa2;
alreadyProcessed3=alreadyProcessed2|pa3;
if all(alreadyProcessed1(:)&alreadyProcessed2(:)&alreadyProcessed3(:))
break;
end
end
imagedd1(~alreadyProcessed1) = imagemid1(~alreadyProcessed1);
imagedd2(~alreadyProcessed2) = imagemid2(~alreadyProcessed2);
imagedd3(~alreadyProcessed3) = imagemid3(~alreadyProcessed3);
imagedd=cat(3,imagedd1,imagedd2,imagedd3);
imagedd=uint8(imagedd);
output=imagedd;
③自适应均值滤波器,对灰度图进行处理
clear;clc;
%% 导入原图像,并添加高斯噪声
image=imread('whl.jpg');
[width,height,~]=size(image);
imagen=rgb2gray(image);
mu=0; %均值
sigma=0.1; %标准差
u1=rand(width,height); %生成图像大小的均匀(0,1)分布的u1,u2
u2=rand(width,height);
x=sigma*sqrt(-2*log(u1)).*cos(2*pi*u2)+mu; %box-muller方法的公式书写,生成的是标准正态分布,再乘上标准差,加上均值,为最终的高斯分布
k=double(imagen)/255;
imagen=k+x; %将图像变为double型,且数值区间在(0,1),再加上高斯分布形成的噪声
imagen=uint8(255*imagen); %将double类型的灰度值变回为图像
%% 自适应均值滤波器的设计
imagenn=double(imagen);
iamgee=rgb2gray(image); %取未加噪声的原图像的灰度
iamgee=double(iamgee);
%初始化
imagedd=imagenn;
imagemean=imagenn;
imagevar=imagenn;
n=7;%滤波器阶数为7
sigma=(imagenn-iamgee).^2; %干扰f形成在gxy上的噪声方差
for i=1:width-n+1
for j=1:height-n+1
pattern=imagenn(i:i+n-1,j:j+n-1);
patterns=reshape(pattern,1,length(pattern(:)));
means=mean(patterns);%求均值
imagemean(i+(n-1)/2,j+(n-1)/2)=means;
vars=var(patterns,1);%求方差
imagevar(i+(n-1)/2,j+(n-1)/2)=vars;
end
end
%对自适应局部滤波的各项条件作了修改
da=(sigma<1);%噪声方差小于1的返回原像素值
dc=~da&(abs(sigma-imagevar)<=100); %噪声方差与局部方差高度相关时,返回一个近似值
db=~dc; %略有调整,剩下的像素位置设置为均值
%da,db,dc为逻辑值
imagedd(da)=imagenn(da);
imagedd(db)=imagemean(db);
imagedd(dc)=imagenn(dc)-(sigma(dc)./imagevar(dc).*(imagenn(dc)-imagemean(dc)));
imagedd=uint8(imagedd);
%% 画图
subplot(1,3,1);
imshow(imagen);
title('原图像');
output=mean_filter(imagen,3);
subplot(1,3,2);
imshow(output);
title('均值滤波处理后结果');
subplot(1,3,3);
imshow(imagedd);
title('自适应均值滤波处理后结果');
其他程序:
④中值滤波器
%自编写中值滤波器
function output=mid_filter(image,n)
%输入image为原始图像,n为滤波器规模n*n,输出为滤波后的图像output
[h,w]=size(image);
imaged=double(image); %转换为double类型
imagedd=imaged; %初始化滤波结果的规模
for i=1:h-n+1
for j=1:w-n+1
pattern=imaged(i:i+n-1,j:j+n-1); %取出n*n的像素点值
patterns=reshape(pattern,1,length(pattern(:))); %将n*n矩阵转换为行向量
middle=median(patterns); %对行向量取中位数
imagedd(i+(n-1)/2,j+(n-1)/2)=middle; %该值储存在滤波结果的对应位置上
end
end
output=uint8(imagedd);
end
⑤均值滤波器
%自编写均值滤波器
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
⑥椒盐噪声
%自编写添加椒盐噪声
function output=salt_noise(image,n)
%输入image为原图像,n为椒盐噪声的密度,输出为添加椒盐噪声后的图像
[width,height,~]=size(image);
result2=image;
%k1、k2作为判断临界点
k1=n;
k2=n;
%小于k的元素在矩阵中为1,反之为0(逻辑值)
a1=rand(width,height)<k1;
a2=rand(width,height)<k2;
b1=rand(width,height)<k1;
b2=rand(width,height)<k2;
c1=rand(width,height)<k1;
c2=rand(width,height)<k2;
%合成彩色图像,RGB三通道分开添加
t1=result2(:,:,1);
t2=result2(:,:,2);
t3=result2(:,:,3);
%分成黑点,白点
% a1&a2:a1,a2均为1时,结果为逻辑1
t1(a1&a2)=0;
t2(b1&b2)=0;
t3(c1&c2)=0;
% a1&~a2:a1为1,a2为0时,结果为逻辑1
t1(a1& ~a2)=255;
t2(b1& ~b2)=255;
t3(c1& ~c2)=255;
result2(:,:,1)=t1;
result2(:,:,2)=t2;
result2(:,:,3)=t3;
output=result2;
end
⑦主程序:显示各个子图
clear;clc;
image=imread('whl.jpg');
subplot(2,4,1),imshow(image),title('原图');
k1=salt_noise(image,0.5);
subplot(2,4,2),imshow(k1),title('加入椒盐噪声');
output11=mid_filter(k1,3);
subplot(2,4,3),imshow(output11),title('中值滤波处理后');
output22=mean_filter(k1,3);
subplot(2,4,4),imshow(output22),title('均值滤波处理后');
imagen=rgb2gray(image);
imagen=imnoise(imagen,'salt & pepper',0.5);
subplot(2,4,5),imshow(imagen),title('灰度图');
imagedd=adp_median(imagen,3,9);
subplot(2,4,6),imshow(imagedd),title('自适应中值滤波处理后');
imagenn=salt_noise(image,0.5);
subplot(2,4,7),imshow(imagenn),title('0.5椒盐噪声图');
imagekk=adpmedian(imagenn,3,21);
subplot(2,4,8),imshow(imagekk),title('自适应中值滤波处理后的彩色图像');
①自适应中值滤波器的程序运行结果:
该图包括有:加入椒盐噪声的原图像显示,中值滤波与均值滤波的处理结果图显示,自适应中值滤波的灰度图结果显示,自适应中值滤波的彩色图结果显示。以子图的形式显示,是方便了进行原图与处理结果的比较,以及各种方法的效果比较总结。
结果分析:当椒盐噪声的密度较大时,中值滤波的处理结果不理想,仍存在较多噪声点,而自适应中值滤波的处理结果较好,灰度图和彩色图的结果都能较为清晰。
②自适应均值滤波器的程序运行结果:
该图包括有:添加了高斯噪声的原图像,均值滤波处理后的结果显示,自适应均值滤波处理后的结果,均是以灰度图的形式显示。
结果分析:均值滤波的处理结果仍是较模糊,自适应的效果更好,能让局部的像素点更加的清晰,但实现起来较复杂。
自适应局部滤波器
# 自适应均值滤波器
# 即,自适应局部滤波器
import cv2
import numpy as np
import matplotlib.pyplot as plt
def ada_mean_m(image):
[width, height] = image.shape[:2]
imagen = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
mu = 0 # 均值
sigma = 0.1 # 标准差
u1 = np.random.rand(width, height) # 生成图像大小的均匀(0,1)分布的u1,u2
u2 = np.random.rand(width, height)
x = sigma * np.sqrt(-2 * np.log(u1)) * np.cos(
2 * np.pi * u2) + mu # box-muller方法的公式书写,生成的是标准正态分布,再乘上标准差,加上均值,为最终的高斯分布
k = imagen / 255
imagen = k + x # 将图像变为double型,且数值区间在(0,1),再加上高斯分布形成的噪声
imagen = np.uint8(255 * imagen) # 将double类型的灰度值变回为图像
# 自适应均值滤波器的设计
imagenn = imagen
iamgee = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 取未加噪声的原图像的灰度
iamgee = iamgee
# 初始化
imagecc = imagenn
imagedd = imagenn
imagemean = imagenn
imagevar = imagenn
n = 7 # 滤波器阶数为7
sigma0 = (imagenn - iamgee) ^ 2 # 干扰f形成在gxy上的噪声方差
for i in range(width - n + 1):
for j in range(height - n + 1):
pattern = imagenn[i:i + n - 1, j:j + n - 1]
height = int(pattern.shape[0])
width = int(pattern.shape[1])
dim = width * height
patterns = cv2.resize(pattern, (dim, 1), interpolation=cv2.INTER_AREA)
means = np.mean(patterns) # 求均值
imagemean[int(i + (n - 1) / 2), int(j + (n - 1) / 2)] = means
Vars = np.var(patterns, 1) # 求方差
imagevar[int(i + (n - 1) / 2), int(j + (n - 1) / 2)] = Vars
da = (sigma0 < 1) # 噪声方差小于1的返回原像素值
dc = ~da & (abs(sigma0 - imagevar) <= 100) # 噪声方差与局部方差高度相关时,返回一个近似值
db = ~dc # 略有调整,剩下的像素位置设置为均值
# da,db,dc为逻辑值
imagedd[da] = imagenn[da]
imagedd[db] = imagemean[db]
imagedd[dc] = imagenn[dc] - (sigma0[dc] / imagevar[dc] * (imagenn[dc] - imagemean[dc]))
where_are_nan = np.isnan(imagedd)
where_are_inf = np.isinf(imagedd)
imagedd[where_are_nan] = 0
imagedd[where_are_inf] = 0
imagedd = np.uint8(imagedd)
return imagedd
# 导入原图像,并添加高斯噪声
image = cv2.imread('whl.jpg', 1)
# 画图
plt.subplot(1, 3, 1)
plt.imshow(image)
plt.title('original')
'''
output=mean_filter(imagen,3)
plt.subplot(1,3,2)
plt.imshow(output)
plt.title('均值滤波处理后结果')
'''
imagedd = ada_mean_m(image)
plt.subplot(1, 3, 3)
plt.imshow(imagedd)
plt.title('adapt_mean_filter')
plt.show()
自适应中值滤波器
# 自适应中值滤波器
import cv2
import numpy as np
import matplotlib.pyplot as plt
def AdaptProcess(src, i, j, minSize, maxSize):
filter_size = minSize
kernelSize = filter_size // 2
rio = src[i-kernelSize:i+kernelSize+1, j-kernelSize:j+kernelSize+1]
minPix = np.min(rio)
maxPix = np.max(rio)
medPix = np.median(rio)
zxy = src[i, j]
if (medPix > minPix) and (medPix < maxPix):
if (zxy > minPix) and (zxy < maxPix):
return zxy
else:
return medPix
else:
filter_size = filter_size + 2
if filter_size <= maxSize:
return AdaptProcess(src, i, j, filter_size, maxSize)
else:
return medPix
def adapt_meadian_filter(img, minsize, maxsize):
borderSize = maxsize // 2
src = cv2.copyMakeBorder(img, borderSize, borderSize, borderSize, borderSize, cv2.BORDER_REFLECT)
for m in range(borderSize, src.shape[0] - borderSize):
for n in range(borderSize, src.shape[1] - borderSize):
src[m, n] = AdaptProcess(src, m, n, minsize, maxsize)
dst = src[borderSize:borderSize+img.shape[0], borderSize:borderSize+img.shape[1]]
return dst
# 导入原图像,并添加高斯噪声
image = cv2.imread('whl.jpg')
imagen = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 画图
plt.subplot(1, 3, 1)
plt.imshow(image)
plt.title('original')
'''
output=mean_filter(imagen,3)
plt.subplot(1,3,2)
plt.imshow(output)
plt.title('均值滤波处理后结果')
'''
imagedd = adapt_meadian_filter(imagen, 3, 9)
plt.subplot(1, 3, 3)
plt.imshow(imagedd)
plt.title('adapt_meadian_filter')
plt.show()