1. 程式人生 > >簡單影象處理——傅立葉變換

簡單影象處理——傅立葉變換

學過訊號處理的都應該知道傅立葉變換

把時域上的訊號處理為頻域上的訊號疊加

對於在空間域上的數字影象,我們也能通過傅立葉變換轉換為頻域類的訊號

在實現某些影象處理的時候,頻域類的處理比空間域更簡單

好啦,我們來看看二維離散訊號的傅立葉變換

數字影象的二維離散傅立葉變換所得的結果的頻域成分如圖所示,左上角是直流成分,變換結果四個角周圍對應於低頻成分,中央部分對應於高頻部分。

為了便於觀察,我們常常使直流成分出現在視窗的中央,可採取換位方法,變換後中心為低頻,向外是高頻

我們來看看具體例項

複製程式碼 import cv

def FFT(image,flag = 0):
w
= image.width
h
= image.height
iTmp
= cv.CreateImage((w,h),cv.IPL_DEPTH_32F,1)
cv.Convert(image,iTmp)
iMat
= cv.CreateMat(h,w,cv.CV_32FC2)
mFFT
= cv.CreateMat(h,w,cv.CV_32FC2)
for i in range(h):
for j in range(w):
if flag == 0:
num
=-1if (i+j)%2==1else1else:
num
=1
iMat[i,j]
= (iTmp[i,j]*num,0)
cv.DFT(iMat,mFFT,cv.CV_DXT_FORWARD)
return mFFT

def FImage(mat):
w
= mat.cols
h
= mat.rows
size
= (w,h)
iAdd
= cv.CreateImage(size,cv.IPL_DEPTH_8U,1)
for i in range(h):
for j in range(w):
iAdd[i,j]
= mat[i,j][1]/h + mat[i,j][0]/h
return iAdd

image
= cv.LoadImage('
lena.jpg',0)
mAfterFFT
= FFT(image)
mBeginFFT
= FFT(image,1)
iAfter
= FImage(mAfterFFT)
iBegin
= FImage(mBeginFFT)

cv.ShowImage(
'image',image)
cv.ShowImage(
'iAfter',iAfter)
cv.ShowImage(
'iBegin',iBegin)

cv.WaitKey(0)
複製程式碼 這裡我們直接用了OpenCV的DFT演算法來做傅立葉變換

我們來看看效果吧

中間是沒有換位前,後面是換位後

在函式FFT中第二個引數是控制換位的

預設是換位的

按照此式計算,得到的傅立葉變換就是換位後的

現在我們來看看得到的頻域圖到底有什麼用吧

在分析影象訊號的頻率特性時,對於一幅影象,直流分量表示預想的平均灰度,低頻分量代表了大面積背景區域和緩慢變化部分,高頻部分代表了它的邊緣,細節,跳躍部分以及顆粒噪聲

在前面我們實現了影象在空域的模糊和銳化

其實在頻域,我們也能方便的實現影象的銳化和模糊

我們擷取頻率的低頻分量,對其作傅立葉反變換,得到的就是模糊後的影象

我們擷取頻率的高頻分量,對其作傅立葉反變換,得到的就是銳化後的影象

我們來編寫程式實現

複製程式碼 import cv

def FFT(image,flag = 0):
w
= image.width
h
= image.height
iTmp
= cv.CreateImage((w,h),cv.IPL_DEPTH_32F,1)
cv.Convert(image,iTmp)
iMat
= cv.CreateMat(h,w,cv.CV_32FC2)
mFFT
= cv.CreateMat(h,w,cv.CV_32FC2)
for i in range(h):
for j in range(w):
if flag == 0:
num
=-1if (i+j)%2==1else1else:
num
=1
iMat[i,j]
= (iTmp[i,j]*num,0)
cv.DFT(iMat,mFFT,cv.CV_DXT_FORWARD)
return mFFT

def IFFT(mat):
mIFFt
= cv.CreateMat(mat.rows,mat.cols,cv.CV_32FC2)
cv.DFT(mat,mIFFt,cv.CV_DXT_INVERSE)
return mIFFt

def Restore(mat):
w
= mat.cols
h
= mat.rows
size
= (w,h)
iRestore
= cv.CreateImage(size,cv.IPL_DEPTH_8U,1)
for i in range(h):
for j in range(w):
num
=-1if (i+j)%2==1else1
iRestore[i,j]
= mat[i,j][0]*num/(w*h)
return iRestore


def FImage(mat):
w
= mat.cols
h
= mat.rows
size
= (w,h)
# iReal = cv.CreateImage(size,cv.IPL_DEPTH_8U,1)# iIma = cv.CreateImage(size,cv.IPL_DEPTH_8U,1) iAdd = cv.CreateImage(size,cv.IPL_DEPTH_8U,1)
for i in range(h):
for j in range(w):
# iReal[i,j] = mat[i,j][0]/h# iIma[i,j] = mat[i,j][1]/h iAdd[i,j] = mat[i,j][1]/h + mat[i,j][0]/h
return iAdd


def Filter(mat,flag = 0,num =10):
mFilter
= cv.CreateMat(mat.rows,mat.cols,cv.CV_32FC2)
for i in range(mat.rows):
for j in range(mat.cols):
if flag == 0:
mFilter[i,j]
= (0,0)
else:
mFilter[i,j]
= mat[i,j]
for i in range(mat.rows/2-num,mat.rows/2+num):
for j in range(mat.cols/2-num,mat.cols/2+num):
if flag == 0:
mFilter[i,j]
= mat[i,j]
else:
mFilter[i,j]
= (0,0)
return mFilter

image
= cv.LoadImage('lena.jpg',0)
mFFT
= FFT(image)
mIFFt
= IFFT(mFFT)
iAfter
= FImage(mFFT)
mLP
= Filter(mFFT)
mIFFt1
=IFFT(mLP)
iLP
= FImage(mLP)
iRestore
= Restore(mIFFt1)

mHP
= Filter(mFFT,1)
mIFFt2
= IFFT(mHP)
iHP
= FImage(mHP)
iRestore2
= Restore(mIFFt2)

cv.ShowImage(
'image',image)
cv.ShowImage(
'iAfter',iAfter)
cv.ShowImage(
'iLP',iLP)
cv.ShowImage(
'iHP',iHP)
cv.ShowImage(
'iRestore',iRestore)
cv.ShowImage(
'iRestore2',iRestore2)

cv.WaitKey(0)
複製程式碼 執行效果如下

我們用一個矩形框,把頻域最中心的低頻部分過濾出來,反變換得到影象模糊後的樣子

把頻域最中心的高頻部分過濾出來,反變換得到影象銳化後的樣子

我們來看看一些規則影象的頻域影象

那個方形和菱形是隨手畫的,不是很標準,所以有很多幹擾

左邊是原圖

中間的普通的頻率變換

右邊的是對其進行對數擴充套件後的結果。在前面的灰度變換中,我們已經講過了灰度變換

參考資料: