圖像處理1--傅里葉變換(Fourier Transform )


樓下一個男人病得要死,那間壁的一家唱着留聲機;對面是弄孩子。樓上有兩人狂笑;還有打牌聲。河中的船上有女人哭着她死去的母親。人類的悲歡並不相通,我只覺得他們吵鬧 。

OpenCV是一個基於BSD許可(開源)發行的跨平台計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類 構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了 圖像處理和計算機視覺方面的很多通用算法。
OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言 接口。該庫也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。這些語言的API接口函數可以通過在線 文檔獲得。如今也提供對於C#、Ch、Ruby,GO的支持。
所有新的開發和算法都是用C++接口。一個使用CUDA的GPU接口也於2010年9月開始實現。

圖像的空間域濾波:空間域濾波,空間域濾波就是用各種模板直接與圖像進行卷積運算,實現對圖像的處理,這種方法直接對圖像空間操作,操作簡單,所以也是空間域濾波。

頻域濾波說到底最終可能是和空間域濾波實現相同的功能,比如實現圖像的輪廓提取,在空間域濾波中我們使用一個拉普拉斯模板就可以提取,而在頻域內,我們使用一個高通濾波模板(因為輪廓在頻域內屬於高頻信號),可以實現輪廓的提取,后面也會把拉普拉斯模板頻域化,會發現拉普拉斯其實在頻域來講就是一個高通濾波器。

既然是頻域濾波就涉及到把圖像首先變到頻域內,那么把圖像變到頻域內的方法就是傅里葉變換。關於傅里葉變換,感覺真是個偉大的發明,尤其是其在信號領域的應用。高通濾波器,又稱低截止濾波器、低阻濾波器,允許高於某一截頻的頻率通過,而大大衰減較低頻率的一種濾波器。它去掉了信號中不必要的低頻成分或者說去掉了低頻干擾。

import cv2 as cv

import numpy as np

from matplotlib import pyplot as plt

 

img = cv.imread('23.png', 0)

f = np.fft.fft2(img)

fshift = np.fft.fftshift(f)

#取絕對值:將復數變化成實數

#取對數的目的為了將數據變化到較小的范圍(比如0-255)

s1 = np.log(np.abs(f))

s2 = np.log(np.abs(fshift))

plt.subplot(121),plt.imshow(s1,'gray'),plt.title('original')

plt.subplot(122),plt.imshow(s2,'gray'),plt.title('center')

 

這個圖就是把時域圖像(大概是方波)變成了一系列的正弦波的線性疊加,其等價關系可以表示為:

f()=A1sin(w1x+ϕ1)+A2sin(w2x+ϕ2)+...


那么w1,w2,...可以看成是頻率的變化(一般認為就是從1,2,…n定死了),所有的A就是對應頻率下的振幅,所有的ϕ就是對應頻率下的相位,那么對於任一個信號,如果都認為頻率w是從1,2,3…一直增加的話,那么每個信號就只由一組振幅與一組ϕ來決定,他們的不同決定了最終信號的不同。

再來理解下什么是振幅,振幅就是各個頻率下的信號的決定程度有多大,如果某個頻率的振幅越大,那么它對原始信號的的重要性越大,像上圖,當然是w=1的時候振幅最大,說明它對總的信號影響最多(去掉w=1的信號,原始信號講嚴重變形)。越往后面,也就是越高頻,振幅逐漸減小,那么他們的作用就越小,而他們對於整體信號又有什么影響呢?既然越小,那就是影響小,所以其實去掉,原始信號也基本上不變,他們影響就在於對原始信號的細節上的表現,比如原始信號上的邊邊角角,偶爾有個小凸起凹槽什么的,這些小細節部分都是靠這些個影響不大的高頻信號來表現出來的。深入推廣一下,這就很好理解為什么圖像的高頻信號其實表現出來的就是圖像的邊緣輪廓、噪聲等等這些細節的東西了,而低頻信號,表現的卻是圖像上整塊整塊灰度大概一樣的區域了(這些個區域又稱為直流分量區域)。

再來理解下什么是相位,相位表示其實表面對應頻率下的正弦分量偏離原點的程度,再借用下上述博客中的一個圖,把分量示意圖放大了:

上圖看到,如果各個頻率的分量相位都是0的話,那么每個正弦分量的最大值(在頻率軸附近的那個最大值)都會落在頻率軸為0上,然而上述圖並不是這樣。在說簡單一點,比如原始信號上有個凹槽,正好是由某一頻率的分量疊加出來的,那么如果這個頻率的相位變大一點或者變小一點的話,帶來的影響就會使得這個凹槽向左或者向右移動一下,也就是說,相位的作用就是精確定位到信號上一點的位置的。 好了,有了上述的概念,再來看看圖像的傅里葉變換,上述舉得例子是一維信號的傅里葉變換,並且信號是連續的,我們知道圖像是二維離散的,連續與離散都可以用傅里葉進行變換,那么二維信號無非就是在x方向與y方向都進行一次一維的傅里葉變換得到,這么看來,可以想象,它的頻率構成就是一個網格矩陣了,橫軸從w=1到n,縱軸也是這樣。所有圖像的頻率構成都認為是這樣的,那么不同的就是一幅圖的振幅與相位了(振幅與相位此時同樣是一個網格矩陣),也就是說你在opencv或者matlab下對圖像進行傅里葉變換后其實是可以得到圖像的振幅圖與相位圖的,而想把圖像從頻域空間恢復到時域空間,必須要同時有圖像的振幅圖與相位圖才可以,缺少一個就恢復的不完整。

在這里插入一個獲取視頻的代碼

從攝像頭捕獲視頻

OpenCV提供了一個非常簡單的接口,用來相機捕捉實時流。
任務:從相機中獲取一個視頻(由於練習時家里的台式沒有攝像頭,就直接獲取一個本地視頻),把它轉換成灰度級的視頻並顯示出來。

要捕獲一個視頻,你需要創建一個可視的對象cv.VideoCapture()。參數可以是設備索引,也可以是視頻文件的名稱(這里用視頻文件名稱)。設備索引只是指定哪個攝像頭的號碼,如0、1、2。

 1 import cv2 as cv
 2 
 3 cap = cv.VideoCapture('test.mp4')
 4 while cap.isOpened():
 5     # 逐幀捕獲
 6     ret, frame = cap.read()
 7     # 對幀進行操作
 8     gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
 9     # 展示結果
10     cv.imshow('frame', gray)
11     if cv.waitKey(1) & 0xFF == ord('q'):
12         break
13 
14 # 一切完成后,釋放捕獲
15 cap.release()
16 cv.destroyAllWindows()

回到正題,傅立葉空間的變幻代碼介紹開始:

1.獲取圖片振幅信息

 1 import cv2 as cv
 2 import numpy as np
 3 from matplotlib import pyplot as plt
 4 
 5 img = cv.imread('你想要插入的圖片', 0#0代表傳入的是灰度圖像,1代表彩色圖像)
 6 f = np.fft.fft2(img)
 7 fshift = np.fft.fftshift(f)
 8 #取絕對值:將復數變化成實數
 9 #取對數的目的為了將數據變化到較小的范圍(比如0-255)
10 s1 = np.log(np.abs(f))
11 s2 = np.log(np.abs(fshift))
12 plt.subplot(121),plt.imshow(s1,'gray'),plt.title('original')
13 plt.subplot(122),plt.imshow(s2,'gray'),plt.title('center')

注意的是,這個程序的result其實並沒有什么含義,顯示出來的可以看成是頻域后圖像的振幅信息,並沒有相位信息,ϕ=atan(numpy包中自帶一個angle函數可以直接根據復數的實部與虛部求出角度(默認出來的角度是弧度)。像上述程序出來的f與fshift都是復數,就可以直接angle函數一下,比如試試並把對應的相位圖像顯示出來

 1 import cv2 as cv
 2 import numpy as np
 3 from matplotlib import pyplot as plt
 4 
 5 img = cv.imread('23.png', 0)
 6 
 7 f = np.fft.fft2(img)
 8 fshift = np.fft.fftshift(f)
 9 #取絕對值:將復數變化成實數
10 #取對數的目的為了將數據變化到較小的范圍(比如0-255)
11 ph_f = np.angle(f)
12 ph_fshift = np.angle(fshift)
13 
14 plt.subplot(121),plt.imshow(ph_f,'gray'),plt.title('original')
15 plt.subplot(122),plt.imshow(ph_fshift,'gray'),plt.title('center')
View Code

result就是圖像上每個像素點對應的相位圖,其實是毫無規律的,理解就是偏移的角度。

Ok再來說說程序中為什么要有一個np.fft.fftshift(f)中心化操作,整個圖像是在傅里葉變換的一個周期內完成的,將其看成橫縱兩個方向的一維傅里葉變換,在每個方向上都會有高頻信號和低頻信號,那么傅里葉變換將低頻信號放在了邊緣,高頻信號放在了中間,然而一副圖像,很明顯的低頻信號多而明顯,所以將低頻信號采用一種方法移到中間,在時域上就是對f乘以(-1)^(M+N),換到頻域里面就是位置的移到了。

圖像變換到頻域后就可以進行操作了,目前接觸到的頻域操作似乎也就是一些濾波操作,如同空域里面的濾波操作一樣,不過原理不一樣了,后面再說說一些頻域濾波方法。好了一旦操作完,得到的數據還是頻域數據,那么如何將其變換到時域呢?這里就是傅里葉反變換了,公式表示就如同前面那樣。這個頻域變換到時域的操作就是逆向傅里葉變換再走一遍(比如先反中心化,在逆變換)。

 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 
 5 img = cv2.imread('23.png',0) #直接讀為灰度圖像
 6 f = np.fft.fft2(img)
 7 fshift = np.fft.fftshift(f)
 8 #取絕對值:將復數變化成實數
 9 #取對數的目的為了將數據變化到0-255
10 s1 = np.log(np.abs(fshift))
11 plt.subplot(131),plt.imshow(img,'gray'),plt.title('original')
12 plt.subplot(132),plt.imshow(s1,'gray'),plt.title('center')
13 # 逆變換
14 f1shift = np.fft.ifftshift(fshift)
15 img_back = np.fft.ifft2(f1shift)
16 #出來的是復數,無法顯示
17 img_back = np.abs(img_back)
18 plt.subplot(133),plt.imshow(img_back,'gray'),plt.title('img back')
View Code

可以看到恢復的一模一樣。

(振幅是復數的實數部,相位是復數的虛數部)我們說,恢復一個頻域圖像需要圖像的振幅以及相位,而一個復數也正好包含這些,振幅就是實部虛部的平方和開方,相位就是atan()

,前面說過。那么現在假設我們只用一副圖像的振幅或者相位來將頻域內圖像恢復到時域會怎么樣呢?下面給出只用振幅、只用相位以及兩者在聯合起來來恢復的程序:

 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 
 5 img = cv2.imread('23.png',0) #直接讀為灰度圖像
 6 f = np.fft.fft2(img)
 7 fshift = np.fft.fftshift(f)
 8 #取絕對值:將復數變化成實數
 9 #取對數的目的為了將數據變化到0-255
10 s1 = np.log(np.abs(fshift))
11 plt.subplot(221),plt.imshow(img,'gray'),plt.title('original')
12 plt.xticks([]),plt.yticks([])
13 #---------------------------------------------
14 # 逆變換--取絕對值就是振幅
15 f1shift = np.fft.ifftshift(np.abs(fshift))
16 img_back = np.fft.ifft2(f1shift)
17 #出來的是復數,無法顯示
18 img_back = np.abs(img_back)
19 #調整大小范圍便於顯示
20 img_back = (img_back-np.amin(img_back))/(np.amax(img_back)-np.amin(img_back))
21 plt.subplot(222),plt.imshow(img_back,'gray'),plt.title('only Amplitude')
22 plt.xticks([]),plt.yticks([])
23 #---------------------------------------------
24 # 逆變換--取相位
25 f2shift = np.fft.ifftshift(np.angle(fshift))
26 img_back = np.fft.ifft2(f2shift)
27 #出來的是復數,無法顯示
28 img_back = np.abs(img_back)
29 #調整大小范圍便於顯示
30 img_back = (img_back-np.amin(img_back))/(np.amax(img_back)-np.amin(img_back))
31 plt.subplot(223),plt.imshow(img_back,'gray'),plt.title('only phase')
32 plt.xticks([]),plt.yticks([])
33 #---------------------------------------------
34 # 逆變換--將兩者合成看看
35 s1 = np.abs(fshift) #取振幅
36 s1_angle = np.angle(fshift) #取相位
37 s1_real = s1*np.cos(s1_angle) #取實部
38 s1_imag = s1*np.sin(s1_angle) #取虛部
39 s2 = np.zeros(img.shape,dtype=complex) 
40 s2.real = np.array(s1_real) #重新賦值給s2
41 s2.imag = np.array(s1_imag)
42 
43 f2shift = np.fft.ifftshift(s2) #對新的進行逆變換
44 img_back = np.fft.ifft2(f2shift)
45 #出來的是復數,無法顯示
46 img_back = np.abs(img_back)
47 #調整大小范圍便於顯示
48 img_back = (img_back-np.amin(img_back))/(np.amax(img_back)-np.amin(img_back))
49 plt.subplot(224),plt.imshow(img_back,'gray'),plt.title('another way')
50 plt.xticks([]),plt.yticks([])
View Code

 

可以看到,僅僅振幅的恢復圖啥也不是,僅僅的相位圖還有那么點意思,當然也是啥也不是。最后是把振幅與相位分別作為頻域內復數的實部和虛部,得到的恢復圖才與原來的一樣。

基於此,我們來做一個有趣的實驗,假設有兩幅圖像,將這兩幅圖像進行傅里葉變換到頻域,然后把用一個圖像的振幅做為振幅,用另一幅圖像的相位作為相位生成一副新的圖像,那么,這個圖像會怎么樣呢?你覺得生成的圖像會更像取振幅的那副還是取相位的那副呢?來看看吧:

 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 
 5 img_flower = cv2.imread('v',0) #直接讀為灰度圖像
 6 img_man = cv2.imread('v',0) #直接讀為灰度圖像
 7 plt.subplot(221),plt.imshow(img_flower,'gray'),plt.title('origial1')
 8 plt.xticks([]),plt.yticks([])
 9 plt.subplot(222),plt.imshow(img_man,'gray'),plt.title('origial_2')
10 plt.xticks([]),plt.yticks([])
11 #--------------------------------
12 f1 = np.fft.fft2(img_flower)
13 f1shift = np.fft.fftshift(f1)
14 f1_A = np.abs(f1shift) #取振幅
15 f1_P = np.angle(f1shift) #取相位
16 #--------------------------------
17 f2 = np.fft.fft2(img_man)
18 f2shift = np.fft.fftshift(f2)
19 f2_A = np.abs(f2shift) #取振幅
20 f2_P = np.angle(f2shift) #取相位
21 #---圖1的振幅--圖2的相位--------------------
22 img_new1_f = np.zeros(img_flower.shape,dtype=complex) 
23 img1_real = f1_A*np.cos(f2_P) #取實部
24 img1_imag = f1_A*np.sin(f2_P) #取虛部
25 img_new1_f.real = np.array(img1_real) 
26 img_new1_f.imag = np.array(img1_imag) 
27 f3shift = np.fft.ifftshift(img_new1_f) #對新的進行逆變換
28 img_new1 = np.fft.ifft2(f3shift)
29 #出來的是復數,無法顯示
30 img_new1 = np.abs(img_new1)
31 #調整大小范圍便於顯示
32 img_new1 = (img_new1-np.amin(img_new1))/(np.amax(img_new1)-np.amin(img_new1))
33 plt.subplot(223),plt.imshow(img_new1,'gray'),plt.title('another way')
34 plt.xticks([]),plt.yticks([])
35 #---圖2的振幅--圖1的相位--------------------
36 img_new2_f = np.zeros(img_flower.shape,dtype=complex) 
37 img2_real = f2_A*np.cos(f1_P) #取實部
38 img2_imag = f2_A*np.sin(f1_P) #取虛部
39 img_new2_f.real = np.array(img2_real) 
40 img_new2_f.imag = np.array(img2_imag) 
41 f4shift = np.fft.ifftshift(img_new2_f) #對新的進行逆變換
42 img_new2 = np.fft.ifft2(f4shift)
43 #出來的是復數,無法顯示
44 img_new2 = np.abs(img_new2)
45 #調整大小范圍便於顯示
46 img_new2 = (img_new2-np.amin(img_new2))/(np.amax(img_new2)-np.amin(img_new2))
47 plt.subplot(224),plt.imshow(img_new2,'gray'),plt.title('another way')
48 plt.xticks([]),plt.yticks([])
View Code

重點來了:如果兩張圖片的維度不一樣,也就是矩陣的shape不一樣時,匯報錯ValueError: operands could not be broadcast together with shapes,所以變換的兩張圖片維度一定要一樣,也就是說大小要一樣,這個解決了好久,其他也是,兩張圖片處理時是通過np的方法形成的矩陣,矩陣大小一定要一樣才能繼續計算,否則是無法處理的。

合成的圖像,是不是很有趣,圖像3是圖1的振幅加圖2的相位,圖像4是圖1的相位加上圖2的振幅。很明顯的可以看到,新圖像占用誰的相位就越像誰,為什么會這樣?很簡單,可以理解振幅不過描述圖像灰度的亮度,占用誰的振幅不過使得結果哪些部分偏亮或者暗而已,而圖像是個什么樣子是由它的相位決定的。相位描述的是一個方向,方向正確了,那么最終的結果離你的目的就不遠了。可想而知,方向對於一件事物是多么的重要,大自然的規律尚且如此,更別說做人做事了,找准並相信一個方向,慢慢的走下去吧,總有一天會看到成果的,哪怕你的振幅不對,走的慢一點,但是最終也能走的像模像樣的,不會說到了人生的最后,回頭一看,再來感嘆哎呀這是什么玩意,那就很悲哀了。

下面開始講濾波器啦!

我們只說了開頭(怎么變換)和結尾(怎么變回去),那么中間我們要做的東西才是傅里葉變換的目的—頻域下的各種變化操作。

這里主要介紹頻域下的濾波–低通濾波器,高通濾波器,帶通帶阻濾波器。

我們知道,圖像在變換加移動中心后,從中間到外面,頻率上依次是從低頻到高頻的,那么我們如果把中間規定一小部分去掉,是不是相對於把低頻信號去掉了呢?這也就是相當於進行了高通濾波。這個濾波模板畫出來可能就是這樣的:

 

黑色為0,白色為1,把這個模板去和圖像進過傅里葉變換的頻域矩陣去與(相乘)一下就實現了高通濾波。

高通濾波器代碼如下

 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 
 5 img_man = cv2.imread('lip',0) #直接讀為灰度圖像
 6 plt.subplot(121),plt.imshow(img_man,'gray'),plt.title('origial')
 7 plt.xticks([]),plt.yticks([])
 8 #--------------------------------
 9 rows,cols = img_man.shape
10 mask = np.ones(img_man.shape,np.uint8)
11 mask[rows//2-30:rows//2+30,cols//2-30:cols//2+30] = 0
12 #--------------------------------
13 f1 = np.fft.fft2(img_man)
14 f1shift = np.fft.fftshift(f1)
15 f1shift = f1shift*mask
16 f2shift = np.fft.ifftshift(f1shift) #對新的進行逆變換
17 img_new = np.fft.ifft2(f2shift)
18 #出來的是復數,無法顯示
19 img_new = np.abs(img_new)
20 #調整大小范圍便於顯示
21 img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
22 plt.subplot(122),plt.imshow(img_new,'gray'),plt.title('Highpass')
23 plt.xticks([]),plt.yticks([])

可以看到,高通濾波器有利於提取圖像的輪廓,這里我們從原理上分析一下為什么,圖像的輪廓或者邊緣或者一些噪聲處,灰度變化劇烈,那么在把它們經過傅里葉變換后,就會變成高頻信號(我們知道高頻時捕捉細節的),所以在把圖像低頻信號濾掉以后剩下的自然就是輪廓了。也可以這么說,灰度變化劇烈的地方是高頻信息,輪廓既是如此。傅立葉空間中亮度代表振幅,振幅越大,亮度越高,該頻率下信息越多,而相位則是蘊含着信息。

舉手投足山水間,溫文爾雅真君子,他與世界相遇 他自與世界相蝕 ,他自不辱使命 使他與眾生相聚。

反過來我們來看看空間域濾波中的拉普拉斯模板,現在我們把這個模板進行傅里葉變換到頻域看看:

1 import numpy as np
2 import matplotlib.pyplot as plt
4 laplacian = np.array([[0,1,0],[1,-4,1],[0,1,0]])
5 f = np.fft.fft2(laplacian)
6 f1shift = np.fft.fftshift(f)
7 img = np.log(np.abs(f1shift))
8 plt.imshow(img,'gray')

可以看到,這個模板的頻域變換下四周特別亮,也就是是個高通濾波器。其它空間域下的模板都可以轉到頻域下來看看。

下面再來試試低通濾波器什么效果,構造個低通濾波器也很簡單,把上述模板中的1變成0,0變成1,其實就是低通了:

 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 img_man = cv2.imread('lip',0) #直接讀為灰度圖像
 5 plt.subplot(121),plt.imshow(img_man,'gray'),plt.title('origial')
 6 plt.xticks([]),plt.yticks([])
 7 #--------------------------------
 8 rows,cols = img_man.shape
 9 mask = np.zeros(img_man.shape,np.uint8)
10 mask[rows//2-20:rows//2+20,cols//2-20:cols//2+20] = 1
11 #--------------------------------
12 f1 = np.fft.fft2(img_man)
13 f1shift = np.fft.fftshift(f1)
14 f1shift = f1shift*mask
15 f2shift = np.fft.ifftshift(f1shift) #對新的進行逆變換
16 img_new = np.fft.ifft2(f2shift)
17 #出來的是復數,無法顯示
18 img_new = np.abs(img_new)
19 #調整大小范圍便於顯示
20 img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
21 plt.subplot(122),plt.imshow(img_new,'gray'),plt.title('Highpass')
22 plt.xticks([]),plt.yticks([])
低通濾波器

可以看到低通濾波后圖像除了輪廓模糊了外,基本上沒什么變化,圖像的大部分信息基本上都保持了。從原理上來看,圖像的主要信息都集中在低頻上,所以低通濾波器的效果是這樣也是可以理解的。上述的高通、低通濾波器的構造有0,1構成的理想濾波器,也是最簡單的濾波器,還有一些其他的濾波器,比如說高斯濾波器,butterworth濾波器等等,下面是參考岡薩雷斯書上的圖:

 

 還有就是把高通低通都結合一部分到一個模板上形成的帶通濾波器,這在一些場合會很有用,還是以理想的帶通濾波器實驗下:

 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 img_man = cv2.imread('lip',0) #直接讀為灰度圖像
 5 plt.subplot(121),plt.imshow(img_man,'gray'),plt.title('origial')
 6 plt.xticks([]),plt.yticks([])
 7 #--------------------------------
 8 rows,cols = img_man.shape
 9 mask1 = np.ones(img_man.shape,np.uint8)
10 mask1[rows//2-8:rows//2+8,cols//2-8:cols//2+8] = 0
11 mask2 = np.zeros(img_man.shape,np.uint8)
12 mask2[rows//2-80:rows//2+80,cols//2-80:cols//2+80] = 1
13 mask = mask1*mask2
14 #--------------------------------
15 f1 = np.fft.fft2(img_man)
16 f1shift = np.fft.fftshift(f1)
17 f1shift = f1shift*mask
18 f2shift = np.fft.ifftshift(f1shift) #對新的進行逆變換
19 img_new = np.fft.ifft2(f2shift)
20 #出來的是復數,無法顯示
21 img_new = np.abs(img_new)
22 #調整大小范圍便於顯示
23 img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
24 plt.subplot(122),plt.imshow(img_new,'gray')
25 plt.xticks([]),plt.y
 1 import cv2
 2 import numpy as np
 3 import matplotlib.pyplot as plt
 4 img_man = cv2.imread('lip',0) #直接讀為灰度圖像
 5 plt.subplot(121),plt.imshow(img_man,'gray'),plt.title('origial')
 6 plt.xticks([]),plt.yticks([])
 7 #--------------------------------
 8 rows,cols = img_man.shape
 9 mask1 = np.ones(img_man.shape,np.uint8)
10 mask1[rows//2-8:rows//2+8,cols//2-8:cols//2+8] = 0
11 mask2 = np.zeros(img_man.shape,np.uint8)
12 mask2[rows//2-80:rows//2+80,cols//2-80:cols//2+80] = 1
13 mask = mask1*mask2
14 #--------------------------------
15 f1 = np.fft.fft2(img_man)
16 f1shift = np.fft.fftshift(f1)
17 f1shift = f1shift*mask
18 f2shift = np.fft.ifftshift(f1shift) #對新的進行逆變換
19 img_new = np.fft.ifft2(f2shift)
20 #出來的是復數,無法顯示
21 img_new = np.abs(img_new)
22 #調整大小范圍便於顯示
23 img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
24 plt.subplot(122),plt.imshow(img_new,'gray')
25 plt.xticks([]),plt.yticks([])

 

這就是帶通的效果,既可以保留一部分低頻,也可以保留一部分高頻,至於保留多少,怎么保留就視問題的不同而不同了。 

最后聲明幾點:

1.所有圖像處理部分的23.png,lip,v都是我自己測試時用的數據,在自己做圖像處理時可以直接替換成相應的文件名(執行的py文件要和圖像在同一目錄),其他代碼視情況改變,如果不是想執行其他功能,可以直接用。

2.結果的圖片沒有放上,因為用的linux系統,剛剛配置不想截圖浪費時間。

3.關於庫的問題,ananconda里有numpy,matplotlin.pyplot庫,但是cv2庫要自己下載,下載方法用pip,一句話,在終端輸入如下代碼

pip install opencv-python

至於pip的安裝:

linux下:

下載文件 wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate

執行安裝 python get-pip.py 這就安裝好了 

windows下:

參見網址

https://jingyan.baidu.com/article/ff42efa9d630e5c19e220207.html 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM