【转载】opencv 频域高通、低通滤波演示

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【转载】opencv 频域高通、低通滤波演示相关的知识,希望对你有一定的参考价值。

参考技术A https://www.oschina.net/code/snippet_1170370_32834

opencv 理想滤波、巴特沃兹滤波和高斯滤波的高通、低通滤波演示

    Filter Parameters 窗口: 滤波器参数窗口

        - d0: 滤波器大小 D0

        - flag: 滤波器类型

             0 - 理想滤波

             1 - 巴特沃兹滤波

             2 - 高斯滤波

        - n: 巴特沃兹滤波的阶数

        - lh: 低通滤波 or 高通滤波

    Filtered Image 窗口: 过滤后的图像和过滤器图像

#! /usr/bin/env python

#coding=utf-8

importcv2

importnumpy as np

'''

opencv 理想滤波、巴特沃兹滤波和高斯滤波的高通、低通滤波演示

    Filter Parameters 窗口: 滤波器参数窗口

        - d0: 滤波器大小 D0

        - flag: 滤波器类型

             0 - 理想滤波

             1 - 巴特沃兹滤波

             2 - 高斯滤波

        - n: 巴特沃兹滤波的阶数

        - lh: 低通滤波 or 高通滤波

    Filtered Image 窗口: 过滤后的图像和过滤器图像

'''

defcombine_images(images, axis=1):

    '''

    合并图像。

    @param images: 图像列表(图像成员的维数必须相同)

    @param axis: 合并方向。

        axis=0时,图像垂直合并;

        axis = 1 时, 图像水平合并。

    @return 合并后的图像

    '''

    ndim =images[0].ndim

    shapes =np.array([mat.shape format inimages])

    assertnp.all(map(lambdae: len(e)==ndim, shapes)), 'all images should be same ndim.'

    ifaxis ==0:# 垂直方向合并图像

        # 合并图像的 cols

        cols =np.max(shapes[:, 1])

        # 扩展各图像 cols大小,使得 cols一致

        copy_imgs =[cv2.copyMakeBorder(img, 0, 0, 0, cols-img.shape[1],

            cv2.BORDER_CONSTANT, (0,0,0))  forimg inimages]

        # 垂直方向合并

        returnnp.vstack(copy_imgs)

    else:# 水平方向合并图像

        # 合并图像的 rows

        rows =np.max(shapes[:, 0])

        # 扩展各图像rows大小,使得 rows一致

        copy_imgs =[cv2.copyMakeBorder(img, 0, rows-img.shape[0], 0, 0,

            cv2.BORDER_CONSTANT, (0,0,0))  forimg inimages]

        # 水平方向合并

        returnnp.hstack(copy_imgs)

deffft(img):

    '''对图像进行傅立叶变换,并返回换位后的频率矩阵'''

    assertimg.ndim==2, 'img should be gray.'

    rows, cols =img.shape[:2]

    # 计算最优尺寸

    nrows =cv2.getOptimalDFTSize(rows)

    ncols =cv2.getOptimalDFTSize(cols)

    # 根据新尺寸,建立新变换图像

    nimg =np.zeros((nrows, ncols))

    nimg[:rows,:cols] =img

    # 傅立叶变换

    fft_mat =cv2.dft(np.float32(nimg), flags=cv2.DFT_COMPLEX_OUTPUT)

    # 换位,低频部分移到中间,高频部分移到四周

    returnnp.fft.fftshift(fft_mat)

deffft_image(fft_mat):

    '''将频率矩阵转换为可视图像'''

    # log函数中加1,避免log(0)出现.

    log_mat=cv2.log(1+cv2.magnitude(fft_mat[:,:,0], fft_mat[:,:,1]))

    # 标准化到0~255之间

    cv2.normalize(log_mat, log_mat, 0, 255, cv2.NORM_MINMAX)

    returnnp.uint8(np.around(log_mat))

defifft(fft_mat):

    '''傅立叶反变换,返回反变换图像'''

    # 反换位,低频部分移到四周,高频部分移到中间

    f_ishift_mat =np.fft.ifftshift(fft_mat)

    # 傅立叶反变换

    img_back =cv2.idft(f_ishift_mat)

    # 将复数转换为幅度, sqrt(re^2 + im^2)

    img_back =cv2.magnitude(*cv2.split(img_back))

    # 标准化到0~255之间

    cv2.normalize(img_back, img_back, 0, 255, cv2.NORM_MINMAX)

    returnnp.uint8(np.around(img_back))

deffft_distances(m, n):

    '''

    计算m,n矩阵每一点距离中心的距离

    见《数字图像处理MATLAB版.冈萨雷斯》93页

    '''

    u =np.array([i ifi<=m/2elsem-i fori inrange(m)], dtype=np.float32)

    v =np.array([i ifi<=m/2elsem-i fori inrange(m)], dtype=np.float32)

    v.shape =n, 1

    # 每点距离矩阵左上角的距离

    ret =np.sqrt(u*u +v*v)

    # 每点距离矩阵中心的距离

    returnnp.fft.fftshift(ret)

deflpfilter(flag, rows, cols, d0, n):

    '''低通滤波器

    @param flag: 滤波器类型

        0 - 理想低通滤波

        1 - 巴特沃兹低通滤波

        2 - 高斯低通滤波

    @param rows: 被滤波的矩阵高度

    @param cols: 被滤波的矩阵宽度

    @param d0: 滤波器大小 D0

    @param n: 巴特沃兹低通滤波的阶数 

    @return 滤波器矩阵

    '''

    assertd0 > 0, 'd0 should be more than 0.'

    filter_mat =None

    #理想低通滤波

    ifflag ==0:

        filter_mat =np.zeros((rows, cols ,2), np.float32)

        cv2.circle(filter_mat, (rows/2, cols/2) , d0, (1,1,1), thickness=-1) 

    # 巴特沃兹低通滤波

    elifflag ==1:

        duv =fft_distances(*fft_mat.shape[:2])

        filter_mat =1/(1+np.power(duv/d0, 2*n))

        # fft_mat有2个通道,实部和虚部

        # fliter_mat 也需要2个通道

        filter_mat =cv2.merge((filter_mat, filter_mat))

    #高斯低通滤波

    else:

        duv =fft_distances(*fft_mat.shape[:2])

        filter_mat =np.exp(-(duv*duv) /(2*d0*d0))

        # fft_mat有2个通道,实部和虚部

        # fliter_mat 也需要2个通道

        filter_mat =cv2.merge((filter_mat, filter_mat))                 

    returnfilter_mat

defhpfilter(flag, rows, cols, d0, n):

    '''高通滤波器

    @param flag: 滤波器类型

        0 - 理想高通滤波

        1 - 巴特沃兹高通滤波

        2 - 高斯高通滤波

    @param rows: 被滤波的矩阵高度

    @param cols: 被滤波的矩阵宽度

    @param d0: 滤波器大小 D0

    @param n: 巴特沃兹高通滤波的阶数 

    @return 滤波器矩阵

    '''

    assertd0 > 0, 'd0 should be more than 0.'

    filter_mat =None

    #理想高通滤波

    ifflag ==0:

        filter_mat =np.ones((rows, cols ,2), np.float32)

        cv2.circle(filter_mat, (rows/2, cols/2) , d0, (0,0,0), thickness=-1) 

    # 巴特沃兹高通滤波

    elifflag ==1:

        duv =fft_distances(rows, cols)

        # duv有 0 值(中心距离中心为0), 为避免除以0,设中心为 0.000001

        duv[rows/2, cols/2] =0.000001

        filter_mat =1/(1+np.power(d0/duv, 2*n))

        # fft_mat有2个通道,实部和虚部

        # fliter_mat 也需要2个通道

        filter_mat =cv2.merge((filter_mat, filter_mat))

    #高斯高通滤波

    else:

        duv =fft_distances(*fft_mat.shape[:2])

        filter_mat =1-np.exp(-(duv*duv) /(2*d0*d0))

        # fft_mat有2个通道,实部和虚部

        # fliter_mat 也需要2个通道

        filter_mat =cv2.merge((filter_mat, filter_mat))                 

    returnfilter_mat

defdo_filter(_=None):

    '''滤波,并显示'''

    d0 =cv2.getTrackbarPos('d0', filter_win)

    flag =cv2.getTrackbarPos('flag', filter_win)

    n =cv2.getTrackbarPos('n', filter_win)

    lh =cv2.getTrackbarPos('lh', filter_win)

    # 滤波器

    filter_mat =None

    iflh ==0:

        filter_mat =lpfilter(flag, fft_mat.shape[0], fft_mat.shape[1], d0, n)

    else:

        filter_mat =hpfilter(flag, fft_mat.shape[0], fft_mat.shape[1], d0, n)

    # 进行滤波

    filtered_mat =filter_mat *fft_mat

    # 反变换

    img_back =ifft(filtered_mat)

    # 显示滤波后的图像和滤波器图像

    cv2.imshow(image_win, combine_images([img_back, fft_image(filter_mat)]))

if__name__ =='__main__':

    img =cv2.imread('images/Fig0515.jpg',0)

    rows, cols =img.shape[:2]

    # 滤波器窗口名称

    filter_win ='Filter Parameters'

    # 图像窗口名称

    image_win ='Filtered Image'

    cv2.namedWindow(filter_win)

    cv2.namedWindow(image_win)

    # 创建d0 tracker, d0为过滤器大小

    cv2.createTrackbar('d0', filter_win, 20, min(rows, cols)/4, do_filter)

    # 创建flag tracker,

    # flag=0时,为理想滤波

    # flag=1时,为巴特沃兹滤波

    # flag=2时,为高斯滤波

    cv2.createTrackbar('flag', filter_win, 0, 2, do_filter)

    # 创建n tracker

    # n 为巴特沃兹滤波的阶数

    cv2.createTrackbar('n', filter_win, 1, 5, do_filter)

    # 创建lh tracker

    # lh: 滤波器是低通还是高通, 0 为低通, 1为高通

    cv2.createTrackbar('lh', filter_win, 0, 1, do_filter)

    fft_mat =fft(img)

    do_filter()

    cv2.resizeWindow(filter_win, 512, 20)

    cv2.waitKey(0)

    cv2.destroyAllWindows()

2.  [图片]  低通图像和滤波器.jpg

3.  [图片]  滤波器参数.jpg

计算机视觉图像分割与特征提取——频域增强(低通滤波&高通滤波)

个人简介: 

> 📦个人主页:赵四司机
> 🏆学习方向:JAVA后端开发 
> ⏰往期文章:SpringBoot项目整合微信支付
> 🔔博主推荐网站:牛客网 刷题|面试|找工作神器
> 📣种一棵树最好的时间是十年前,其次是现在!
> 💖喜欢的话麻烦点点关注喔,你们的支持是我的最大动力。

前言:

通过这篇文章你将了解卷积理论与频域的联系,并且你还将学会频域增强的两个常用方法——低通滤波和高通滤波。

目录

一:实验原理

二:低通滤波

三:高通滤波

四:代码实战

1.实验内容

2.Butterworth低通滤波器

3.Butterworth高通滤波器

4.实验分析


一:实验原理

卷积理论是频域技术的基础。设函数f(x,y)与线性位不变算子h(x,y)的卷积结果是g(x,y),即

g(x,y)=h(x,y)*f(x,y)     

那么,根据卷积定理在频域有

G(u,v)=H(u,v)F(u,v)     

其中,G(u,v)、H(u,v)、F(u,v)分别是 g(x,y)、h(x,y)、f(x,y)的傅立叶变换。频域增强的主要步骤是:

  1. 计算所需增强图的傅立叶变换;
  2. 将其与一个(根据需要设计的)转移函数相乘;
  3. 在将结果进行傅立叶反变换以得到增强的图。

常用的频域增强方法有低通滤波和高通滤波。下面分别介绍这两种滤波方法。

二:低通滤波

图像的能量大部分集中在幅度谱的低频和中频部分,而图像的边缘和噪声对应于高频部分。因此能降低高频成分幅度的滤波器就能减弱噪声的影响。

Butterworth低通滤波器是一种物理上可以实现的低通滤波器。n阶截断频率为d0的Butterworth低通滤波器的转移函数为:

                       

%  实现Butterworth低通滤波器

 I1=imread('lena.png');

 I2=imnoise(I1,'salt');

 f=double(I2);

 g=fft2(f);     %采用傅立叶变换

 g=fftshift(g); %数据矩阵平移

 [N1,N2]=size(g);

 n=2;

 d0=50;

 d1=5;

 n1=fix(N1/2);

 n2=fix(N2/2);

 for i=1:N1

     for j=1:N2

         d=sqrt((i-n1)^2+(j-n2)^2);

         %计算Butterworth低通变换函数

         h=1/(1+0.414*(d/d0)^(2*n));

         result(i,j)=h*g(i,j);

     end

 end

 result=ifftshift(result);

 X2=ifft2(result);

 X3=uint8(real(X2));

三:高通滤波

高通滤波也称高频滤波,它的频率值在0频率处为单位1,随着频率的增长,传递函数的值逐渐增加;当频率增加到一定值后,传递函数的值通常又回到0值或者降低到某个大于1的值。在前一种情况下,高频增强滤波器实际上是一种带通滤波器,只不过规定0频率处的增益为单位1。

在实际应用中,为了减少图像中面积大而且缓慢变化的成分的对比度,有时让0频率处的增益小于单位1更合适。如果传递函数通过原点,则可称为laplacian滤波器。

% 实现Butterworth高通滤波器参考代码

 %计算Butterworth高通变换函数

          if d==0

            h=0;

          else

            h=1/(1+(d1/d)^(2*n));

          end

            result(i,j)=h*g(i,j);

 result=ifftshift(result);

 X4=ifft2(result);

 X5=uint8(real(X2));

 figure(1),subplot(2,2,1),imshow(I1),title('原图像');

 subplot(2,2,2),imshow(I2),title('加噪图像');

subplot(2,2,3),imshow(X3),

title('Butterworth低通滤波器去噪图像');

 subplot(2,2,4),imshow(X5),

title('Butterworth高通滤波器去噪图像');

四:代码实战

1.实验内容

分别用两张以上不同的图片,实现Butterworth低通滤波器和Butterworth高通滤波器, 分别加入不同噪声如高斯噪声,椒盐噪声 (可选加入:指数分布噪声,泊松噪声,乘性噪声),分析Butterworth高通和低通的滤波效果。分析比较Butterworth低通滤波器和不同空域平滑滤波器的差别,结合实验结果对比图进行分析。 

2.Butterworth低通滤波器

function I = Butterworth_low(I_in)
    f=double(I_in);
    g=fft2(f);     %采用傅立叶变换
    g=fftshift(g); %数据矩阵平移
    [N1,N2]=size(g);
    result=zeros(N1,N2);
    n=2;
    d0=50;
    n1=fix(N1/2);
    n2=fix(N2/2);
    for i=1:N1
        for j=1:N2
            d=sqrt((i-n1)^2+(j-n2)^2);
            %计算Butterworth低通变换函数
            h=1/(1+0.414*(d/d0)^(2*n));
            result(i,j)=h*g(i,j);
        end
    end
    result=ifftshift(result);
    X2=ifft2(result);
    I=uint8(real(X2));
end


%lena图片
X1_1=Butterworth_low(I1_1);
figure,subplot(131),imshow(I1),title('lena原图像');
subplot(132),imshow(I1_1),title('加入高斯噪声');
subplot(133),imshow(X1_1),title('Butterworth低通滤波');

 

图2.1-1 lena图像加入高斯噪声的低通滤波结果 

X1_2=Butterworth_low(I1_2);

figure,subplot(131),imshow(I1),title('lena原图像');

subplot(132),imshow(I1_2),title('加入椒盐噪声');

subplot(133),imshow(X1_2),title('Butterworth低通滤波');

图2.1-2 lena图像加入椒盐噪声的低通滤波结果 

X1_3=Butterworth_low(I1_3);

figure,subplot(131),imshow(I1),title('lena原图像');

subplot(132),imshow(I1_3),title('加入泊松噪声');

subplot(133),imshow(X1_3),title('Butterworth低通滤波');

图2.1-3 lena图像加入泊松噪声的低通滤波结果

%pout图片

X2_1=Butterworth_low(I2_1);

figure,subplot(131),imshow(I2),title('pout原图像');

subplot(132),imshow(I2_1),title('加入高斯噪声');

subplot(133),imshow(X2_1),title('Butterworth低通滤波');

图2.1-4 pout图像加入高斯噪声的低通滤波结果

X2_2=Butterworth_low(I2_2); 

figure,subplot(131),imshow(I2),title('pout原图像');

subplot(132),imshow(I2_2),title('加入椒盐噪声');

subplot(133),imshow(X2_2),title('Butterworth低通滤波');

图2.1-5 pout图像加入椒盐噪声的低通滤波结果

X2_3=Butterworth_low(I2_3);

figure,subplot(131),imshow(I2),title('pout原图像');

subplot(132),imshow(I2_3),title('加入泊松噪声');

subplot(133),imshow(X2_3),title('Butterworth低通滤波');

图2.1-6  pout图像加入泊松噪声的低通滤波结果

 

%自定义scenery图像

X3_1=Butterworth_low(I3_1);

figure,subplot(131),imshow(I3),title('scenery原图像');

subplot(132),imshow(I3_1),title('加入高斯噪声');

subplot(133),imshow(X3_1),title('Butterworth低通滤波');

图2.1-7 scenery图像加入高斯噪声的低通滤波结果

X3_2=Butterworth_low(I3_2);

figure,subplot(131),imshow(I3),title('scenery原图像');

subplot(132),imshow(I3_2),title('加入椒盐噪声');

subplot(133),imshow(X3_2),title('Butterworth低通滤波');

 

图2.1-8 scenery图像加入椒盐噪声的低通滤波结果

X3_3=Butterworth_low(I3_3);

figure,subplot(131),imshow(I3),title('scenery原图像');

subplot(132),imshow(I3_3),title('加入泊松噪声');

subplot(133),imshow(X3_3),title('Butterworth低通滤波');

图2.1-9 scenery图像加入泊松噪声的低通滤波结果

 

3.Butterworth高通滤波器

function I = Butterworth_high(I_in)

    f=double(I_in);

    g=fft2(f);     %采用傅立叶变换

    g=fftshift(g); %数据矩阵平移

    [N1,N2]=size(g);

    result=zeros(N1,N2);

    n=2;

    d1=5;

    n1=fix(N1/2);

    n2=fix(N2/2);

    for i=1:N1

        for j=1:N2

            d=sqrt((i-n1)^2+(j-n2)^2);

            %计算Butterworth低通变换函数

            if d==0

                h=0;

            else

                h=1/(1+(d1/d)^(2*n));

            end

            result(i,j)=h*g(i,j);

        end

    end

    result=ifftshift(result);

    X2=ifft2(result);

    I=uint8(real(X2));

end

图2.2-1 lena图像加入高斯噪声的高通滤波结果

图2.2-2 lena图像加入椒盐噪声的高通滤波结果

图2.2-3 lena图像加入泊松噪声的高通滤波结果

图2.2-4 pout图像加入高斯噪声的高通滤波结果

图2.2-5 pout图像加入椒盐噪声的高通滤波结果

图2.2-6 pout图像加入泊松噪声的高通滤波结果

图2.2-7 scenery图像加入高斯噪声的高通滤波结果

图2.2-8 scenery图像加入椒盐噪声的高通滤波结果

图2.2-9 scenery图像加入泊松噪声的高通滤波结果

注:为了便于调用,我将低通高通滤波封装成了函数的形式,然后再对不同的图片进行函数调用;为了节省篇幅,这里仅将主要代码放上来,且不再将Butterworth高通滤波的调用代码放上来。

4.实验分析

图像增强可以分为空间域、频率域和彩色增强,其包含的内容如下图所示:

低通高通滤波是在频率域上对图像的增强,而中值滤波、均值滤波等则是在空间域上对图像的增强。

        一开始我的理解为对于二值图像,当某一像素点与中心点的距离大于D0时,该点的像素值就会被置0,因为根据理想低通滤波函数当D>D0时H=0,当D<=D0时,H=1,而G(u,v)=H(u,v)F(u,v),由于这时候做的是频域上的处理,故不需要进行卷积操作,只需要做乘积操作。这就是问题的关键所在,乘积操作是作用在频域上的,频域上的点不一一和空域上的点对应,所以滤波后的结果并不是说距离中心点距离大于D0就置0。而对应于空域,可将h(x,y)分为两部分:原点处的中心部分,中心周围集中的成周期分布的外围部分。前者决定模糊,后者决定振铃现象。理想低通滤波器函数转换为空域后,对应的函数图像两边对称的余波就是造成振铃现象的原因。

        低通滤波器,顾名思义就是将高频的图像信息过滤掉让低频部分通过,由于低频部分表示图像变化缓慢的部分,故低通滤波器可以实现过滤噪声,平滑图像的功能。低通滤波器有多种,理想的低通滤波器非常尖锐,其在以原点为圆心、D0为半径的园内,通过所有的频率,而在圆外截断所有的频率。从上面实验结果可以看到,布特沃斯低通滤波对于各种噪声的去除效果还是比较理想的,但是实验中发现对变化较平缓的图像(如pout图像),无论是加入高斯噪声还是椒盐噪声,布特沃斯低通滤波的去噪效果并不明显(见图2.1-4)。我猜想其中的原因是由于图像加入噪声之后绝大部分也还是低频信息,通过布特沃斯低通滤波器后绝大多数的噪声未能被过滤掉。因此可以考虑将截止频率D0调低,将D0由50调至30,可以有效去除噪声,但是随之而来的是图像的模糊问题(见下图)。

 

        除此之外,当布特沃斯低通滤波器的阶很大时(截止频率也要较小),这是其效果就接近理想低通滤波器,会产生振铃现象(见下图)。

 

        对于布特沃斯高通滤波,其作用是过滤掉图像的低频部分,保留图像的高频部分。由于图像的高频部分对应着图像的边缘,所以通过高通滤波后的效果是得到图像的边缘,达到图像锐化的作用。由于图像噪声对应着高频部分,所以高通滤波会把噪声保留下来。对于变化平缓的图像(如pout图像),在参数不变的情况下可以看到加入椒盐噪声后锐化效果不明显(得到的边缘不清晰,见图2.2-5)。这是就需要调整参数,以改变其对边缘检测的“灵敏度”,这就说明要降低截止频率,让更多的相对低频的信息能通过,将截止频率由5降至3,得到结果见下图,可以看到图像的边缘更清晰了一些,尽管则会导致噪声的增加。

 

        均值滤波、中值滤波等都是直接在空域上对图像进行处理,而布特沃斯低通滤波器是在频域上对图像进行处理,所以在处理上面布特沃斯低通滤波器的处理过程要更“细腻”一些。对于不同的噪声,布特沃斯都能带来较好的降噪效果,而对于空域上面的平滑滤波,均值滤波会导致图像的边缘模糊化,中值滤波可能会改变图像的性质。

 

以上是关于【转载】opencv 频域高通、低通滤波演示的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV-高斯低通&高通滤波器(C++)

计算机视觉图像分割与特征提取——频域增强(低通滤波&高通滤波)

计算机视觉图像分割与特征提取——频域增强(低通滤波&高通滤波)

OpenCV 完整例程84. 由低通滤波器得到高通滤波器

数字图像处理-频域滤波

OpenCV-高斯低通&高通滤波器(C++)