分享

opencv 傅立叶变换演示

 dbn9981 2016-09-30

      演示傅立叶变换的低通滤波和高通滤波

      #! /usr/bin/env python
      #coding=utf-8
      from __future__ import unicode_literals
      import cv2
      import numpy as np
      '''
      傅立叶变换演示
      频谱图像窗口: 显示图像滤波后的频谱
      - size: 滤波器大小
      - flag:滤波器类型,0 为低通滤波, 1为高通滤波
      图像窗口: 显示原图像和滤波后频谱进行反变换的图像
      '''
      def fft(img):
      '''对图像进行傅立叶变换,并返回换位后的频谱'''
      assert img.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)
      # 换位,低频部分移到中间,高频部分移到四周
      min_value = np.min(fft_mat)
      return np.fft.fftshift(fft_mat)def fft_img(shift_mat):
      '''将频谱转换为可视图像'''
      # log函数中加1,避免log(0)出现.
      log_mat= cv2.log(1 + cv2.magnitude(shift_mat[:,:,0], shift_mat[:,:,1]))
      # 标准化到0~255之间
      cv2.normalize(log_mat, log_mat, 0, 255, cv2.NORM_MINMAX)
      return np.uint8(np.around(log_mat))def ifft(fshift_mat):
      '''傅立叶反变换,返回反变换图像'''
      # 反换位,低频部分移到四周,高频部分移到中间
      f_ishift_mat = np.fft.ifftshift(fshift_mat)
      # 傅立叶反变换
      img_back = cv2.idft(f_ishift_mat)
      img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
      cv2.normalize(img_back, img_back, 0, 255, cv2.NORM_MINMAX)
      return np.uint8(np.around(img_back))def do_filter(_=None):
      '''滤波,并显示'''
      size = cv2.getTrackbarPos('size', dft_spectrum_window)
      flag = cv2.getTrackbarPos('flag', dft_spectrum_window)
      filter_mat, mask = None, None
      # 低通滤波
      if flag == 0:
      mask = np.zeros((frows, fcols ,2),np.float32)
      mask[frows/2-size/2:frows/2+size/2, fcols/2-size/2:fcols/2+size/2] = 1
      # 高通滤波
      else:
      mask = np.ones((frows, fcols ,2),np.float32)
      mask[frows/2-size/2:frows/2+size/2, fcols/2-size/2:fcols/2+size/2] = 0
      # 滤波后的频谱
      filter_mat = fft_shift_mat * mask
      # 同时显示原图像和反变换后的图像
      cv2.imshow(dft_image_window, combine_images([img, ifft(filter_mat)]))
      # 显示滤波后的频谱图像
      cv2.imshow(dft_spectrum_window, fft_img(filter_mat))def combine_images(images, axis=1):
      '''
      使用numpy函数合并图像。
      @type images: list or iter
      @param images: 图像列表,图像成员的维数必须相同
      @type axis: int
      @param axis: 合并方向。 axis=0时,图像垂直合并,axis = 1 时, 图像水平合并。
      @return 合并后的图像
      '''
      ndim = images[0].ndim
      shapes = np.array([mat.shape for mat in images])
      assert np.all(map(lambda e: len(e)==ndim, shapes)), 'all images should be same ndim.'
      if axis == 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)) for img in images]
      # 垂直方向合并
      return np.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)) for img in images]
      # 水平方向合并
      return np.hstack(copy_imgs)if __name__ == '__main__':
      img = cv2.imread('lena.jpg',0)
      rows, cols = img.shape[:2]
      # 频谱窗口名称
      dft_spectrum_window = 'spectrum'
      # 图像窗口名称
      dft_image_window = 'image'
      cv2.namedWindow(dft_spectrum_window)
      cv2.namedWindow(dft_image_window)
      # 创建size tracker, size为过滤器大小,初始大小为50
      cv2.createTrackbar('size', dft_spectrum_window, 50, min(rows, cols), do_filter)
      # 创建flag tracker, flag=0时,为低通滤波, flag=1时,为高通滤波,初始设置为低通滤波
      cv2.createTrackbar('flag', dft_spectrum_window, 0, 1, do_filter)
      fft_shift_mat = fft(img)
      frows, fcols = fft_shift_mat.shape[:2]
      do_filter()
      cv2.waitKey(0)
      cv2.destroyAllWindows()

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约