【轉載】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]


????# 計算最優(yōu)尺寸

????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)


????# 創(chuàng)建d0 tracker, d0為過濾器大小

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


????# 創(chuàng)建flag tracker,

????# flag=0時,為理想濾波

????# flag=1時,為巴特沃茲濾波

????# flag=2時,為高斯濾波

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


????# 創(chuàng)建n tracker

????# n 為巴特沃茲濾波的階數

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


????# 創(chuàng)建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

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容