opencv?傅里葉變換的實(shí)現(xiàn)
傅里葉變換
圖像處理一般分為空間域處理和頻率域處理。
空間域處理是直接對(duì)圖像內(nèi)的像素進(jìn)行處理。
空間域處理主要?jiǎng)澐譃榛叶茸儞Q和空間濾波兩種形式。
- 灰度變換是對(duì)圖像內(nèi)的單個(gè)像素進(jìn)行處理,比如調(diào)節(jié)對(duì)比度和處理閾值等。
- 空間濾波涉及圖像質(zhì)量的改變,例如圖像平滑處理。空間域處理的計(jì)算簡(jiǎn)單方便,運(yùn)算速度更快。
頻率域處理是先將圖像變換到頻率域,然后在頻率域?qū)D像進(jìn)行處理,最后再通過(guò)反變換將圖像從頻率域變換到空間域。
理論基礎(chǔ)
時(shí)間差,在傅里葉變換里就是相位。相位表述的是與時(shí)間差相關(guān)的信息。
在圖像處理過(guò)程中,傅里葉變換就是將圖像分解為正弦分量和余弦分量?jī)刹糠?,即將圖像從空間域轉(zhuǎn)換到頻域。
數(shù)字圖像經(jīng)過(guò)傅里葉變換后,得到的頻域值是復(fù)數(shù)。因此,顯示傅里葉變換的結(jié)果需要使用實(shí)數(shù)圖像(real image)加虛數(shù)圖像(complex image),或者幅度圖像(magnitude image)加相位圖像(phase image)的形式。
因?yàn)榉葓D像包含了原圖像中我們所需要的大部分信息,所以在圖像處理過(guò)程中,通常僅使用幅度圖像。
如果希望先在頻域內(nèi)對(duì)圖像進(jìn)行處理,再通過(guò)逆傅里葉變換得到修改后的空域圖像,就必須同時(shí)保留幅度圖像和相位圖像。
對(duì)圖像進(jìn)行傅里葉變換后,會(huì)得到圖像中的低頻和高頻信息。
低頻信息對(duì)應(yīng)圖像內(nèi)變化緩慢的灰度分量。高頻信息對(duì)應(yīng)圖像內(nèi)變化越來(lái)越快的灰度分量,是由灰度的尖銳過(guò)渡造成的。
傅里葉變換的目的,就是為了將圖像從空域轉(zhuǎn)換到頻域,并在頻域內(nèi)實(shí)現(xiàn)對(duì)圖像內(nèi)特定對(duì)象的處理,然后再對(duì)經(jīng)過(guò)處理的頻域圖像進(jìn)行逆傅里葉變換得到空域圖像。
傅里葉變換在圖像處理領(lǐng)域發(fā)揮著非常關(guān)鍵的作用,可以實(shí)現(xiàn)圖像增強(qiáng)、圖像去噪、邊緣檢測(cè)、特征提取、圖像壓縮和加密等。
Numpy實(shí)現(xiàn)傅里葉變換
Numpy模塊中的fft2()函數(shù)可以實(shí)現(xiàn)圖像的傅里葉變換。
實(shí)現(xiàn)傅里葉變換
Numpy提供的實(shí)現(xiàn)傅里葉變換的函數(shù)是numpy.fft.fft2(),它的語(yǔ)法格式是:
返回值 = numpy.fft.fft2(原始圖像)
參數(shù)“原始圖像”的類(lèi)型是灰度圖像,函數(shù)的返回值是一個(gè)復(fù)數(shù)數(shù)組(complex ndarray)。
經(jīng)過(guò)該函數(shù)的處理,就能得到圖像的頻譜信息。
此時(shí),圖像頻譜中的零頻率分量位于頻譜圖像(頻域圖像)的左上角
為了便于觀察,通常會(huì)使用numpy.fft.fftshift()函數(shù)將零頻率成分移動(dòng)到頻域圖像的中心位置。
函數(shù)numpy.fft.fftshift()的語(yǔ)法格式是:
返回值=numpy.fft.fftshift(原始頻譜)
使用該函數(shù)處理后,圖像頻譜中的零頻率分量會(huì)被移到頻域圖像的中心位置,對(duì)于觀察傅里葉變換后頻譜中的零頻率部分非常有效。
對(duì)圖像進(jìn)行傅里葉變換后,得到的是一個(gè)復(fù)數(shù)數(shù)組。
為了顯示為圖像,需要將它們的值調(diào)整到[0, 255]的灰度空間內(nèi),使用的公式為:
像素新值=20*np.log(np.abs(頻譜值))
用Numpy實(shí)現(xiàn)傅里葉變換,觀察得到的頻譜圖像。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png',0) f = np.fft.fft2(img) fshift = np.fft.fftshift(f) magnitude_spectrum = 20*np.log(np.abs(fshift)) plt.subplot(121) plt.imshow(img, cmap = 'gray') plt.title('original') plt.axis('off') plt.subplot(122) plt.imshow(magnitude_spectrum, cmap = 'gray') plt.title('result') plt.axis('off') plt.show()
實(shí)現(xiàn)逆傅里葉變換
注意: 如果在傅里葉變換過(guò)程中使用了numpy.fft.fftshift()函數(shù)移動(dòng)零頻率分量,那么在逆傅里葉變換過(guò)程中,需要先使用numpy.fft.ifftshift()函數(shù)將零頻率分量移到原來(lái)的位置,再進(jìn)行逆傅里葉變換
函數(shù)numpy.fft.ifftshift()是numpy.fft.fftshift()的逆函數(shù),其語(yǔ)法格式為:
調(diào)整后的頻譜 = numpy.fft.ifftshift(原始頻譜)
numpy.fft.ifft2()函數(shù)可以實(shí)現(xiàn)逆傅里葉變換,返回空域復(fù)數(shù)數(shù)組。
它是numpy.fft.fft2()的逆函數(shù),該函數(shù)的語(yǔ)法格式為:
返回值=numpy.fft.ifft2(頻域數(shù)據(jù))
函數(shù)numpy.fft.ifft2()的返回值仍舊是一個(gè)復(fù)數(shù)數(shù)組(complex ndarray)。
逆傅里葉變換得到的空域信息是一個(gè)復(fù)數(shù)數(shù)組,需要將該信息調(diào)整至[0, 255]灰度空間內(nèi),使用的公式為:
iimg = np.abs(逆傅里葉變換結(jié)果)
在Numpy內(nèi)實(shí)現(xiàn)傅里葉變換、逆傅里葉變換,觀察逆傅里葉變換的結(jié)果圖像。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png',0) f = np.fft.fft2(img) fshift = np.fft.fftshift(f) ishift = np.fft.ifftshift(fshift) iimg = np.fft.ifft2(ishift) iimg = np.abs(iimg) plt.subplot(121), plt.imshow(img, cmap = 'gray') plt.title('original'), plt.axis('off') plt.subplot(122), plt.imshow(iimg, cmap = 'gray') plt.title('iimg'), plt.axis('off') plt.show()
高通濾波示例
一幅圖像內(nèi),同時(shí)存在著高頻信號(hào)和低頻信號(hào)。
- 低頻信號(hào)對(duì)應(yīng)圖像內(nèi)變化緩慢的灰度分量。例如,在一幅大草原的圖像中,低頻信號(hào)對(duì)應(yīng)著顏色趨于一致的廣袤草原。
- 高頻信號(hào)對(duì)應(yīng)圖像內(nèi)變化越來(lái)越快的灰度分量,是由灰度的尖銳過(guò)渡造成的。如果在上面的大草原圖像中還有一頭獅子,那么高頻信號(hào)就對(duì)應(yīng)著獅子的邊緣等信息。
濾波器能夠允許一定頻率的分量通過(guò)或者拒絕其通過(guò),按照其作用方式可以劃分為低通濾波器和高通濾波器。
- 允許低頻信號(hào)通過(guò)的濾波器稱(chēng)為低通濾波器。低通濾波器使高頻信號(hào)衰減而對(duì)低頻信號(hào)放行,會(huì)使圖像變模糊。
- 允許高頻信號(hào)通過(guò)的濾波器稱(chēng)為高通濾波器。高通濾波器使低頻信號(hào)衰減而讓高頻信號(hào)通過(guò),將增強(qiáng)圖像中尖銳的細(xì)節(jié),但是會(huì)導(dǎo)致圖像的對(duì)比度降低。
傅里葉變換可以將圖像的高頻信號(hào)和低頻信號(hào)分離。
通過(guò)對(duì)圖像的頻域處理,可以實(shí)現(xiàn)圖像增強(qiáng)、圖像去噪、邊緣檢測(cè)、特征提取、壓縮和加密等操作。
在Numpy內(nèi)對(duì)圖像進(jìn)行傅里葉變換,得到其頻域圖像。然后,在頻域內(nèi)將低頻分量的值處理為0,實(shí)現(xiàn)高通濾波。最后,對(duì)圖像進(jìn)行逆傅里葉變換,得到恢復(fù)的原始圖像。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png',0) f = np.fft.fft2(img) fshift = np.fft.fftshift(f) rows, cols = img.shape crow, ccol = int(rows/2) , int(cols/2) fshift[crow-30:crow+30, ccol-30:ccol+30] = 0 ishift = np.fft.ifftshift(fshift) iimg = np.fft.ifft2(ishift) iimg = np.abs(iimg) plt.subplot(121), plt.imshow(img, cmap = 'gray') plt.title('original'), plt.axis('off') plt.subplot(122), plt.imshow(iimg, cmap = 'gray') plt.title('iimg'), plt.axis('off') plt.show()
OpenCV實(shí)現(xiàn)傅里葉變換
OpenCV提供了函數(shù)cv2.dft()和cv2.idft()來(lái)實(shí)現(xiàn)傅里葉變換和逆傅里葉變換
實(shí)現(xiàn)傅里葉變換
函數(shù)cv2.dft()的語(yǔ)法格式為:
返回結(jié)果=cv2.dft(原始圖像,轉(zhuǎn)換標(biāo)識(shí))
在使用該函數(shù)時(shí),需要注意參數(shù)的使用規(guī)范:
- 對(duì)于參數(shù)“原始圖像”,要首先使用np.float32()函數(shù)將圖像轉(zhuǎn)換成np.float32格式。
- “轉(zhuǎn)換標(biāo)識(shí)”的值通常為“cv2.DFT_COMPLEX_OUTPUT”,用來(lái)輸出一個(gè)復(fù)數(shù)陣列。
函數(shù)cv2.dft()返回的結(jié)果與使用Numpy進(jìn)行傅里葉變換得到的結(jié)果是一致的,但是它返回的值是雙通道的,第1個(gè)通道是結(jié)果的實(shí)數(shù)部分,第2個(gè)通道是結(jié)果的虛數(shù)部分。
經(jīng)過(guò)函數(shù)cv2.dft()的變換后,得到了原始圖像的頻譜信息。
此時(shí),零頻率分量并不在中心位置,為了處理方便需要將其移至中心位置,可以用函數(shù)numpy.fft.fftshift()實(shí)現(xiàn)。
例如,如下語(yǔ)句將頻譜圖像dft中的零頻率分量移到頻譜中心,得到了零頻率分量位于中心的頻譜圖像dftshift。
dftShift = np.fft.fftshift(dft)
經(jīng)過(guò)上述處理后,頻譜圖像還只是一個(gè)由實(shí)部和虛部構(gòu)成的值。要將其顯示出來(lái),還要做進(jìn)一步的處理才行。
函數(shù)cv2.magnitude()可以計(jì)算頻譜信息的幅度。該函數(shù)的語(yǔ)法格式為:
返回值=cv2.magnitude(參數(shù)1,參數(shù)2)
- 參數(shù)1:浮點(diǎn)型x坐標(biāo)值,也就是實(shí)部。
- 參數(shù)2:浮點(diǎn)型y坐標(biāo)值,也就是虛部,它必須和參數(shù)1具有相同的size
函數(shù)cv2.magnitude()的返回值是參數(shù)1和參數(shù)2的平方和的平方根,公式為:
得到頻譜信息的幅度后,通常還要對(duì)幅度值做進(jìn)一步的轉(zhuǎn)換,以便將頻譜信息以圖像的形式展示出來(lái)。簡(jiǎn)單來(lái)說(shuō),就是需要將幅度值映射到灰度圖像的灰度空間[0, 255]內(nèi),使其以灰度圖像的形式顯示出來(lái)。
這里使用的公式為:
result = 20*np.log(cv2.magnitude(實(shí)部,虛部))
import numpy as np import cv2 img = cv2.imread('./img/hand1.jpg',0) dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) print(dft) dftShift = np.fft.fftshift(dft) print(dftShift) result = 20*np.log(cv2.magnitude(dftShift[:, :,0], dftShift[:, :,1])) #兩個(gè)參數(shù),需要拆分通道print(result)
用OpenCV函數(shù)對(duì)圖像進(jìn)行傅里葉變換,并展示其頻譜信息。
import numpy as np import cv2 import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png',0) dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) dftShift = np.fft.fftshift(dft) result = 20*np.log(cv2.magnitude(dftShift[:, :,0], dftShift[:, :,1])) plt.subplot(121), plt.imshow(img, cmap = 'gray') plt.title('original'), plt.axis('off') plt.subplot(122), plt.imshow(result, cmap = 'gray') plt.title('result'), plt.axis('off') plt.show()
實(shí)現(xiàn)逆傅里葉變換
在OpenCV中,使用函數(shù)cv2.idft()實(shí)現(xiàn)逆傅里葉變換,該函數(shù)是傅里葉變換函數(shù)cv2.dft()的逆函數(shù)。其語(yǔ)法格式為:
返回結(jié)果=cv2.idft(原始數(shù)據(jù))
對(duì)圖像進(jìn)行傅里葉變換后,通常會(huì)將零頻率分量移至頻譜圖像的中心位置。如果使用函數(shù)numpy.fft.fftshift()移動(dòng)了零頻率分量,那么在進(jìn)行逆傅里葉變換前,要使用函數(shù)numpy.fft.ifftshift()將零頻率分量恢復(fù)到原來(lái)位置。
注意: 在進(jìn)行逆傅里葉變換后,得到的值仍舊是復(fù)數(shù),需要使用函數(shù)cv2.magnitude()計(jì)算其幅度。
用OpenCV函數(shù)對(duì)圖像進(jìn)行傅里葉變換、逆傅里葉變換,并展示原始圖像及經(jīng)過(guò)逆傅里葉變換后得到的圖像。
import numpy as np import cv2 import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png',0) dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) dftShift = np.fft.fftshift(dft) ishift = np.fft.ifftshift(dftShift) iImg = cv2.idft(ishift) iImg= cv2.magnitude(iImg[:, :,0], iImg[:, :,1]) # 計(jì)算幅度 plt.subplot(121), plt.imshow(img, cmap = 'gray') plt.title('original'), plt.axis('off') plt.subplot(122), plt.imshow(iImg, cmap = 'gray') plt.title('inverse'), plt.axis('off') plt.show()
低通濾波示例
在一幅圖像內(nèi),低頻信號(hào)對(duì)應(yīng)圖像內(nèi)變化緩慢的灰度分量。圖像進(jìn)行低通濾波后會(huì)變模糊。
實(shí)現(xiàn)的中間步驟
rows, cols = img.shape crow, ccol = int(rows/2) , int(cols/2) mask = np.zeros((rows, cols,2), np.uint8) # 二維的原因,有實(shí)部和虛部 mask[crow-30:crow+30, ccol-30:ccol+30,:] = 1
然后,將其與頻譜圖像進(jìn)行運(yùn)算,實(shí)現(xiàn)低通濾波。這里采用的運(yùn)算形式是:
fShift = dftShift*mask
使用函數(shù)cv2.dft()對(duì)圖像進(jìn)行傅里葉變換,得到其頻譜圖像。然后,在頻域內(nèi)將其高頻分量的值處理為0,實(shí)現(xiàn)低通濾波。最后,對(duì)圖像進(jìn)行逆傅里葉變換,得到恢復(fù)的原始圖像。
import numpy as np import cv2 import matplotlib.pyplot as plt img = cv2.imread('./img/hand1.png',0) dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) dftShift = np.fft.fftshift(dft) rows, cols = img.shape crow, ccol = int(rows/2) , int(cols/2) mask = np.zeros((rows, cols,2), np.uint8) #兩個(gè)通道,與頻域圖像匹配 mask[crow-30:crow+30, ccol-30:ccol+30,:] = 1 fShift = dftShift*mask ishift = np.fft.ifftshift(fShift) iImg = cv2.idft(ishift) iImg= cv2.magnitude(iImg[:, :,0], iImg[:, :,1]) plt.subplot(121), plt.imshow(img, cmap = 'gray') plt.title('original'), plt.axis('off') plt.subplot(122), plt.imshow(iImg, cmap = 'gray') plt.title('inverse'), plt.axis('off') plt.show()
經(jīng)過(guò)低通濾波后,圖像的邊緣信息被削弱了。
時(shí)域卷積 --> 頻域乘積
到此這篇關(guān)于opencv 傅里葉變換的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)opencv 傅里葉變換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python進(jìn)階教程之函數(shù)參數(shù)的多種傳遞方法
這篇文章主要介紹了python進(jìn)階教程之函數(shù)參數(shù)的多種傳遞方法,包括關(guān)鍵字傳遞、默認(rèn)值傳遞、包裹位置傳遞、包裹關(guān)鍵字混合傳遞等,需要的朋友可以參考下2014-08-08Python入門(mén)教程 超詳細(xì)1小時(shí)學(xué)會(huì)Python
本文適合有經(jīng)驗(yàn)的程序員盡快進(jìn)入Python世界.特別地,如果你掌握J(rèn)ava和Javascript,不用1小時(shí)你就可以用Python快速流暢地寫(xiě)有用的Python程序.2006-09-09Django使用uwsgi部署時(shí)的配置以及django日志文件的處理方法
今天小編就為大家分享一篇Django使用uwsgi部署時(shí)的配置以及django日志文件的處理方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08Python使用Scrapy爬蟲(chóng)框架全站爬取圖片并保存本地的實(shí)現(xiàn)代碼
這篇文章主要介紹了Python使用Scrapy爬蟲(chóng)框架全站爬取圖片并保存本地的實(shí)現(xiàn)代碼,需要的朋友可以參考下2018-03-03pandas combine_first函數(shù)處理兩個(gè)數(shù)據(jù)集重疊和缺失
combine_first是pandas中的一個(gè)函數(shù),它可以將兩個(gè)DataFrame對(duì)象按照索引進(jìn)行合并,用一個(gè)對(duì)象中的非空值填充另一個(gè)對(duì)象中的空值,這個(gè)函數(shù)非常適合處理兩個(gè)數(shù)據(jù)集有部分重疊和缺失的情況,可以實(shí)現(xiàn)數(shù)據(jù)的補(bǔ)全和更新,本文介紹combine_first函數(shù)的語(yǔ)法及一些案例應(yīng)用2024-01-01