自适应中值滤波器和自适应局部(均值)滤波器的设计 python+matlab各实现

要求是:自适应中值滤波器和自适应均值滤波器的设计,分别使用python和matlab去实现

一.原理

1.自适应中值滤波器
在这里插入图片描述在这里插入图片描述

2.自适应局部滤波器,也叫自适应均值滤波器
在这里插入图片描述在这里插入图片描述

二.设计流程

1.自适应中值滤波器
①生成椒盐噪声
利用rand()函数生成[0,1]的随机数,将随机数作逻辑判断,小于n值(n为椒盐密度)的为逻辑1,其余为逻辑0,再将这些逻辑值通过逻辑与、非等操作赋予像素点0或255值,得到椒盐噪声。

②设计中值滤波
中值滤波器的设计过程为:取出当前n*n阶滤波器对应的像素点,对其中像素作排序,取出中位数,赋予当前的中间位置像素点,放至结果矩阵中,输出。

③设计自适应中值滤波器
设计过程:以整个矩阵为整体进行操作。取出当前的n阶像素点,取出中位数、最小值、最大值并存储到新矩阵。将这三个新矩阵进行自适应中值滤波器的A、B过程的比较,并按照要求将符合的结果放至结果矩阵中,输出。
在这里插入图片描述

2.自适应局部滤波器
①生成高斯噪声
按照上次作业的原理设计出高斯噪声,并添加到原图像中。

②设计均值滤波器
设计过程为:取出当前n*n阶滤波器对应的像素点,求其均值,并将结果放至结果矩阵中,输出。

③设计自适应均值滤波器
设计过程为:求噪声方差;以矩阵为整体运算,求出n阶滤波器对应的像素点像素的均值,方差;将局部方差与噪声方差进行比较,按照规则计算新的像素,并存在结果矩阵中,输出。

在这里插入图片描述

三.MATLAB代码

①自适应中值滤波器,对灰度图像进行处理

%自适应中值滤波器,对灰度图像进行处理
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('自适应中值滤波处理后的彩色图像');

四.运行结果

①自适应中值滤波器的程序运行结果:
该图包括有:加入椒盐噪声的原图像显示,中值滤波与均值滤波的处理结果图显示,自适应中值滤波的灰度图结果显示,自适应中值滤波的彩色图结果显示。以子图的形式显示,是方便了进行原图与处理结果的比较,以及各种方法的效果比较总结。
结果分析:当椒盐噪声的密度较大时,中值滤波的处理结果不理想,仍存在较多噪声点,而自适应中值滤波的处理结果较好,灰度图和彩色图的结果都能较为清晰。
在这里插入图片描述

②自适应均值滤波器的程序运行结果:
该图包括有:添加了高斯噪声的原图像,均值滤波处理后的结果显示,自适应均值滤波处理后的结果,均是以灰度图的形式显示。
结果分析:均值滤波的处理结果仍是较模糊,自适应的效果更好,能让局部的像素点更加的清晰,但实现起来较复杂。
在这里插入图片描述

五.python版本代码

自适应局部滤波器

# 自适应均值滤波器
# 即,自适应局部滤波器

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()

猜你喜欢

转载自blog.csdn.net/Wadewhl/article/details/112318534