【QT+VTK 学习笔记】12:VTK频域处理

前言

“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;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Qt中使用VTK库,可以实现VTK的可视化功能,并且可以通过Qt的事件机制来处理鼠标点击事件。下面是一个简单的示例代码,演示了如何在VTK处理鼠标左键点击事件: 首先,需要在Qt中创建一个VTK窗口,并将其作为一个QWidget的子类来使用。然后,通过重写QWidget的鼠标事件函数来处理鼠标点击事件。 ```cpp #include <QVTKWidget.h> #include <vtkRenderWindow.h> #include <vtkRenderer.h> #include <vtkRenderWindowInteractor.h> #include <vtkSmartPointer.h> #include <vtkCommand.h> class MyVTKWidget : public QVTKWidget { public: MyVTKWidget(QWidget* parent = nullptr) : QVTKWidget(parent) { // 创建VTK渲染器和交互器 renderer = vtkSmartPointer<vtkRenderer>::New(); interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); interactor->SetRenderWindow(GetRenderWindow()); GetRenderWindow()->AddRenderer(renderer); // 设置交互器样式为默认样式 interactor->SetInteractorStyle(vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New()); // 添加鼠标左键点击事件监听器 vtkSmartPointer<MouseClickListener> clickListener = vtkSmartPointer<MouseClickListener>::New(); clickListener->SetVTKWidget(this); interactor->AddObserver(vtkCommand::LeftButtonPressEvent, clickListener); } private: vtkSmartPointer<vtkRenderer> renderer; vtkSmartPointer<vtkRenderWindowInteractor> interactor; class MouseClickListener : public vtkCommand { public: static MouseClickListener* New() { return new MouseClickListener; } void SetVTKWidget(MyVTKWidget* widget) { vtkWidget = widget; } virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) { if (eventId == vtkCommand::LeftButtonPressEvent) { // 处理鼠标左键点击事件 vtkRenderWindowInteractor* interactor = static_cast<vtkRenderWindowInteractor*>(caller); int* pos = interactor->GetEventPosition(); // 在这里可以根据鼠标点击的位置进行相应的操作 // 输出鼠标点击的位置 std::cout << "Mouse left button clicked at position: " << pos[0] << ", " << pos[1] << std::endl; } } private: MyVTKWidget* vtkWidget; }; }; int main(int argc, char** argv) { QApplication app(argc, argv); // 创建一个Qt窗口 QWidget window; window.resize(800, 600); // 创建一个VTK窗口,并将其添加到Qt窗口中 MyVTKWidget vtkWidget(&window); vtkWidget.resize(800, 600); window.show(); return app.exec(); } ``` 在上述代码中,我们创建了一个名为`MyVTKWidget`的类,继承自`QVTKWidget`,并重写了鼠标事件函数`Execute`。在`MyVTKWidget`的构造函数中,我们创建了VTK渲染器和交互器,并将其与VTK窗口关联起来。然后,我们创建了一个名为`MouseClickListener`的内部类,继承自`vtkCommand`,用于处理鼠标左键点击事件。在`MouseClickListener`的`Execute`函数中,我们可以根据鼠标点击的位置进行相应的操作。 请注意,上述代码只是一个简单示例,实际使用时可能需要根据具体需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jbyyy、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值