圖像處理一般分為空間域處理和頻率域處理
空間域處理是直接對圖像內的像素進行處理。主要划分為灰度變換核空間濾波兩種形式,
灰度變換對圖像內的單個像素進行處理,濾波處理涉及對圖像質量的改變
頻率域處理是先將圖像變換到頻率域,然后在頻率域對圖像進行處理,最后通過反變換將圖像變為空間域。
傅里葉變換可以將圖像變換為頻率域, 傅立葉反變換將頻率域變換為空間域
時域是以時間為坐標軸表示動態信號的關系, 頻域則是把信號變為一頻率為坐標軸表示出來。
時域是實際存在的,而頻域則是數學構造。
numpy實現傅里葉變換
函數
dst = numpy.fft.fft2(src)
dst為一個復數數組
src 原始圖像的類型應是灰度圖像
該函數處理之后就能得到圖像的頻譜信息
零頻率分量位於頻譜圖像的左上角
函數
dst = numpy.ffr.fftshift(src)
使用該函數處理后,圖像頻譜中的零頻率分量會被移到頻域圖像的中心位置
對圖像傅里葉變換后得到的是一個復數數組,為了顯示圖像需要將他們的值調整到 [0 , 255 ] 的灰度空間
公式為
像素新值 = 20 * np.log( np.abs( 頻譜值 ) )
1 import cv2 2 import numpy as np 3 import matplotlib.pyplot as plt 4 img = cv2.imread("/home/miao/dog.jpg", 0) 5 f = np.fft.fft2(img) 6 fshift = np.fft.fftshift(f) 7 f_img = 20 * np.log(np.abs(f)) 8 magnitude_spectrum = 20 * np.log(np.abs(fshift)) 9 plt.subplot(221) 10 plt.imshow(img , cmap = 'gray') 11 plt.title('original') 12 plt.axis('off') 13 plt.subplot(222) 14 plt.imshow(f_img , cmap = 'gray') 15 plt.title('f_img') 16 plt.axis('off') 17 plt.subplot(223) 18 plt.imshow(magnitude_spectrum , cmap = 'gray') 19 plt.title("magnitude_spectrum") 20 plt.axis('off') 21 plt.show()
書上和查到的一些資料說傅里葉變換后的圖像頻譜的零頻率分量位於頻譜圖像的左上角
通過實際操作后得到的圖像 f_img 所示 零頻率分量分布於四個角, 不知為何,望指教!
對於一張圖片進行傅里葉變換就是將它分解為正弦和余弦兩部分,以完成從空間域到頻域的轉換。在轉換到頻域時以復數的形式存在,因此變換后的結果需要使用實數圖像和虛數圖像,或者幅度圖像加相位圖像的形式。但是在實際處理當中僅僅使用了幅度圖像(magitude Image),因為幅度圖像包含了幾乎所有的原圖像的幾何信息。但是如果想用傅里葉逆變換就需要同時保留幅度圖像和相位圖像,才能實現對原圖像的操作。
在頻域里,對於一幅圖像,高頻部分代表了圖像的、紋理信息;低頻部分則代表了圖像的輪廓信息。如果圖像受到的噪聲恰好在某個特定的頻率范圍內,就可以使用濾波器來恢復原來的圖像。因此傅里葉變換在圖像處理中可以做到圖像增強和去噪、圖像分割之邊緣檢測、圖像特征提取和壓縮等。
magnitude_spectrum可以看到中間白色區域,表示低頻內容更多
實現逆傅里葉變換
numpy.fft.fftshift()函數移動了零頻率分量,在逆傅里葉變換中需要使用numpy.fft.ifftshift()函數將零頻率分量一道原來位置
在進行逆傅里葉變換
函數numpy.fft.ifft2() 是先逆傅里葉變換 返回值仍舊是一個復數數組
需要將信息調整至[ 0 , 255 ]灰度空間內, 使用公式
iimg = np.abs( 逆傅里葉變換結果)
1 import cv2 2 import numpy as np 3 import matplotlib.pyplot as plt 4 img = cv2.imread("/home/miao/dog.jpg", 0) 5 f = np.fft.fft2(img) 6 fshift = np.fft.fftshift(f) 7 ishift = np.fft.ifftshift(fshift) 8 iimg = np.fft.ifft2(ishift) 9 print(img) 10 iimg = np.abs(iimg) 11 print(iimg) 12 plt.subplot(121) 13 plt.imshow(img , cmap = 'gray') 14 plt.title('original') 15 plt.axis('off') 16 plt.subplot(122) 17 plt.imshow(iimg , cmap = 'gray') 18 plt.title('iimg') 19 plt.axis('off') 20 plt.show()
OpenCv實現傅里葉變換
函數
cv2.dft() 和 cv2.idft()
返回結果 = cv2.dft( 原始圖像, 轉換標識 )
原始圖像 首先要使用np.float32() 函數將圖像轉換為np.float32格式
轉換標識的值通常為cv2.DFT_COMPLEX_OUTPUT 用來輸出一個復數陣列
函數cv2.dft()返回的結果和numpy進行傅里葉變換得到的結果一致 , 但是他返回的值是雙通道的
第1通道是結果的實數部分,第2通道是結果的虛數部分
使用函數cv2.dft()之后同樣需要函數numpy.fft.fftshift()實現將零頻率分量移到頻譜中心
之后要將其顯示出來還要使用函數cv2.magnitude()計算頻譜信息的幅度,函數形式
返回值 = cv2.magnitude(參數一,參數二)
參數一:浮點型x坐標值,也就是實部
參數二:浮點型y坐標值,也就是虛部,和參數一具有相同的位數
返回值為 參數一和參數二的平方和的平方根
得到頻譜信息的幅度后,通常還要對幅度值進一步轉換,以便將圖像顯示出來,
即將幅度值映射到灰度值的灰度空間[0,255]內,
即公式 result = 20 * np.log( cv2.magnitude(實部,虛部))
1 import cv2 2 import numpy as np 3 img = cv2.imread("/home/miao/dog.jpg" , 0) 4 dft = cv2.dft( np.float32(img) , flags = cv2.DFT_COMPLEX_OUTPUT) 5 print("dft = \n" ,dft) 6 dftshift = np.fft.fftshift(dft) 7 print("dftshift = \n" , dftshift) 8 result = 20 * np.log(cv2.magnitude(dftshift[:,:,0] , dftshift[:,:,1])) 9 print("result = \n" , result)
dft
[[[ 5442629. 0. ] [ 112638.86 720144.94 ] [ 199291.6 295989.75 ] ... [ -73885.945 -117819.76 ] [ 199291.6 -295989.75 ] [ 112638.86 -720144.94 ]] [[-2031877. 118866.445] [ -290884.75 -240315.62 ] [ -69323.47 -217808.45 ] ... [ -80757.25 -214683.94 ] [ 87689.74 -263512.44 ] [ -298817.5 465312.25 ]] [[ 117940.055 419359.5 ] [ 226322.28 229652.14 ] [ -170327.42 -338387.7 ] ... [ -68762.08 216805.8 ] [ -248173.78 344444.22 ] [ 167779.88 156720.78 ]] ... [[ 203563.9 -291130.38 ] [ 31911.941 267805.7 ] [ 142347.9 116130.445] ... [ -151712.56 -62466.57 ] [ -239283.3 -319897.38 ] [ -128576.625 41041.527]] [[ 117940.06 -419359.53 ] [ 167779.88 -156720.78 ] [ -248173.78 -344444.22 ] ... [ 78999.33 209142.4 ] [ -170327.42 338387.7 ] [ 226322.28 -229652.14 ]] [[-2031877.1 -118866.48 ] [ -298817.5 -465312.25 ] [ 87689.74 263512.44 ] ... [ 158813.72 -68133.9 ] [ -69323.47 217808.45 ] [ -290884.75 240315.62 ]]]
dftshift
[[[-3.05175781e-05 1.81000122e+02] [-2.21242020e+02 4.47310547e+02] [-4.91660858e+02 -3.89533997e+02] ... [-7.22862366e+02 -5.56106812e+02] [ 4.91660858e+02 -3.89533997e+02] [ 2.21242020e+02 4.47310547e+02]] [[-5.04687836e+02 -1.13754280e+02] [ 3.67620728e+02 -5.22734070e+02] [ 2.31780884e+02 3.46142975e+02] ... [-1.25527039e+02 3.59883911e+02] [-2.29090759e+02 1.01479324e+02] [-5.85184814e+02 -2.68481232e+02]] [[ 2.69147797e+02 9.58936920e+01] [-3.20615723e+02 2.28430405e+02] [-3.35807678e+02 -5.58035095e+02] ... [ 4.27737488e+02 -3.72080078e+02] [ 3.80756531e+01 2.09622498e+02] [ 2.67722412e+02 -4.23770844e+02]] ... [[-4.27722015e+02 -1.86195862e+02] [ 4.19498779e+02 2.00292221e+02] [-5.37565613e+01 3.44412720e+02] ... [-3.42792969e+01 7.90777832e+02] [-6.05357666e+02 1.66101379e+01] [-1.82286621e+02 -1.37281662e+02]] [[-2.69147888e+02 9.58937073e+01] [-2.67722412e+02 -4.23770844e+02] [-3.80756531e+01 2.09622498e+02] ... [ 4.04659668e+02 -5.31339905e+02] [ 3.35807678e+02 -5.58035095e+02] [ 3.20615723e+02 2.28430405e+02]] [[ 5.04687744e+02 -1.13754257e+02] [ 5.85184814e+02 -2.68481232e+02] [ 2.29090759e+02 1.01479324e+02] ... [ 4.21408844e+02 3.88300781e+02] [-2.31780884e+02 3.46142975e+02] [-3.67620728e+02 -5.22734070e+02]]]
result 可以看出值的范圍在 [0 , 255]
[[103.969955 124.25348 128.82753 ... 136.3133 128.82753 124.25348 ] [124.97435 129.19992 120.64148 ... 118.86374 110.47402 129.34885 ] [113.10027 119.510185 129.57889 ... 126.804504 107.23077 124.342316] ... [122.90482 122.834785 117.077515 ... 133.47913 128.12392 108.60434 ] [113.10028 124.342316 107.23077 ... 130.08235 129.57889 119.510185] [124.97435 129.34885 110.47402 ... 127.018745 120.64148 129.19992 ]]
逆變換
1 import cv2 2 import numpy as np 3 import matplotlib.pyplot as plt 4 img = cv2.imread("/home/miao/dog.jpg" , 0) 5 dft = cv2.dft(np.float32(img) , flags = cv2.DFT_COMPLEX_OUTPUT) 6 dftshift = np.fft.fftshift(dft) 7 ishift = np.fft.ifftshift(dftshift) 8 iimg = cv2.idft(ishift) 9 iimg = cv2.magnitude(iimg[:,:,0] , iimg[:,:,1]) 10 Iimg = 20 * np.log(iimg) 11 plt.subplot(221) 12 plt.imshow(img,cmap = 'gray') 13 plt.title("original") 14 plt.axis("off") 15 16 plt.subplot(222) 17 plt.imshow(iimg,cmap = 'gray') 18 plt.title("imverse") 19 plt.axis("off") 20 21 plt.show()
低通高通濾波示例
高通
通過對傅里葉變換后的頻譜圖像中間部分即低頻分量的值替換為0,就屏蔽了低頻,實現高通
低通
與高通相反將傅里葉變換后的中間低頻部分之外的高頻信號值替換為0,實現了低通
1 import cv2 2 import numpy as np 3 import matplotlib.pyplot as plt 4 img = cv2.imread("/home/miao/dog.jpg" , 0) 5 f = np.fft.fft2(img) 6 fshift = np.fft.fftshift(f) 7 rows , cols = img.shape 8 crow , ccol = int(rows/2) , int(cols/2) 9 # 10 mask = np.zeros((rows , cols ) , np.uint8) 11 mask[crow-30:crow+30 , ccol-30:ccol+30] = 1 12 l_shift = fshift.copy() 13 h_shift = fshift.copy() 14 l_shift[crow-30:crow+30 , ccol-30:ccol+30] = 0 15 h_shift = fshift * mask 16 # 17 l_ishift = np.fft.ifftshift(l_shift) 18 h_ishift = np.fft.ifftshift(h_shift) 19 ishift = np.fft.ifftshift(fshift) 20 # 21 iimg = np.fft.ifft2(ishift) 22 l_img = np.fft.ifft2(l_shift) 23 h_img = np.fft.ifft2(h_shift) 24 # 25 iimg = np.abs(iimg) 26 l_img = np.abs(l_img) 27 h_img = np.abs(h_img) 28 # 29 plt.subplot(221) , plt.imshow(img , cmap = 'gray') 30 plt.title('original') , plt.axis('off') 31 # 32 plt.subplot(222) , plt.imshow(l_img , cmap = 'gray') 33 plt.title('l_img') , plt.axis('off') 34 # 35 plt.subplot(223) , plt.imshow(h_img , cmap = 'gray') 36 plt.title('h_img') , plt.axis('off') 37 # 38 plt.subplot(224) , plt.imshow(iimg , cmap = 'gray') 39 plt.title('iimg') , plt.axis('off') 40 plt.show()
12,13行復制圖像時需要進行深復制,