写了篇实现medfilt2函数功能的文章,有兴趣的朋友可以看看:medfilt2函数的实现源代码
目录
中值滤波
原理
中值滤波窗口
重要特性
实现方法
图像处理程序
原图与加噪图像(椒盐噪声)
3*3方形窗口
5*5方形窗口
横线窗口(5像素点)
竖线窗口(5像素点)
原图与加噪图像(高斯噪声)
3*3方形窗口(高斯噪声)
应用与注意事项
中值滤波代码
中值滤波
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。
二维中值滤波输出为
g(x,y)=med{f(x-k,y-l),(k,l∈W)}
其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W为二维模板,通常为3*3,5*5区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。
常见的中值滤波窗口,即为上面提及的W(二维模板)
许录平《数字图像处理》(第二版) P87
以使用3*3方形窗口进行中值滤波为例,如下图,这些数据是从加椒盐噪声的图像和处理后的图像截取的一部分像素点的灰度值(非图像边缘处),对框内9个数排序,然后将中值代替原值,便是图中的156→157
clear;close all;clc;
f=imread('cameraman.tif');
fsap=imnoise(f,'salt & pepper',0.05); %加入椒盐噪声
% fsap=imnoise(f,'gaussian',0.01); %加入高斯噪声
fmed=median_filtering(fsap,6,3); %中值滤波
subplot(121),imshow(f);title('原图')
subplot(122),imshow(fsap);title('加噪图像')
figure;
subplot(121),imshow(fmed);title('中值滤波处理')
subplot(122),fimg=medfilt2(fsap,[3 3]);imshow(fimg);title('medfilt2处理') %对比medfilt2函数
根据代码,会进行线状(横线与竖线)窗口以及方形窗口的中值滤波,并与medfilt2函数对比(上面的代码为3*3方形窗口,使用其他窗口仅需修改一下数字)
首先我们对原图进行加噪处理,此处加的是椒盐噪声
然后我们使用3*3方形的中值滤波窗口进行处理
眼尖的朋友会发现其实我是没有处理边缘的而medfilt2函数是有处理的,因为边缘处凑不足9个像素点,所以让边缘取最近值用以消除边缘噪声
实际处理效果如下图(图像左下角处),四个顶角取离它最近的像素点的灰度值。我们能看出边缘同时也会变得模糊
最终效果
对比
再看看其他窗口处理的效果如何
十字形、X状那些窗口不再一一展示,接下来展示一下处理高斯噪声的情况
中值滤波是一个非线性滤波。它对椒盐噪声这类随机出现的噪点有比较好的平滑效果,但对于线性的噪声(如高斯噪声)效果不佳
中值滤波法对消除椒盐噪声及干扰脉冲非常有效,尤其适合于目标物形状是块状时的图像滤波。
在光学测量条纹图象的相位分析处理方法中有特殊作用,但在条纹中心分析方法中作用不大。
中值滤波在图像处理中,常用于保护边缘信息(不处理边缘的话),是经典的平滑噪声的方法。
具有丰富尖角几何结构的图像,一般采用十字形滤波窗,且窗口大小最好不要超过图像中最小目标物的尺寸,否则会丢失目标物的细小几何特征。
需要保持细线状及尖顶角目标物细节时,最好不要使用中值滤波。
再推一次medfilt2函数的文章:medfilt2函数的实现源代码
function fmed=median_filtering(f,mode,num)
%中值滤波
%f为含噪图像
%返回的fmed为中值滤波处理后的图像
%mode取不同的数值代表不同的窗口,取值范围为1-8
%mode=1,为横线,num为对应的像素点,仅支持大于1的奇数
%mode=2,为竖线,num为对应的像素点,仅支持大于1的奇数
%mode=3,为十字形-5像素点
%mode=4,为十字形-9像素点
%mode=5,为X状
%mode=6,为方形,num为方形矩阵阶数,仅支持大于1的奇数
%mode=7,为菱形
%mode=8,为圆形
%统一使边缘处取最近值
[m,n]=size(f); %读取矩阵大小
fmed=f;
%开始进行中值滤波
if mode==1||mode==2 %线状窗口
num2=(num+1)/2;
a=ones(1,num); %提前创建矩阵提升运算速度
if mode==1 %横线线状窗口
for w=1:m %从第一行到最后一行
for l=num2:n-num2+1
for o=1:num
a(o)=f(w,l+o-num2); %线状窗口取值
end
a=sort(a); %排序
fmed(w,l)=a(num2);
end
end
elseif mode==2 %竖线线状窗口
for w=num2:m-num2+1
for l=1:n %从第一列到最后一列
for o=1:num
a(o)=f(w+o-num2,l); %线状窗口取值
end
a=sort(a); %排序
fmed(w,l)=a(num2);
end
end
end
elseif mode==3||mode==5||mode==6
if mode==3 %十字形(5个点)
for w=2:m-2
for l=2:n-2
a(1)=f(w-1,l); %取点
a(2)=f(w,l-1);
a(3)=f(w,l);
a(4)=f(w,l+1);
a(5)=f(w+1,l);
a=sort(a); %对a排序
fmed(w,l)=a(3); %赋中值
end
end
elseif mode==5 %X状
for w=2:m-2
for l=2:n-2
a(1)=f(w-1,l-1); %取点
a(2)=f(w-1,l+1);
a(3)=f(w,l);
a(4)=f(w+1,l-1);
a(5)=f(w+1,l+1);
a=sort(a); %对a排序
fmed(w,l)=a(3); %赋中值
end
end
else %num阶方形
a=zeros(num); %创造滤波窗口
num1=(num-1)/2;
num2=(num+1)/2;
for w=num2:m-num1
for l=num2:n-num1
for i=-1*num1:num1
for j=-1*num1:num1
a(num2+i,num2+j)=f(w+i,l+j); %取点
end
end
a2=reshape(a,num^2,1); %排成一列,方便排序
a3=sort(a2); %排序
fmed(w,l)=a3((num^2+1)/2); %赋中值
end
end
end
elseif mode==4||mode==7||mode==8
if mode==4 %十字形(9个点)
for w=3:m-2
for l=3:n-2
a(1)=f(w-2,l); %取点
a(2)=f(w-1,l);
a(3)=f(w,l-2);
a(4)=f(w,l-1);
a(5)=f(w,l);
a(6)=f(w,l+1);
a(7)=f(w,l+2);
a(8)=f(w+1,l);
a(9)=f(w+2,l);
a=sort(a); %对a排序
fmed(w,l)=a(5); %赋中值
end
end
elseif mode==7 %菱形
for w=3:m-2
for l=3:n-2
a(1)=f(w-2,l); %取点
a(2)=f(w-1,l-1);
a(3)=f(w-1,l);
a(4)=f(w-1,l+1);
a(5)=f(w,l-2);
a(6)=f(w,l-1);
a(7)=f(w,l);
a(8)=f(w,l+1);
a(9)=f(w,l+2);
a(10)=f(w+1,l-1);
a(11)=f(w+1,l);
a(12)=f(w+1,l+1);
a(13)=f(w+2,l);
a=sort(a); %对a排序
fmed(w,l)=a(7); %赋中值
end
end
else %圆形
for w=3:m-2
for l=3:n-2
a(1)=f(w-2,l-1); %取点
a(2)=f(w-2,l);
a(3)=f(w-2,l+1);
a(4)=f(w-1,l-2);
a(5)=f(w-1,l-1);
a(6)=f(w-1,l);
a(7)=f(w-1,l+1);
a(8)=f(w-1,l+2);
a(9)=f(w,l-2);
a(10)=f(w,l-1);
a(11)=f(w,l);
a(12)=f(w,l+1);
a(13)=f(w,l+2);
a(14)=f(w+1,l-2);
a(15)=f(w+1,l-1);
a(16)=f(w+1,l);
a(17)=f(w+1,l+1);
a(18)=f(w+1,l+2);
a(19)=f(w+2,l-1);
a(20)=f(w+2,l);
a(21)=f(w+2,l+1);
a=sort(a); %对a排序
fmed(w,l)=a(11); %赋中值
end
end
end
end
%处理边缘
for i=1:2 %处理第1、2行、倒数第1、第2行的第3列到倒数第三列的边缘像素点
for j=3:n-2
fmed(i,j)=fmed(3,j);
fmed(m+1-i,j)=fmed(m-2,j);
end
end
for j=1:2 %处理第1、2列、倒数第1、第2列的第3行到倒数第三行的边缘像素点
for i=3:m-2
fmed(i,j)=fmed(i,3);
fmed(i,n+1-j)=fmed(i,n-2);
end
end
%处理四个顶角
fmed(1,1)=fmed(3,3);fmed(1,2)=fmed(3,3);fmed(2,1)=fmed(3,3);fmed(2,2)=fmed(3,3);
fmed(1,n)=fmed(3,n-2);fmed(1,n-1)=fmed(3,n-2);fmed(2,n)=fmed(3,n-2);fmed(2,n-1)=fmed(3,n-2);
fmed(m,1)=fmed(m-2,3);fmed(m-1,1)=fmed(m-2,3);fmed(m,2)=fmed(m-2,3);fmed(m-1,2)=fmed(m-2,3);
fmed(m,n)=fmed(m-2,n-2);fmed(m-1,n)=fmed(m-2,n-2);fmed(m,n-1)=fmed(m-2,n-2);fmed(m-1,n-1)=fmed(m-2,n-2);
end
如果觉得有用的话,能否点个赞呢?