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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容