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修炼之道62:体绘制_固定点光线投影体绘制与GPU加速光线投影体绘制
1.固定点光线投影算法 vtkFixedPointVolumeRayCastMapper是一个较好的vtkVolumeRayCastMapper的替代者.该类能够实现基于Alpha合成的体绘制方法和最 ...
- VTK修炼之道60:体绘制_体绘制管线图形渲染管线
1.几何渲染与体绘制 1.1 几何渲染 前面练习的渲染技术都是几何渲染技术.所谓的几何渲染技术,就是通过绘制几何图元(顶点.线段.面片等)来渲染数据,例如:绘制图像需要在空间中建立一个四边形图元,然后 ...
- VTK修炼之道15:图像处理_显示(vtkImageViewer2 vtkImageActor)
1.vtkImageViewer2用于图像显示实例分析 在VTK早期版本中,提供了vtkImageViewer类来显示图像.随着版本的发展,目前vtkImageViewer2代替了vtkImageVi ...
- VTK修炼之道14:图像处理_创建
1.引言:图像数据结构 数字图像文件内容由两个部分组成:图像头信息和数据.图像头信息定义了图像的基本信息,主要包括起点位置(Origin),像素间隔(space)和维数(dimension).通过这三 ...
- VTK修炼之道61:体绘制_光线投影+最大密度投影+等值面法
1.vtkVolumeMapper vtkVolumeMapper是所有体绘制Mapper类的虚基类,提供接口函数,并由其子类实现具体功能.该类的继承关系如下图所示: 应该掌握一些常用的体绘制类. 2 ...
- VTK修炼之道39:图像平滑_各向异性滤波
1.各向异性扩散滤波 高斯平滑方法在平滑噪声的同时,模糊了图像的重要边缘图像. 各向异性滤波是一种基于偏微分方程的滤波技术,建立于热量的各向异性扩散理论. 各向异性滤波在图像的平坦区域选择大尺度平滑, ...
- VTK修炼之道38:图像平滑_中值滤波器
1.中值滤波 vtkImageHybridMedian2D实现了对二维图像的中值滤波.其实现原理是,采用一个5x5的模板,逐次将模板中心对应于图像的每个像素上,将模板图像覆盖的像素的中值作为当前像素的 ...
- VTK修炼之道37:图像平滑_高斯滤波器
1.高斯滤波 高斯平滑的原理类似于均值滤波.均值滤波模板的系数都是一样的,而高斯平滑则是需要根据像素与模板中心的距离来定义权重.权重的计算方法是采用高斯分布,离中心越远,权重越小. 下面是一个利用Ga ...
- VTK修炼之道36:图像平滑_均值滤波器
1.图像平滑 图像平滑常用于图像的预处理中,如计算梯度时先对图像进行平滑处理,可以减少噪声对梯度的影响.图像平滑一般是通过模板卷积运算实现.模板可以看做是一个大小为nxn的小图像,例如3x3,5x5等 ...
最新文章
- HTTP请求时connectionRequestTimeout 、connectionTimeout、socketTimeout三个超时时间的含义...
- 字节跳动的敌人,只有时间
- html5 生存游戏,html5版生命游戏
- 类似Tinder APP的配对逻辑
- OneNET物联网云平台HTTP数据流上传与下发,使用Fiddler调试开关应用,stm32 esp8266物联网家居远程开关
- Python学习之路3 - 字符串操作字典
- 用Ruby读取Excel文件
- 设计文档应该怎么写?
- Linux中ffmpeg批量压缩音频
- 【重要】股票收益互换
- 计算机类课题研究方法,课题研究方法有哪些
- Kibana坐标地图example
- 如何将pdf转word?这几个软件可以做到文档格式转换
- 元芳,你怎么看?元芳是谁?
- HPUoj1210: OY问题 [搜索](DFS
- 目前流行的机器学习算法
- 如何使用U-Net-train进行语义分段,并在Keras中测试您的自定义数据
- redis stream持久化_[灌水] Redis 的持久化
- 快速看懂SaaS、CRM、OA、ERP、HR、进销存系统
- 安裝wgt文件失败[-1205]:WGT安装包中manifest.json文件的version版本不匹配