VTK修炼之道40:频域处理_快速傅里叶变换及其反变换1
生活随笔
收集整理的這篇文章主要介紹了
VTK修炼之道40:频域处理_快速傅里叶变换及其反变换1
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.圖像頻域處理的意義
在圖像處理和分析中,經常會將圖像從圖像空間轉換到其他空間中,并利用這些空間的特點進行對轉換后圖像進行分析處理,然后再將處理后的圖像轉換到圖像空間中,這稱之為圖像變換。 在一些圖像處理和分析中通過空間變換往往會取得更有效的結果。圖像頻域處理是指將圖像從圖像空間轉換到頻域空間進行處理的過程。最常用的頻域轉換是傅里葉變換。 傅里葉變換的計算量較大,人們為了提高速度,提出了快速傅里葉變換,并得到了廣泛的應用。本篇博客主要來學習VTK中的快速傅里葉變換。2.快速傅里葉變換及其逆變換
快速傅里葉變換(Fast Fourier Transform),簡稱做FFT。它是根據離散傅氏變換的奇、偶、虛、實等特性,對離散傅立葉變換的算法進行改進獲得的。傅里葉變換是可逆的,其逆變換為RFFT。 FFT在數字圖像處理中有著廣泛的應用,例如數字圖像頻域濾波,去噪,增強等等。 目前VTK中兩變換都已經實現,對應的類分別為vtkImageFFT和vtkImageRFFT。vtkImageFFT和vtkImageRFFT的輸入為實數或者復數數據,輸出都為復數數據。因此,vtkImageFFT與vtkImageRFFT的輸出結果不能直接顯示,因為VTK會將其當做彩色圖像顯示,需要通過vtkImageExtractComponents提取某一組分圖像顯示。
VTK頻率域的圖像處理步驟如下:
下面代碼演示了怎樣對圖像進行傅里葉變換,以及將傅里葉變換結果進行逆變換: #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL);#include <vtkSmartPointer.h> #include <vtkJPEGReader.h> #include <vtkImageFFT.h> #include <vtkImageExtractComponents.h> #include <vtkImageData.h> #include <vtkImageShiftScale.h> #include <vtkImageRFFT.h> #include <vtkImageActor.h> #include <vtkrenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleImage.h>int main() {vtkSmartPointer<vtkJPEGReader> reader =vtkSmartPointer<vtkJPEGReader>::New();reader->SetFileName("lena.jpg");reader->Update();//FFT//vtkSmartPointer<vtkImageFFT> imgFFT =vtkSmartPointer<vtkImageFFT>::New();imgFFT->SetInputConnection(reader->GetOutputPort());imgFFT->SetDimensionality(2);imgFFT->Update();// the resualts are complex, we shoule extract one component to displayvtkSmartPointer<vtkImageExtractComponents> imgComponent =vtkSmartPointer<vtkImageExtractComponents>::New();imgComponent->SetInputConnection(imgFFT->GetOutputPort());imgComponent->SetComponents(0);// norm image rangedouble Range[2];imgComponent->GetOutput()->GetScalarRange(Range);vtkSmartPointer<vtkImageShiftScale> imgfftShiftScale =vtkSmartPointer<vtkImageShiftScale>::New();imgfftShiftScale->SetOutputScalarTypeToUnsignedChar();imgfftShiftScale->SetScale(255.0 / (Range[1] - Range[0]));imgfftShiftScale->SetShift(-Range[0]);imgfftShiftScale->SetInputConnection(imgComponent->GetOutputPort());imgfftShiftScale->Update();//RFFT/vtkSmartPointer<vtkImageRFFT> imgRFFT =vtkSmartPointer<vtkImageRFFT>::New();imgRFFT->SetInputConnection(imgFFT->GetOutputPort());imgRFFT->SetDimensionality(2);imgRFFT->Update();vtkSmartPointer<vtkImageExtractComponents> imgComponetNew =vtkSmartPointer<vtkImageExtractComponents>::New();imgComponetNew->SetInputConnection(imgRFFT->GetOutputPort());imgComponetNew->SetComponents(0);double RangeNew[2];imgComponetNew->GetOutput()->GetScalarRange(RangeNew);vtkSmartPointer<vtkImageShiftScale> imgrfftShiftScale =vtkSmartPointer<vtkImageShiftScale>::New();imgrfftShiftScale->SetOutputScalarTypeToUnsignedChar();imgrfftShiftScale->SetScale(255.0 / (RangeNew[1] - RangeNew[0]));imgrfftShiftScale->SetInputConnection(imgComponetNew->GetOutputPort());imgrfftShiftScale->Update();/////謹記vtkImageActor僅能夠顯示UnsignedChar類型數據vtkSmartPointer<vtkImageActor> origActor =vtkSmartPointer<vtkImageActor>::New();origActor->SetInputData(reader->GetOutput());vtkSmartPointer<vtkImageActor> fftActor =vtkSmartPointer<vtkImageActor>::New();fftActor->SetInputData(imgFFT->GetOutput());vtkSmartPointer<vtkImageActor> rfftActor =vtkSmartPointer<vtkImageActor>::New();rfftActor->SetInputData(imgrfftShiftScale->GetOutput());///double origView[4] = { 0, 0, 0.33, 1 };double fftView[4] = { 0.33, 0, 0.66, 1 };double rfftView[4] = { 0.66, 0, 1, 1 };vtkSmartPointer<vtkRenderer> origRender =vtkSmartPointer<vtkRenderer>::New();origRender->SetViewport(origView);origRender->AddActor(origActor);origRender->ResetCamera();origRender->SetBackground(1, 0, 0);vtkSmartPointer<vtkRenderer> fftRender =vtkSmartPointer<vtkRenderer>::New();fftRender->SetViewport(fftView);fftRender->AddActor(fftActor);fftRender->ResetCamera();fftRender->SetBackground(0, 1, 0);vtkSmartPointer<vtkRenderer> rfftRender =vtkSmartPointer<vtkRenderer>::New();rfftRender->SetViewport(rfftView);rfftRender->AddActor(rfftActor);rfftRender->ResetCamera();rfftRender->SetBackground(0, 0, 1);/vtkSmartPointer<vtkRenderWindow> rw =vtkSmartPointer<vtkRenderWindow>::New();rw->AddRenderer(origRender);rw->AddRenderer(fftRender);rw->AddRenderer(rfftRender);rw->SetWindowName("Frequncy_FFT_RFFT");rw->SetSize(960, 320);vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();vtkSmartPointer<vtkInteractorStyleImage> style =vtkSmartPointer<vtkInteractorStyleImage>::New();rwi->SetInteractorStyle(style);rwi->SetRenderWindow(rw);rwi->Initialize();rwi->Start();return 0; }
首先建立一個JPEG圖像reader來讀取一副灰度圖像。然后定義一個vtkImageFFT指針,直接接收reader的輸出即原圖像數據作為輸入進行二維快速傅里葉變換。其輸出為一個像素類型為復數的vtkImageData數據,即每個像素值為兩個組分(Component):復數實部和虛部。因此如果直接顯示這個vtkImageData,會發現是一個彩色圖像。如果需要顯示頻域圖像,需要通過vtkImageExtractComponents類來提取某一個組分圖像來顯示。上例中通過定義vtkImageExtractComponents類指針,利用函數SetComponents(0)指定提取實部圖像顯示;由于vtkImageActor類僅支持unsigned char數據類型的圖像,利用vtkImageCast類的SetOutputScalarTypeToUnsignedChar()指定輸出類型為unsigned char,將FFT結果圖像轉換為需要的類型。
對于逆變換的過程也是類似。首先定義vtkImageRFFT指針,并接收輸入為vtkImageFFT指針的輸出,調用Update執行函數完成快速傅里葉逆變換。vtkImageRFFT的輸出同樣為一副復數圖像,通常不能直接顯示或者進行其他操作。對于傅里葉逆變換的圖像中虛數部分值為0,實數部分圖像即為重建的原始圖像。因此再次利用vtkImageExtractComponents提取實數部分圖像,并通過SetOutputScalarTypeToUnsignedChar()將圖像轉換為unsigned char類型進行顯示。 下圖為計算結果:
3.參看資料
1.《C++ primer》2.《The VTK User’s Guide – 11thEdition》
3. ?張曉東, 羅火靈. VTK圖形圖像開發進階[M]. 機械工業出版社, 2015.
總結
以上是生活随笔為你收集整理的VTK修炼之道40:频域处理_快速傅里叶变换及其反变换1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VTK修炼之道39:图像平滑_各向异性滤
- 下一篇: 刘翔博客答即时通信公司网友提问