2019-10-13 23:28:44 qq_40573632 阅读数 77

空域低通滤波

       将空间域模板用于图像处理,通常称为空间滤波,而空间域模板称为空间滤波器。

       空间域滤波按线性和非线性特点有:线性、非线性平滑滤波器线性滤波在消除图像噪声的同时也会模糊图像的细节,利用非线性平滑滤波可在消除图像中噪声的同时较好的保持图像的细节。

       线性平滑滤波器包括邻近域平均法非线性平滑滤波器中值滤波器

       平滑滤波:平滑滤波能减弱或消除图像中高频率的分量,但不影响低频率的分量。因为高频分量对应图像中的区域边缘等灰度值具有较大、变化较快的部分,平滑滤波将这个分量滤除可以减少局部灰度的起伏,使图像变得平滑。经常用于模糊处理和减小噪声。

  1. 邻域平均法

       邻域平均法的思想是用像素及其指定邻域内像素的平均值或加权平均值作为该像素的新值,以便去除突变的像素点,从而滤除一定的噪声。邻域平均法的数学含义可用下式表示: 

                                             

式中:x,y =0,1,2,…,N-1;S为(x,y)点邻域中到的坐标集合,但其中不包括(x,y)点;M为集合坐标点的总数。

邻域平均法中常用的模板是(线性平滑滤波所用的卷积模板均为正值):

                                                       

邻域平均处理方法是以图像模糊为代价来减小噪声的,且模板尺寸越大,噪声减小的效果越显著,灰度突变的边缘图像更模糊。

  1. 中值滤波器

中值滤波的算法原理是,首先确定一个奇数像素的窗口W,窗口内各像素按灰度大小排队后,用其中间位置的灰度值代替原f(x,y)灰度值成为窗口中心的灰度值g(x,y)。数学含义可用下式表示:

                           

       式中:W为选定窗口大小,f(m-i,n-j)为窗口W的像素灰度值。通常窗内像素为奇数,以便于有中间像素。若窗内像素为偶数时,则中值取中间两像素灰度值的平均值。

   给选定的图像加上椒盐噪声、高斯噪声

P=rgb2gray(imread('E:\文本文件\作业\数字图像处理与分析\camema.jpg'));
noise_bl=imnoise(P,'salt & pepper',0.1); %添加椒盐噪声
noise_gs=imnoise(P,'gaussian');          %添加高斯噪声
subplot(131),imshow(P),title('原图');                %一行三列第一个显示原图
subplot(132),imshow(noise_bl),title('添加椒盐噪声');  %一行三列第二个显示添加椒盐噪声图像
subplot(133),imshow(noise_gs),title('添加高斯噪声');  %一行三列第三个显示添加高斯噪声图像

  运行结果如下:

1 邻域平均法

  • 用P=imread('E:\文本文件\作业\数字图像处理与分析\camema.jpg')读取图像转化为二维矩阵;
  • 用noise_jy=imnoise(P,’salt & pepper’,0.1);得到椒盐噪声图像
  • 用noise_gs=imnoise(P,’gaussian’);得到高斯噪声图像
  • 用 h1=fspecial(‘average’)  得到默认的h为3x3的邻域平均模板
  • 用 h2=fspecial(‘average’,7])得到h为7x7的邻域平均模板。
  • P1=imfilter(P,h1) 进行3x3模板的平滑处理
  • P2=imfilter(P,h2) 进行7x7模板的平滑处理
  • 相同函数对椒盐噪声图片和高斯噪声图片进行平滑处理
  • 显示原图和处理后的图片

    代码如下:

clear;close all;clc;
P=rgb2gray(imread('E:\\作业\数字图像处理与分析\图片\camema.jpg'));  %读取图像并转为灰色图像
noise_jy=imnoise(P,'salt & pepper',0.1); %添加椒盐噪声 
noise_gs=imnoise(P,'gaussian');          %添加高斯噪声 
h1=fspecial('average');          % 产生3x3的默认均值模板
h2=fspecial('average',7);        % 产生7x7的均值模板
P1=imfilter(P,h1);               %进行3*3模板的均值滤波处理
P2=imfilter(P,h2);               %进行7*7模板的均值滤波处理
B1=imfilter(noise_jy,h1);        %3x3模板均值滤波处理椒盐噪声图片
B2=imfilter(noise_gs,h1);        %3x3模板均值滤波处理高斯噪声图片
subplot(3,3,1),imshow(P),title('原图');
subplot(3,3,2),imshow(noise_jy),title('添加椒盐噪声');
subplot(3,3,3),imshow(noise_gs),title('添加高斯噪声');
subplot(3,3,4);imshow(P1);title('3*3 均值滤波处理原图后的图像 ');
subplot(3,3,5);imshow(B1);title('3*3 均值滤波处理椒盐噪声图片后的图像 ');
subplot(3,3,6);imshow(B2);title('3*3 均值滤波处理高斯噪声图片后的图像 ');
subplot(3,3,7);imshow(P2);title('7*7 均值滤波处理原图后的图像 ');

  运行结果如下:

 

原  图

添加椒盐噪声图

添加高斯噪声图

3*3均值处理椒盐噪声图

3*3均值处理高斯噪声图

3*3均值处理原图

7*7均值处理原图

2 )中值滤波

  中值滤波的基本步骤是:

(1)将模板在图中漫游,并将模板中心与图中某个像素位置重合;

(2)读取模板下各对应像素的灰度值;

(3)将这些灰度值从小到大排成一列;

(4)找出这些灰度值里排在中间的一个;

(5)将这个中间值赋给对应模板中心位置的像素。

 

        选定了一幅二维图像,分别加入椒盐噪声和高斯噪声,均是期望为 0 ,椒盐噪声方差为 0.1 。然后利用中值滤波法进行滤波去噪。 Matlab 自带了中值滤波的函数,因此较为便捷。

①用P=imread(图片位置’)与读取图像;

②用noise_jy=imnoise(P,’salt & pepper’,0.1);得到椒盐噪声图像

③用noise_gs=imnoise(P,’gaussian’);得到高斯噪声图像

④用 h1= medfilt2(noise_jy,[5,5] ); 对有椒盐噪声图像进行5×5方形窗口中值滤波

⑤相同函数对高斯噪声图片进行平滑处理

⑥显示原图和处理后的图片 

    代码如下:

clear;close all;clc;
P=rgb2gray(imread('E:\文本文件\作业\数字图像处理与分析\图片\camema.jpg'));
noise_jy=imnoise(P,'salt & pepper',0.1);   %添加椒盐噪声 
noise_gs=imnoise(P,'gaussian');            %添加高斯噪声 
h1= medfilt2(noise_jy,[5,5] );     %对有椒盐噪声图像进行5×5方形窗口中值滤波
h2= medfilt2(noise_gs,[5,5] );     %对有高斯噪声图像进行5×5方形窗口中值滤波
subplot(2,3,1),imshow(P),title('原图');
subplot(2,3,2),imshow(noise_jy),title('添加椒盐噪声');
subplot(2,3,3),imshow(noise_gs),title('添加高斯噪声');
subplot(2,3,5);imshow(h1);title('中值滤波处理椒盐噪声图片后的图像 ');
subplot(2,3,6);imshow(h2);title('中值滤波处理高斯噪声图片后的图像 ');

  运行结果如下:

           原图

         添加椒盐噪声图

        添加高斯噪声图

      中值滤波处理椒盐噪声图

     中值滤波处理高斯噪声图

比较处理后的图像结果可知:

(1)邻域平均法的平滑效果与所采用邻域的编辑有关,模板尺寸越大,则图像的模糊程度越大;此时消除噪声的效果也将增强,但同时所得到的图像将变得更模糊;

(2)加入椒盐噪声的图呈现出随机分布的黑白斑点,用均值滤波后,噪声并未消除多少,且图片反而变得更加模糊了,而经过中值滤波器之后噪声不但得到了有效的消除,同时图片也并没怎么模糊。

 

 

2014-10-10 15:44:28 u012596983 阅读数 2534
空域滤波的概念和分类
使用空域模板进行的图像处理,被称为空域滤波。模板本身被称为空域滤波器。
空域滤波的机理就是在待处理的图像中逐点地移动模板,滤波器在该点地响应通过事先定义的滤波器系数与滤波模板扫过区域的相应像素值的关系来计算。
空域滤波可以按照以下关系进行分类:
  ⑴ 从数学形态上可以把空域滤波器分为线性滤波器和非线性滤波器:
  线性滤波器是线性系统和频域滤波概念在空域的自然延伸。其特征是结果像素值的计算由下列公式定义:
  R = w1z1 + w2z2 + … + wnzn
  其中:wi   i = 1,2, … ,n 是模板的系数
             zi   i = 1,2, … ,n 是被计算像素及其邻域像素的值
线性滤波器又可以分为高通,低通和带通滤波器。
非线性滤波器使用模板进行结果像素值的计算,结果值直接取决于像素邻域的值,而不与线性乘积和无关
,它包括中值滤波,最大最小值滤波器等等。
  ⑵ 从处理效果上可以把空域滤波器分为平滑空间滤波器和锐化空间滤波器:
   平滑空间滤波器用于模糊处理和减小噪声,经常在图像的预处理中使用
   锐化空间滤波器主要用于突出图像中的细节或者增强被模糊了的细节
下面逐一介绍几种比较典型的空域滤波器:

一:均值滤波

最简单的空预处理方法,属于线性滤波器,其基本思想是利用几个像素灰度的平均值代替每个像素的灰度,均值滤波的平滑效果与所使用的领域半径有关。半径

越大,平滑图像的模糊程度越大。均值滤波的优点在于算法简单,计算速度快,主要缺点是在降低噪声的同时使图像产生模糊,特别是在边缘和细节处,领域越大越模糊。

H=fspecial('averager',n);
Y=filter2(B,H);
其中n为邻域大小,B为待滤波的二维灰度图像矩阵,H为所构造的均值滤波器。

二:加权均值滤波

为了克服简单局部平均的弊端,目前已经研究出许多保留边缘细节的局部平滑算法,他们讨论的重点都在如何选择领域的大小,形状和方向,如何选择参加平均的点数以及

邻域个点的权重系数等。把这类根据参与平均像素的特点赋予不同权值的方法称为加权均值滤波,常用的灰度最近K个邻域点平均法,梯度倒数加权平滑,最大均匀性平滑、小斜面模型平滑滤波等。

matlab代码如下:

H=[1 2 1;2 4 2;1 2 1];
H1=1/16*H;
I=imread('lena.png');
I1=imnoise(I,'salt & pepper',0.02);
J=imfilter(I1,H1);
subplot(121),imshow(I1);
subplot(122),imshow(J);
三:中值滤波

如果既要消除噪声又要保持图像细节,可以使用中值滤波。中值滤波器是一种非线性平滑滤波器。它的主要功能是让与周围像素灰度值的差比较大的像素改变,并取与周围像素相近的值,从而消除孤立的噪声点。

clear
A=imread('lena.png');
A=imnoise(A, 'salt & pepper',0.04);
subplot(1,2,1)
imshow(A)
title('添加噪声后的图像');
A=rgb2gray(A);
image=double(A);
[m,n]=size(A);
u=zeros(1,9);
for i=2:m-1
    for j=2:n-1
        u(1)=image(i,j);
        u(2)=image(i,j+1);
        u(3)=image(i-1,j+1);
        u(4)=image(i-1,j);
        u(5)=image(i-1,j-1);
        u(6)=image(i,j-1);
        u(7)=image(i+1,j-1);
        u(8)=image(i+1,j);
        u(9)=image(i+1,j+1);
        for p=1:8
            for q=1:8-p
                if u(p)>u(q+1)
                    k=u(q);u(q)=u(q+1);u(q+1)=k;
                end
            end
        end
        rimage(i,j)=u(5);
    end
end
subplot(1,2,2)
rimage=uint8(rimage);
imshow(rimage);
title('中值滤波后的图像')

效果图如下:



四:双边滤波器

待续。。。



2018-11-23 14:37:20 shanwenkang 阅读数 530

信号处理

我们在信号处理课程中学过一维信号的处理,其中有个很重要的概念就是卷积。在时域上来看,x是我们的原信号,h是冲激响应,x*h代表x与h卷积,也就是将h翻转平移,与x对应元素相乘相加以后就能得到输出信号;在频域上来看就是x的频谱与y的频谱相乘可以得到y的频谱,再经过傅里叶反变换就能得到输出信号y

在图像处理中,与时域对应的叫做空域,与一维卷积类似的是二维卷积也是翻转、平移、相乘相加这一系列的操作,但是不同的是本来一维的向量变成了二维的矩阵。而对于某幅特定的图像来说,它永远是有限长的,这就意味着冲激响应h矩阵平移到边缘的时候可能会出现有值与无值相乘,这种情况我们可以人为地去定义它,我们可以将无值区域设为0,这样可以保证输出图像维度与输入图像维度相同,但是边缘会失真;我们还可以直接抛弃有值与无值相乘的情况,这样不会产生失真的结果,但是会导致图像的维度缩减

与一维相同的是我们可以定义二维的卷积,这种定义方法看起来像是卷积,但是实际上它更像是相关操作,唯一的差别就是正负号。事实上我们很多时候不会关心正负号,因为我们的滤波器很多时候是中心对称的,因此翻转操作对其没有影响。

 

空域滤波器

平滑滤波器

我们在之前的博客也讲过平滑滤波器,平滑滤波器实际上就是一个低通滤波器,它用来消除高斯噪声(在原本像素值上增加随机噪声,噪声值分布满足高斯分布)有很好的效果。我们需要注意的是在设计滤波器的时候应该使得矩阵系数之和为1以保证输出图像的亮度大致与输入图像相同

除了以上所有九个点权重相等的滤波器外我们还可以设计权重不同的滤波器来满足不同的需求

下面让我们来看看两个matlab中相关的重要函数,一个是filter2,这种方法得到的结果是浮点型;另一个是imfilter函数,这种方法输入与输出图像都是uint8类型的,并且无法保留小于0或大于255的值,但一个好处就是这个函数也可以对彩色图像进行操作

锐化滤波器

与平滑滤波器相对应的就是锐化滤波器,锐化滤波器实际上就是增强相邻像素值之间的差值来提高对比度。这种操作与差分相关。我们先来看一维图像的差分结果,我们可以看出来一次差分(一阶导)可以显示图像的边缘,即像素值产生变化;而二次差分(二阶导)可以显示边缘符号的变化,即边缘的开始点与结束点,我们会将重点主要放在二阶导上

那么将其推导到二维呢?我们采用拉普拉斯算子来衡量横向与纵向的变化,像素值对x与y的二阶偏导都可由一维的情况得到

最后我们得到的矩阵实际上是一个边缘检测器,因为我们就检出了图像的边缘,而还未对边缘两边进行增强操作。我们可以看到图像的大部分是黑色,因为对于颜色没有太大变化的区域,计算出来的像素值大约在0左右,而在边缘处;即相邻像素值相差较大的位置,总有一侧的值较大,这个值乘以-4后会变成很小的负值,而另一侧的值较小,乘以-4后再加上上下左右四个像素的值会是一个很大的正值。我们在用 imshow(im,[]) 函数将像素值压缩到0-255这个区间,因此负值会变为0(黑色),正值会变为255(白色),0变为处于0-255之间的灰色。

那么我们有了图像的边缘以后其实图像的锐化也很容易完成了,由于在图像边缘处一侧是极大值,一侧是极小值,那我们就可以将原图像加上图像的边缘,使得原来像素值大的一侧值更大,像素值小的一侧值更小。边缘检测器实际上是一个高通滤波器,它由全通滤波器减去低通滤波器得到,而锐化滤波器就是在全通滤波器基础上加上一个高通滤波器得到。

我们应用了锐化滤波器后,物体的对比度更大,相应的噪声的对比度也会变得更大,因此我们可以只加上部分图像的边缘来在二者之间达到一个平衡,这种方法叫做非锐化掩蔽。F矩阵的系数只在中央处为1,其他地方为0;高通滤波器各元素之和为零。这样就保证了F加上Fhp的一部分后矩阵各系数之和任然为1,这就意味着像素值的亮度基本不变

SOBEL水平/竖直边缘检测

我们在之前的博客也讲过能够用作特定方向的边缘检测器

中值滤波器

不是所有滤波器都是线性的,中值滤波器就是取一个像素周围一定范围内的像素值,然后取中值作为这个像素的值。这种滤波器用来滤除椒盐噪声(即图像中偶然出现的值为0或255的像素点)有很好的效果。在matlab中可以采用medfilter2这个函数来实现

 

 

 

2015-05-02 11:17:41 fztfztfzt 阅读数 3984
图像的真强即为图像的滤波,分为空间滤波和频域滤波
空间滤波可分为线性滤波和非线性滤波
空域滤波算法在进行高通或低通滤波时,采用的手法都是一样的,即小区域模版卷积

1.线性平滑滤波器:
用3*3模版中心与待处理图像的每个像素点重合,将模版各值与其下像素点相乘,几种典型模版:
{0,1,0,
1,1,1,
0,1,0,
4,3
},
{
1,1,1,
1,0,1,
1,1,1,
8,3
},
{
1,1,1,
1,1,1,
1,1,1,
9,3
},
{
1,1,1,
1,2,1,
1,1,1,
10,3
},
{/////////////////高斯滤波模版
1,2,1,
2,4,2,
1,2,1,
16,3
  1. /*************************************************************************
  2. *
  3. * 函数名称:
  4. * KernelFilter()
  5. *
  6. * 参数:
  7. * BYTE* bmp,LONG width,LONG height ------图像参数
  8. KERNEL kernel ---------模版
  9. *
  10. * 返回值:
  11. * BOOL - 成功返回TRUE,否则返回FALSE。
  12. *
  13. * 说明:
  14. * 该函数对图象进行二维快速沃尔什——哈达马变换。
  15. *
  16. ************************************************************************/
  17. voidKernelFilter(BYTE *bmp,LONG width,LONG height,KERNEL kernel);
  18. /*************************************************************************
  19. *
  20. * 函数名称:
  21. * BmpFilter()
  22. *
  23. * 参数:
  24. * BYTE *srcBmp --------原图像
  25. BYTE *desBmp --------转换后图像
  26. LONG width,LONG height ------图像参数
  27. *
  28. * 返回值:
  29. * BOOL - 成功返回TRUE,否则返回FALSE。
  30. *
  31. * 说明:
  32. * 该函数将原图像转换为由1填充的图像,方便进行模版滤波。
  33. *
  34. ************************************************************************/
  35. voidBmpFilter(BYTE *desBmp,BYTE *srcBmp,LONG width,LONG height);
  36. voidMyProcess::BmpFilter(BYTE *desBmp,BYTE *srcBmp,LONG width,LONG height)
  37. {
  38. LONG i,j;
  39. memset(desBmp,0,(width+6)*(height+2));
  40. for(i=0;i<height;i++)
  41. for(j=0;j<width;j++)
  42. {
  43. desBmp[(i+1)*(width+6)+j+3]=srcBmp[i*width+j];
  44. }
  45. }
  46. voidMyProcess::KernelFilter(BYTE *bmp,LONG width,LONG height,KERNEL kernel)
  47. {
  48. LONG i,j;
  49. //申请一个临时空间,由1包围bmp图像,方便进行模版处理
  50. BYTE *temp_bmp =new BYTE[(width+6)*(height+2)];
  51. BmpFilter(temp_bmp,bmp,width,height);
  52. //模版滤波
  53. for(i=1;i<height+1;i++)
  54. for(j=3;j<width+3;j++)
  55. {
  56. LONG k,m,temp=0;
  57. for(k=-1;k<kernel.Dimention-1;k++)
  58. for(m=-1;m<kernel.Dimention-1;m++)
  59. {
  60. int a = temp_bmp[(i+k)*(width+6)+j+m*3];
  61. int b = kernel.Element[k+1][m+1];
  62. temp+=a*b;
  63. }
  64. temp/=kernel.Divisor;
  65. //////////////////////////////////////////////////////////////////////////            //此处注意,不应将值给待处理对象,而应传给未处理的原图像
  66. // temp_bmp[i*(width+6)+j] = (BYTE)temp;
  67. bmp[(i-1)*width+j-3]= temp;
  68. }
  69. delete[] temp_bmp;
  70. }

线性锐化滤波器:
锐化即使模糊图像变清晰,可用原始图像经放大A倍后,减去低通图像得到,对于这种模版,中心元素为9A-1,系数和为0.例:
-1 -1 -1        -2 -2 -2
-1  8 -1        -2 16 -2
-1 -1 -1        -2 -2 -2
前一种为拉普拉斯算子,可直接调用模版滤波函数

中值滤波:
中值滤波可以在一定程度上克服模糊图像细节的缺点,尤其对脉冲噪声,扫描噪声有较好效果,但图像细节过多时效果不好
把领域像素按灰度级进行排序,取中间值。
  1. /*************************************************************************
  2. *
  3. * 函数名称:
  4. * MedianFilter()
  5. *
  6. * 参数:
  7. * BYTE* bmp,LONG width,LONG height ------图像参数
  8. *
  9. * 返回值:
  10. * BOOL - 成功返回TRUE,否则返回FALSE。
  11. *
  12. * 说明:
  13. * 该函数对图象进行中值滤波。
  14. *
  15. ************************************************************************/
  16. voidMedianFilter(BYTE *bmp,LONG width,LONG height);
  1. voidMyProcess::MedianFilter(BYTE *bmp,LONG width,LONG height)
  2. {
  3. LONG i,j;
  4. //申请一个临时空间,由1包围bmp图像,方便进行模版处理
  5. BYTE *temp_bmp =new BYTE[(width+6)*(height+2)];
  6. BmpFilter(temp_bmp,bmp,width,height);
  7. //中值滤波
  8. //待排序值
  9. int value[9];
  10. for(i=1;i<height+1;i++)
  11. for(j=3;j<width+3;j++)
  12. {
  13. LONG k,m,temp=0;
  14. for(k=-1;k<2;k++)
  15. for(m=-1;m<2;m++)
  16. {
  17. value[(k+1)*3+(m+1)]= temp_bmp[(i+k)*(width+6)+j+m*3];
  18. }
  19. sort(value,value+9);
  20. //////////////////////////////////////////////////////////////////////////
  21. //此处注意,不应将值给待处理对象,而应传给未处理的原图像
  22. // temp_bmp[i*(width+6)+j] = (BYTE)temp;
  23. bmp[(i-1)*width+j-3]= value[4];
  24. }
  25. delete[] temp_bmp;
  26. }
还有一种与之类似的排序统计滤波器----百分比滤波器,先对模版下的元素进行排序,再按某个确定的百分比选取序列中相应的像素值作为模版输出。

非线性锐化滤波器:
图像的模糊是由于平均或积分运算而产生的,因此通过积分的逆运算可以达到去除模糊,增强边界的目的。

浮雕滤波特效:
浮雕特效是将图像一侧值减去另一侧的值,代替原值,以使边缘(颜色变化大的地方)突出,例如:
-1 0 0    1 0 0,取图像左上角与右下角的差值,还有如:
0 0 0    0 0 0
0 0 1    0 0 -1
  1. //////浮雕效果模版 下标7到13
  2. {-1,0,0,
  3. 0,0,0,
  4. 0,0,1,
  5. 1,3
  6. },
  7. {1,0,0,
  8. 0,0,0,
  9. 0,0,-1,
  10. 1,3
  11. },
  12. {0,0,-1,
  13. 0,0,0,
  14. 1,0,0,
  15. 1,3
  16. },
  17. {0,0,1,
  18. 0,0,0,
  19. -1,0,0,
  20. 1,3
  21. },
  22. {-1,0,-1,
  23. 0,0,0,
  24. 1,0,1,
  25. 1,3
  26. },
  27. {-1,0,1,
  28. 0,0,0,
  29. 1,0,-1,
  30. 1,3
  31. },
  32. {1,0,1,
  33. 0,0,0,
  34. -1,0,-1,
  35. 1,3
  36. },
  37. {1,0,-1,
  38. 0,0,0,
  39. -1,0,1,
  40. 1,3
  41. }
可利用模版滤波代码,更改一些条件:
增加type,用以判断是否是浮雕处理,浮雕处理的话,kernel除以的系数应为1,且计算后的temp应+128以增强视觉效果,否则非边缘部分会因为颜色值相近而减过后为很小的值,而显示黑色。另外还要使temp在(0,255)内,防止超出。
  1. voidMyProcess::KernelFilter(BYTE *bmp,LONG width,LONG height,KERNEL kernel,int type)
  2. {
  3. LONG i,j;
  4. //申请一个临时空间,由1包围bmp图像,方便进行模版处理
  5. BYTE *temp_bmp =new BYTE[(width+6)*(height+2)];
  6. BmpFilter(temp_bmp,bmp,width,height);
  7. //模版滤波
  8. for(i=1;i<height+1;i++)
  9. for(j=3;j<width+3;j++)
  10. {
  11. LONG k,m,temp=0;
  12. for(k=-1;k<kernel.Dimention-1;k++)
  13. for(m=-1;m<kernel.Dimention-1;m++)
  14. {
  15. int a = temp_bmp[(i+k)*(width+6)+j+m*3];
  16. int b = kernel.Element[k+1][m+1];
  17. temp+=a*b;
  18. }
  19. temp/=kernel.Divisor;
  20. //////////////////////////////////////////////////////////////////////////
  21. //此处注意,不应将值给待处理对象,而应传给未处理的原图像
  22. // temp_bmp[i*(width+6)+j] = (BYTE)temp;
  23. if(type==1)
  24. {
  25. temp = max(0,min(temp+128,255));
  26. }
  27. bmp[(i-1)*width+j-3]= temp;
  28. }
  29. delete[] temp_bmp;
  30. }
频域滤波:
空域的模版运算即是空域的卷积运算的简单实现,而空域的卷积运算等于频域的乘法运算。处理后的频域图像G=F*H
F为源图像的频域值,H为转移函数。由H的不同,可将频域的处理方法分为低通滤波,高通滤波以及带通,带阻滤波等等

2019-01-15 13:30:53 freehawkzk 阅读数 221

【图像处理】-015 空域滤波处理-高斯滤波

  在讨论频域滤波时,我们讨论了高斯低通滤波器、高斯高通滤波器等,这里,我们将对空域中的高斯滤波器进行讨论。

1 理论依据

1.1 空间域中的高斯滤波器

  高斯低通滤波器(GLPF)的数学表达式如下:
(1)H(u,v)=1eD2(u,v)/2σ2 H(u,v)=1-e^{-D^{2}(u,v)/2\sigma ^2} \tag{1}
通常讨论时,可以去截止频率D0D_0,表示形式如下:
(2)H(u,v)=1eD2(u,v)/2D02 H(u,v)=1-e^{-D^{2}(u,v)/2D_0^2} \tag{2}

2 实现

#include "../include/importOpenCV.h"
#include "../include/baseOps.h"
#include "../include/opencv400/opencv2/core.hpp"
#include <iostream>



int main()
{
	//将工作目录设置到EXE所在的目录。
	SetCurrentDirectoryToExePath();

	cv::Mat src = cv::imread("../images/71.jpg");
	cv::imshow("原图", src);

	cv::Mat gaussianFilter2;
	SGLPFParam param;
	param.r = 8;
	param.sz = cv::Size(3, 3);
	CreateGaussianLowpassFilter(param, gaussianFilter2);
	std::vector<cv::Mat> w;
	cv::split(gaussianFilter2, w);
	cv::Scalar ssum = cv::sum(w[0]);
	w[0] = w[0] / ssum.val[0];
	cv::Mat& w1 = w[0];
	cv::Mat output;
	src.copyTo(output);
	if (src.channels() == 3)
	{
		std::vector<cv::Mat> srcbgr;
		cv::split(src, srcbgr);
		std::vector<cv::Mat> dstbgr;
		cv::split(output, dstbgr);

		for (int i = 1; i < srcbgr[0].rows-1; i ++)
		{
			for (int j = 1; j < srcbgr[0].cols-1; j++)
			{
				dstbgr[0].at<uchar>(i, j) = (uchar)(srcbgr[0].at<uchar>(i - 1, j - 1)*w1.at<float>(0, 0) + srcbgr[0].at<uchar>(i - 1, j)*w1.at<float>(0, 1) + srcbgr[0].at<uchar>(i - 1, j + 1)*w1.at<float>(0, 2) + \
					                                srcbgr[0].at<uchar>(i    , j - 1)*w1.at<float>(1, 0) + srcbgr[0].at<uchar>(i    , j)*w1.at<float>(1, 1) + srcbgr[0].at<uchar>(i    , j + 1)*w1.at<float>(1, 2) + \
					                                srcbgr[0].at<uchar>(i + 1, j - 1)*w1.at<float>(2, 0) + srcbgr[0].at<uchar>(i + 1, j)*w1.at<float>(2, 1) + srcbgr[0].at<uchar>(i + 1, j + 1)*w1.at<float>(2, 2));

				dstbgr[1].at<uchar>(i, j) = (uchar)(srcbgr[1].at<uchar>(i - 1, j - 1)*w1.at<float>(0, 0) + srcbgr[1].at<uchar>(i - 1, j)*w1.at<float>(0, 1) + srcbgr[1].at<uchar>(i - 1, j + 1)*w1.at<float>(0, 2) + \
					                                srcbgr[1].at<uchar>(i    , j - 1)*w1.at<float>(1, 0) + srcbgr[1].at<uchar>(i    , j)*w1.at<float>(1, 1) + srcbgr[1].at<uchar>(i    , j + 1)*w1.at<float>(1, 2) + \
					                                srcbgr[1].at<uchar>(i + 1, j - 1)*w1.at<float>(2, 0) + srcbgr[1].at<uchar>(i + 1, j)*w1.at<float>(2, 1) + srcbgr[1].at<uchar>(i + 1, j + 1)*w1.at<float>(2, 2));
				
				dstbgr[2].at<uchar>(i, j) = (uchar)(srcbgr[2].at<uchar>(i - 1, j - 1)*w1.at<float>(0, 0) + srcbgr[2].at<uchar>(i - 1, j)*w1.at<float>(0, 1) + srcbgr[2].at<uchar>(i - 1, j + 1)*w1.at<float>(0, 2) + \
					                                srcbgr[2].at<uchar>(i    , j - 1)*w1.at<float>(1, 0) + srcbgr[2].at<uchar>(i    , j)*w1.at<float>(1, 1) + srcbgr[2].at<uchar>(i    , j + 1)*w1.at<float>(1, 2) + \
					                                srcbgr[2].at<uchar>(i + 1, j - 1)*w1.at<float>(2, 0) + srcbgr[2].at<uchar>(i + 1, j)*w1.at<float>(2, 1) + srcbgr[2].at<uchar>(i + 1, j + 1)*w1.at<float>(2, 2));
			}
		}

		cv::merge(dstbgr, output);
		cv::imshow("高斯滤波3*3_手动计算", output);
		cv::Mat dst1;
		cv::GaussianBlur(src, dst1, cv::Size(3, 3),8);
		cv::imshow("高斯滤波3*3_cv::blur", dst1);
		cv::GaussianBlur(src, dst1, cv::Size(5, 5),8);
		cv::imshow("高斯滤波5*5_cv::blur", dst1);
		cv::GaussianBlur(src, dst1, cv::Size(7, 7), 8);
		cv::imshow("高斯滤波7*7_cv::blur", dst1);
		cv::GaussianBlur(src, dst1, cv::Size(9, 9), 8);
		cv::imshow("高斯滤波9*9_cv::blur", dst1);
	}
	else
	{

		for (int i = 1; i < src.rows - 1; i++)
		{
			for (int j = 1; j < src.cols - 1; j++)
			{
				output.at<uchar>(i, j) = (uchar)(src.at<uchar>(i - 1, j - 1)*w1.at<float>(0, 0) + src.at<uchar>(i - 1, j)*w1.at<float>(0, 1) + src.at<uchar>(i - 1, j + 1)*w1.at<float>(0, 2) + \
					                             src.at<uchar>(i    , j - 1)*w1.at<float>(1, 0) + src.at<uchar>(i    , j)*w1.at<float>(1, 1) + src.at<uchar>(i    , j + 1)*w1.at<float>(1, 2) + \
					                             src.at<uchar>(i + 1, j - 1)*w1.at<float>(2, 0) + src.at<uchar>(i + 1, j)*w1.at<float>(2, 1) + src.at<uchar>(i + 1, j + 1)*w1.at<float>(2, 2));
			}
		}

		cv::Mat dst1;
		cv::GaussianBlur(src, dst1, cv::Size(3, 3), 8);
		cv::imshow("高斯滤波3*3_手动计算", output);
		cv::imshow("高斯滤波3*3_cv::blur", dst1);
	}

	cv::waitKey();
	return 0;
}

3 讨论

  在OpenCV中,高斯滤波通过GaussianBlur函数来实现。高斯模糊的效果受高斯滤波器的尺寸和方差控制。

3.1 不同尺寸,相同方差

高斯滤波-不同尺寸,相同方差可以看出,在方差相同时,随着滤波器尺寸的增加,图像的模糊效果逐渐加重。

3.2 相同尺寸,不同方差

在这里插入图片描述
可以看出,在滤波器尺寸相同时,方差逐渐增加,模糊效果会加强。

没有更多推荐了,返回首页