前言
“VTK图形图像开发进阶_张晓东_罗火灵”的学习笔记。
东灵工作室 教程系列导航:http://blog.csdn.net/www_doling_net/article/details/8763686
学习资料
VTK官网学习地址:https://vtk.org/doc/nightly/html/
图像的频域处理
频域处理是指根据一定的图像模型,对图像频谱进行不同程度修改的技术,通常作如下假设:
1.引起图像质量下降的噪声占频谱的高频段.
2.图像边缘占高频段
3.图像主体或灰度缓变区域占低频段.
基于这些假设,可以频谱的各个频段进行有选择性的修改。
图像频域处理借助空间变换将图像从图像空间转换到频域空间,根据频域空间的性质对数据进行处理(如滤波),最后通过空间变换将处理后的数 据变换至图像空间。
最常用的频域转换是傅里叶变换。
快速傅里叶变换(FFT)
FFT是可逆的,其逆变换为RFFTo。FFT 在数字图像处理中有着广泛的应用,例如数字图像频域滤波、去噪、增强等。目前,在VTK 中FFT和RFFT这两种变换都已经实现,对应的类分别为vtklmageFFT和vtklmageRFFT。
vtklmageFFT和vtklmageRFFT的输入为实数或复数数据,输出均为复数数据。因此, vtklmageFFT与vtklmageRFFT的输出结果不能直接显示,因为VTK会将其当作彩色图像显 示,需要通过vtklmageExtractComponents类提取某一组分进行图像显示。
#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageFFT.h>
#include <vtkImageRFFT.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkImageCast.h>
#include <vtkJPEGReader.h>
#include <vtkImageExtractComponents.h>
#include <vtkImageFourierCenter.h>
#include <vtkImageMagnitude.h>
#include <vtkImageShiftScale.h>
//测试图像:../data/lena-gray.jpg
int main(int argc, char* argv[])
{
vtkSmartPointer<vtkJPEGReader> reader =
vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName ("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap05/data/lena-gray.jpg");
reader->Update();
double range[2];
reader->GetOutput()->GetScalarRange(range);
float oldRange = range[1] - range[0];
std::cout << "Old range: [" <<range[0] << ", " << range[1] << "]" << std::endl;
std::cout << "Old range magnitude: " << oldRange << std::endl;
//二维快速傅里叶变换
vtkSmartPointer<vtkImageFFT> fftFilter =
vtkSmartPointer<vtkImageFFT>::New();
fftFilter->SetInputConnection(reader->GetOutputPort());
fftFilter->SetDimensionality(2);
fftFilter->Update();
//利用函数SetComponents(O)指定提取实部图像显示
vtkSmartPointer<vtkImageExtractComponents> fftExtractReal =
vtkSmartPointer<vtkImageExtractComponents>::New();
fftExtractReal->SetInputConnection(fftFilter->GetOutputPort());
fftExtractReal->SetComponents(0);
fftExtractReal->GetOutput()->GetScalarRange(range);
//数据转换 to unsigned char
vtkSmartPointer<vtkImageShiftScale> ShiftScale =
vtkSmartPointer<vtkImageShiftScale>::New();
ShiftScale->SetOutputScalarTypeToUnsignedChar();
ShiftScale->SetScale( 255.0 / (range[1]-range[0]) );
ShiftScale->SetShift(-range[0]);
ShiftScale->SetInputConnection(fftExtractReal->GetOutputPort());
ShiftScale->Update();
//完成快速傅里叶逆变换
vtkSmartPointer<vtkImageRFFT> rfftFilter =
vtkSmartPointer<vtkImageRFFT>::New();
rfftFilter->SetInputConnection(fftFilter->GetOutputPort());
rfftFilter->SetDimensionality(2);
rfftFilter->Update();
vtkSmartPointer<vtkImageExtractComponents> ifftExtractReal =
vtkSmartPointer<vtkImageExtractComponents>::New();
ifftExtractReal->SetInputConnection(rfftFilter->GetOutputPort());
ifftExtractReal->SetComponents(0);
vtkSmartPointer<vtkImageCast> rfftCastFilter =
vtkSmartPointer<vtkImageCast>::New();
rfftCastFilter->SetInputConnection(ifftExtractReal->GetOutputPort());
rfftCastFilter->SetOutputScalarTypeToUnsignedChar();
rfftCastFilter->Update();
//不知道为啥用这种方式转化数据 显示异常
// vtkSmartPointer<vtkImageShiftScale> rfftCastFilter =
// vtkSmartPointer<vtkImageShiftScale>::New();
// rfftCastFilter->SetOutputScalarTypeToUnsignedChar();
// rfftCastFilter->SetScale( 255.0 / (range[1]-range[0]) );
// rfftCastFilter->SetShift(-range[0]);
// rfftCastFilter->SetInputConnection(ifftExtractReal->GetOutputPort());
// rfftCastFilter->Update();
rfftCastFilter->GetOutput()->GetScalarRange(range);
oldRange = range[1] - range[0];
std::cout << "Old range: [" <<range[0] << ", " << range[1] << "]" << std::endl;
std::cout << "Old range magnitude: " << oldRange << std::endl;
//vtklmageActor类仅支持unsigned char数据类型的图像
vtkSmartPointer<vtkImageActor> originalActor =
vtkSmartPointer<vtkImageActor>::New();
originalActor->SetInputData(reader->GetOutput());
vtkSmartPointer<vtkImageActor> fftActor =
vtkSmartPointer<vtkImageActor>::New();
fftActor->SetInputData(ShiftScale->GetOutput());
vtkSmartPointer<vtkImageActor> rfftActor =
vtkSmartPointer<vtkImageActor>::New();
rfftActor->SetInputData(rfftCastFilter->GetOutput());
double originalViewport[4] = {0.0, 0.0, 0.33, 1.0};
double fftViewport[4] = {0.33, 0.0, 0.66, 1.0};
double rfftViewport[4] = {0.66, 0.0, 1.0, 1.0};
vtkSmartPointer<vtkRenderer> originalRenderer =
vtkSmartPointer<vtkRenderer>::New();
originalRenderer->SetViewport(originalViewport);
originalRenderer->AddActor(originalActor);
originalRenderer->ResetCamera();
originalRenderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer> fftRenderer =
vtkSmartPointer<vtkRenderer>::New();
fftRenderer->SetViewport(fftViewport);
fftRenderer->AddActor(fftActor);
fftRenderer->ResetCamera();
fftRenderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer> rfftRenderer =
vtkSmartPointer<vtkRenderer>::New();
rfftRenderer->SetViewport(rfftViewport);
rfftRenderer->AddActor(rfftActor);
rfftRenderer->ResetCamera();
rfftRenderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(originalRenderer);
renderWindow->AddRenderer(fftRenderer);
renderWindow->AddRenderer(rfftRenderer);
renderWindow->SetSize(640, 320);
renderWindow->Render();
renderWindow->SetWindowName("FFTAndRFFTExample");
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style =
vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
低通滤波
标题理想低通滤波器
低通滤波是将频域图像中的高频部分滤除而保留低频部分。图像的边缘和噪声对应于频域图像中的高频部分,而低通滤波的作用即是减弱这部分的能量,从而达到图像平滑去噪的目的。最简单的低通滤波器是理想低通滤波器,其基本思想是给定一个频率阈值,将高于该阈值的所有部分设置为0,而低于该频率的部分保持不变。
从结果看,在过滤掉图像的高频部分后,图像 变得模糊,丢失了许多细节,另外还可以看到理想低通滤波后图像会存在一定的振铃效应, 这也是理想低通滤波的特点。
巴特沃斯低通滤波器
在实际应用中,经常使用的低通滤波器是巴特沃斯滤波器。
从结果看,巴特沃斯低通滤波器产生的图像更为平滑,不会出现振铃现象。
#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageIdealLowPass.h>
#include <vtkImageActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkJPEGReader.h>
#include <vtkImageFFT.h>
#include <vtkImageRFFT.h>
#include <vtkImageExtractComponents.h>
#include <vtkImageCast.h>
#include <vtkInteractorStyleImage.h>
#include <vtkImageButterworthLowPass.h>
//测试图像:../data/lena-gray.jpg
int main(int argc, char* argv[])
{
vtkSmartPointer<vtkJPEGReader> reader =
vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap05/data/lena-gray.jpg");
reader->Update();
vtkSmartPointer<vtkImageFFT> fftFilter =
vtkSmartPointer<vtkImageFFT>::New();
fftFilter->SetInputConnection(reader->GetOutputPort());
fftFilter->Update();
//频域图像理想低通滤波
// vtkSmartPointer<vtkImageIdealLowPass> lowPassFilter =
// vtkSmartPointer<vtkImageIdealLowPass>::New();
// lowPassFilter->SetInputConnection(fftFilter->GetOutputPort());
// lowPassFilter->SetXCutOff(0.05); //用户设置每个方向的截断频率
// lowPassFilter->SetYCutOff(0.05);
// lowPassFilter->Update();
//巴特沃斯低通滤波器
vtkSmartPointer<vtkImageButterworthLowPass> lowPassFilter = vtkSmartPointer<vtkImageButterworthLowPass>::New();
lowPassFilter->SetInputConnection(fftFilter->GetOutputPort());
lowPassFilter->SetXCutOff(0.05);
lowPassFilter->SetYCutOff(0.05);
lowPassFilter->Update();
vtkSmartPointer<vtkImageRFFT> rfftFilter =
vtkSmartPointer<vtkImageRFFT>::New();
rfftFilter->SetInputConnection(lowPassFilter->GetOutputPort());
rfftFilter->Update();
vtkSmartPointer<vtkImageExtractComponents> ifftExtractReal =
vtkSmartPointer<vtkImageExtractComponents>::New();
ifftExtractReal->SetInputConnection(rfftFilter->GetOutputPort());
ifftExtractReal->SetComponents(0);
vtkSmartPointer<vtkImageCast> castFilter =
vtkSmartPointer<vtkImageCast>::New();
castFilter->SetInputConnection(ifftExtractReal->GetOutputPort());
castFilter->SetOutputScalarTypeToUnsignedChar();
castFilter->Update();
vtkSmartPointer<vtkImageActor> originalActor =
vtkSmartPointer<vtkImageActor>::New();
originalActor->SetInputData(reader->GetOutput());
vtkSmartPointer<vtkImageActor> erodedActor =
vtkSmartPointer<vtkImageActor>::New();
erodedActor->SetInputData(castFilter->GetOutput());
double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(640, 320);
renderWindow->Render();
renderWindow->SetWindowName("IdealLowPassExample");
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkRenderer> leftRenderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(leftRenderer);
leftRenderer->SetViewport(leftViewport);
leftRenderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer> rightRenderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(rightRenderer);
rightRenderer->SetViewport(rightViewport);
rightRenderer->SetBackground(1.0, 1.0, 1.0);
leftRenderer->AddActor(originalActor);
rightRenderer->AddActor(erodedActor);
leftRenderer->ResetCamera();
rightRenderer->ResetCamera();
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}
高通滤波
理想高通滤波器
高通滤波与低通滤波正好相反,是让频域图像的高频部分通过而抑制低频部分。图像的 边缘对应高频分量,因此高通滤波的效果是图像锐化。同样,最简单的高通滤波器是理想高通滤波器。其基本思想是通过设置一个频率阈值,让高于该阈值的频率部分通过,而低于阈 值的低频部分设置为0。
从结果可以看出,理想高通滤波后图像得到锐化处理, 图像仅剩下边缘。
巴特沃斯高通滤波器
理想高通滤波器不能通过电子元器件来实现,而且存在振铃现象。在实际应用中,最常 使用的高通滤波器是巴特沃斯高通滤波器。
#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageIdealHighPass.h>
#include <vtkImageActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkJPEGReader.h>
#include <vtkImageFFT.h>
#include <vtkImageRFFT.h>
#include <vtkImageExtractComponents.h>
#include <vtkImageCast.h>
#include <vtkImageIdealHighPass.h>
#include <vtkImageButterworthHighPass.h>
//测试图像:../data/lena-gray.jpg
int main(int argc, char* argv[])
{
vtkSmartPointer<vtkJPEGReader> reader =
vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap05/data/lena-gray.jpg");
reader->Update();
vtkSmartPointer<vtkImageFFT> fftFilter =
vtkSmartPointer<vtkImageFFT>::New();
fftFilter->SetInputConnection(reader->GetOutputPort());
fftFilter->Update();
// //理想高通滤波器
// vtkSmartPointer<vtkImageIdealHighPass> highPassFilter =
// vtkSmartPointer<vtkImageIdealHighPass>::New();
// highPassFilter->SetInputConnection(fftFilter->GetOutputPort());
// highPassFilter->SetXCutOff(0.05); //设置X和Y方向的截止频率
// highPassFilter->SetYCutOff(0.05);
// highPassFilter->Update();
//巴特沃斯高通滤波器
vtkSmartPointer<vtkImageButterworthHighPass> highPassFilter = vtkSmartPointer<vtkImageButterworthHighPass>::New();
highPassFilter->SetInputConnection(fftFilter->GetOutputPort());
highPassFilter->SetXCutOff(0.05);
highPassFilter->SetYCutOff(0.05);
highPassFilter->Update();
vtkSmartPointer<vtkImageRFFT> rfftFilter =
vtkSmartPointer<vtkImageRFFT>::New();
rfftFilter->SetInputConnection(highPassFilter->GetOutputPort());
rfftFilter->Update();
vtkSmartPointer<vtkImageExtractComponents> ifftExtractReal =
vtkSmartPointer<vtkImageExtractComponents>::New();
ifftExtractReal->SetInputConnection(rfftFilter->GetOutputPort());
ifftExtractReal->SetComponents(0);
vtkSmartPointer<vtkImageCast> castFilter =
vtkSmartPointer<vtkImageCast>::New();
castFilter->SetInputConnection(ifftExtractReal->GetOutputPort());
castFilter->SetOutputScalarTypeToUnsignedChar();
castFilter->Update();
vtkSmartPointer<vtkImageActor> originalActor =
vtkSmartPointer<vtkImageActor>::New();
originalActor->SetInputData(reader->GetOutput());
vtkSmartPointer<vtkImageActor> erodedActor =
vtkSmartPointer<vtkImageActor>::New();
erodedActor->SetInputData(castFilter->GetOutput());
double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(640, 320);
renderWindow->Render();
renderWindow->SetWindowName("IdealHighPassExample");
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkRenderer> leftRenderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(leftRenderer);
leftRenderer->SetViewport(leftViewport);
leftRenderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer> rightRenderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(rightRenderer);
rightRenderer->SetViewport(rightViewport);
rightRenderer->SetBackground(1.0, 1.0, 1.0);
leftRenderer->AddActor(originalActor);
rightRenderer->AddActor(erodedActor);
leftRenderer->ResetCamera();
rightRenderer->ResetCamera();
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}