演示傅立葉變換的低通濾波和高通濾波 #! /usr/bin/env python#coding=utf-8 from __future__ import unicode_literals import cv2 import numpy as np ''' 傅立葉變換演示 頻譜圖像窗口: 顯示圖像濾波后的頻譜 - size: 濾波器大小 - flag:濾波器類型,0 為低通濾波, 1為高通濾波 圖像窗口: 顯示原圖像和濾波后頻譜進(jìn)行反變換的圖像 ''' def fft(img): '''對圖像進(jìn)行傅立葉變換,并返回?fù)Q位后的頻譜''' assert img.ndim==2, 'img should be gray.' rows, cols = img.shape[:2] # 計(jì)算最優(yōu)尺寸 nrows = cv2.getOptimalDFTSize(rows) ncols = cv2.getOptimalDFTSize(cols) # 根據(jù)新尺寸,建立新變換圖像 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): '''將頻譜轉(zhuǎn)換為可視圖像''' # log函數(shù)中加1,避免log(0)出現(xiàn). log_mat= cv2.log(1 + cv2.magnitude(shift_mat[:,:,0], shift_mat[:,:,1])) # 標(biāo)準(zhǔn)化到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 # 同時(shí)顯示原圖像和反變換后的圖像 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函數(shù)合并圖像。 @type images: list or iter @param images: 圖像列表,圖像成員的維數(shù)必須相同 @type axis: int @param axis: 合并方向。 axis=0時(shí),圖像垂直合并,axis = 1 時(shí), 圖像水平合并。 @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]) # 擴(kuò)展各圖像 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]) # 擴(kuò)展各圖像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) # 創(chuàng)建size tracker, size為過濾器大小,初始大小為50 cv2.createTrackbar('size', dft_spectrum_window, 50, min(rows, cols), do_filter) # 創(chuàng)建flag tracker, flag=0時(shí),為低通濾波, flag=1時(shí),為高通濾波,初始設(shè)置為低通濾波 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() |
|