import matplotlib.pyplot as plt import numpy as np import cv2 %matplotlib inline
首先讀入此次須要使用的圖像python
img = cv2.imread('apple.jpg',0) #直接讀爲灰度圖像 plt.imshow(img,cmap="gray") plt.axis("off") plt.show()
使用numpy帶的fft庫完成從頻率域到空間域的轉換。app
f = np.fft.fft2(img) fshift = np.fft.fftshift(f)
低通濾波器的公式以下
\[ H(u,v)= \begin{cases} 1, & \text{if $D(u,v)$ } \leq D_{0}\\ 0, & \text{if $D(u,v)$} \geq D_{0} \end{cases} \]
其中\(D(u,v)\)爲頻率域上\((u,v)\)點到中心的距離,\(D_0\)由本身設置
白點就是所容許經過的頻率範圍
3d圖像以下
ui
咱們先把蘋果轉化成頻率域看下效果spa
#取絕對值:將複數變化成實數 #取對數的目的爲了將數據變化到0-255 s1 = np.log(np.abs(fshift)) plt.subplot(121),plt.imshow(s1,'gray') plt.title('Frequency Domain') plt.show()
matplotlib對於不是uint8的圖像會自動把圖像的數值縮放到0-255上,更多能夠查看對該問題的討論3d
咱們在頻率域上試着取不一樣的\(d_0\)再將其反變換到空間域看下效果code
def make_transform_matrix(d,image): transfor_matrix = np.zeros(image.shape) center_point = tuple(map(lambda x:(x-1)/2,s1.shape)) for i in range(transfor_matrix.shape[0]): for j in range(transfor_matrix.shape[1]): def cal_distance(pa,pb): from math import sqrt dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2) return dis dis = cal_distance(center_point,(i,j)) if dis <= d: transfor_matrix[i,j]=1 else: transfor_matrix[i,j]=0 return transfor_matrix d_1 = make_transform_matrix(10,fshift) d_2 = make_transform_matrix(30,fshift) d_3 = make_transform_matrix(50,fshift)
設定距離分別爲10,30,50其經過的頻率的範圍如圖orm
plt.subplot(131) plt.axis("off") plt.imshow(d_1,cmap="gray") plt.title('D_1 10') plt.subplot(132) plt.axis("off") plt.title('D_2 30') plt.imshow(d_2,cmap="gray") plt.subplot(133) plt.axis("off") plt.title("D_3 50") plt.imshow(d_3,cmap="gray") plt.show()
img_d1 = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_1))) img_d2 = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_2))) img_d3 = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_3))) plt.subplot(131) plt.axis("off") plt.imshow(img_d1,cmap="gray") plt.title('D_1 10') plt.subplot(132) plt.axis("off") plt.title('D_2 30') plt.imshow(img_d2,cmap="gray") plt.subplot(133) plt.axis("off") plt.title("D_3 50") plt.imshow(img_d3,cmap="gray") plt.show()
講上面過程整理獲得頻率域低通濾波器的代碼以下blog
def lowPassFilter(image,d): f = np.fft.fft2(image) fshift = np.fft.fftshift(f) def make_transform_matrix(d): transfor_matrix = np.zeros(image.shape) center_point = tuple(map(lambda x:(x-1)/2,s1.shape)) for i in range(transfor_matrix.shape[0]): for j in range(transfor_matrix.shape[1]): def cal_distance(pa,pb): from math import sqrt dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2) return dis dis = cal_distance(center_point,(i,j)) if dis <= d: transfor_matrix[i,j]=1 else: transfor_matrix[i,j]=0 return transfor_matrix d_matrix = make_transform_matrix(d) new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix))) return new_img
plt.imshow(lowPassFilter(img,60),cmap="gray")
高通濾波器同低通濾波器很是相似,只不過兩者經過的波正好是相反的
\[ H(u,v)= \begin{cases} 0, & \text{if $D(u,v)$ } \leq D_{0}\\ 1, & \text{if $D(u,v)$} \geq D_{0} \end{cases} \]
get
def highPassFilter(image,d): f = np.fft.fft2(image) fshift = np.fft.fftshift(f) def make_transform_matrix(d): transfor_matrix = np.zeros(image.shape) center_point = tuple(map(lambda x:(x-1)/2,s1.shape)) for i in range(transfor_matrix.shape[0]): for j in range(transfor_matrix.shape[1]): def cal_distance(pa,pb): from math import sqrt dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2) return dis dis = cal_distance(center_point,(i,j)) if dis <= d: transfor_matrix[i,j]=0 else: transfor_matrix[i,j]=1 return transfor_matrix d_matrix = make_transform_matrix(d) new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix))) return new_img
img_d1 = highPassFilter(img,10) img_d2 = highPassFilter(img,30) img_d3 = highPassFilter(img,50) plt.subplot(131) plt.axis("off") plt.imshow(img_d1,cmap="gray") plt.title('D_1 10') plt.subplot(132) plt.axis("off") plt.title('D_2 30') plt.imshow(img_d2,cmap="gray") plt.subplot(133) plt.axis("off") plt.title("D_3 50") plt.imshow(img_d3,cmap="gray") plt.show()
顯然當\(D_0=10\)時,蘋果的邊緣最清楚it
import imagefilter
thread_img = imagefilter.RobertsAlogrithm(img) laplace_img = imagefilter.LaplaceAlogrithm(img,"fourfields") mean_img = cv2.blur(img,(3,3)) plt.subplot(131) plt.imshow(thread_img,cmap="gray") plt.title("ThreadImage") plt.axis("off") plt.subplot(132) plt.imshow(laplace_img,cmap="gray") plt.axis("off") plt.title("LaplaceImage") plt.subplot(133) plt.imshow(mean_img,cmap="gray") plt.title("meanImage") plt.axis("off") plt.show()
空間域上的平均濾波和低通濾波同樣,只要起去掉無關信息,平滑圖像的做用。
Roberts,Laplace等濾波則起的提取邊緣的做用。
頻率域高斯高通濾波器的公式以下
\[ H(u,v) = 1-e^{\dfrac{-D^2(u,v)}{2D_0^2}} \]
def GaussianHighFilter(image,d): f = np.fft.fft2(image) fshift = np.fft.fftshift(f) def make_transform_matrix(d): transfor_matrix = np.zeros(image.shape) center_point = tuple(map(lambda x:(x-1)/2,s1.shape)) for i in range(transfor_matrix.shape[0]): for j in range(transfor_matrix.shape[1]): def cal_distance(pa,pb): from math import sqrt dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2) return dis dis = cal_distance(center_point,(i,j)) transfor_matrix[i,j] = 1-np.exp(-(dis**2)/(2*(d**2))) return transfor_matrix d_matrix = make_transform_matrix(d) new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix))) return new_img
使用高斯濾波器d分別爲10,30,50實現的效果
img_d1 = GaussianHighFilter(img,10) img_d2 = GaussianHighFilter(img,30) img_d3 = GaussianHighFilter(img,50) plt.subplot(131) plt.axis("off") plt.imshow(img_d1,cmap="gray") plt.title('D_1 10') plt.subplot(132) plt.axis("off") plt.title('D_2 30') plt.imshow(img_d2,cmap="gray") plt.subplot(133) plt.axis("off") plt.title("D_3 50") plt.imshow(img_d3,cmap="gray") plt.show()
頻率域高斯低通濾波器的公式以下
\[ H(u,v) = e^{\dfrac{-D^2(u,v)}{2D_0^2}} \]
def GaussianLowFilter(image,d): f = np.fft.fft2(image) fshift = np.fft.fftshift(f) def make_transform_matrix(d): transfor_matrix = np.zeros(image.shape) center_point = tuple(map(lambda x:(x-1)/2,s1.shape)) for i in range(transfor_matrix.shape[0]): for j in range(transfor_matrix.shape[1]): def cal_distance(pa,pb): from math import sqrt dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2) return dis dis = cal_distance(center_point,(i,j)) transfor_matrix[i,j] = np.exp(-(dis**2)/(2*(d**2))) return transfor_matrix d_matrix = make_transform_matrix(d) new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix))) return new_img
img_d1 = GaussianLowFilter(img,10) img_d2 = GaussianLowFilter(img,30) img_d3 = GaussianLowFilter(img,50) plt.subplot(131) plt.axis("off") plt.imshow(img_d1,cmap="gray") plt.title('D_1 10') plt.subplot(132) plt.axis("off") plt.title('D_2 30') plt.imshow(img_d2,cmap="gray") plt.subplot(133) plt.axis("off") plt.title("D_3 50") plt.imshow(img_d3,cmap="gray") plt.show()
一般空間域使用高斯濾波來平滑圖像,在上一篇已經寫過,直接使用上篇文章的代碼。
def GaussianOperator(roi): GaussianKernel = np.array([[1,2,1],[2,4,2],[1,2,1]]) result = np.sum(roi*GaussianKernel/16) return result def GaussianSmooth(image): new_image = np.zeros(image.shape) image = cv2.copyMakeBorder(image,1,1,1,1,cv2.BORDER_DEFAULT) for i in range(1,image.shape[0]-1): for j in range(1,image.shape[1]-1): new_image[i-1,j-1] =GaussianOperator(image[i-1:i+2,j-1:j+2]) return new_image.astype(np.uint8) new_apple = GaussianSmooth(img) plt.subplot(121) plt.axis("off") plt.title("origin image") plt.imshow(img,cmap="gray") plt.subplot(122) plt.axis("off") plt.title("Gaussian image") plt.imshow(img,cmap="gray") plt.subplot(122) plt.axis("off") plt.show()
不管是低通濾波器,高通濾波器都是粗暴的一刀切,正如以前那麼多空間域的濾波器同樣,咱們但願它經過的頻率和與中心線性相關。
\[ h(u,v) = \frac{1} {{1+(D_0 / D(u,v))}^{2n}} \]
def butterworthPassFilter(image,d,n): f = np.fft.fft2(image) fshift = np.fft.fftshift(f) def make_transform_matrix(d): transfor_matrix = np.zeros(image.shape) center_point = tuple(map(lambda x:(x-1)/2,s1.shape)) for i in range(transfor_matrix.shape[0]): for j in range(transfor_matrix.shape[1]): def cal_distance(pa,pb): from math import sqrt dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2) return dis dis = cal_distance(center_point,(i,j)) transfor_matrix[i,j] = 1/((1+(d/dis))**n) return transfor_matrix d_matrix = make_transform_matrix(d) new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix))) return new_img
plt.subplot(231) butter_100_1 = butterworthPassFilter(img,100,1) plt.imshow(butter_100_1,cmap="gray") plt.title("d=100,n=1") plt.axis("off") plt.subplot(232) butter_100_2 = butterworthPassFilter(img,100,2) plt.imshow(butter_100_2,cmap="gray") plt.title("d=100,n=2") plt.axis("off") plt.subplot(233) butter_100_3 = butterworthPassFilter(img,100,3) plt.imshow(butter_100_3,cmap="gray") plt.title("d=100,n=3") plt.axis("off") plt.subplot(234) butter_100_1 = butterworthPassFilter(img,30,1) plt.imshow(butter_100_1,cmap="gray") plt.title("d=30,n=1") plt.axis("off") plt.subplot(235) butter_100_2 = butterworthPassFilter(img,30,2) plt.imshow(butter_100_2,cmap="gray") plt.title("d=30,n=2") plt.axis("off") plt.subplot(236) butter_100_3 = butterworthPassFilter(img,30,3) plt.imshow(butter_100_3,cmap="gray") plt.title("d=30,n=3") plt.axis("off") plt.show()
能夠明顯的觀察出過大的n形成的振鈴現象
butter_5_1 = butterworthPassFilter(img,5,1) plt.imshow(butter_5_1,cmap="gray") plt.title("d=5,n=3") plt.axis("off") plt.show()