演示傅立叶变换的低通滤波和高通滤波 #! /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() |
|
来自: dbn9981 > 《python与程序设计》