【QT+VTK 学习笔记】05:VTK数据的读写

前言

“VTK图形图像开发进阶_张晓东_罗火灵”的学习笔记。
东灵工作室 教程系列导航:http://blog.csdn.net/www_doling_net/article/details/8763686

学习资料

VTK官网学习地址:https://vtk.org/doc/nightly/html/

学习笔记

VTK应用程序所需的数据可以通过两种途径获取:第一种是生成模型,然后处理 这些模型数据(如由类vtkCylinderSource生成的多边形数据);第二种是从外部存储介质里 导入相关的数据文件,然后在应用程序中处理这些读入的数据(如vtkBMPReader读取BMP 图像)。另一方面,VTK也可以将程序中处理完成的数据写入单个文件中,或者将所渲染的 场景导出,以备后续操作的使用。从可视化管线的角度来看,一般以数据的读取(或由模型 创建数据)开始,而以数据的写盘操作(或Mapper)结束

数据读写

vtklmageData 类型

图像数据在VTK中是用vtklmageData类表示的,对于不同的图像文件类型,VTK提 供相对应的类对图像文件进行读写操作。比如,前面章节中所提的vtkBMPReader是用于读 取BMP图像,vtkJPEGReader用于读取JPG图像。VTK除了支持BMP, JPG图像格式之外, 还支持其他多种图像格式的读写,表4-1列出了部分VTK支持的常见图像文件的 Reader/Writer 类。
在这里插入图片描述
程序源码
该例先使用vtkPNGReader读入PNG图像,然后用VTK窗口显示读取的PNG图像,最后使用类vtkJPEGWriter将读入的文件写成JPG图像。示例中使用SetFileName方法设置要 读写的图像名,在写文件操作时要调用方法Write。才会将内存中的数据写入到存储介质中。 此外,该示例与前面【QT+VTK 学习笔记】01:绘制圆柱体数据模型 介绍的VTK可视化管线有所不同,在显示图像时并没有用到 vtkRenderWindow, vtkRenderer、vtkActor 等类,而只是使用了 vtkImageViewer2 以及设置了 交互样式。其实,VTK可视化管线相关的几个类都已经封装在vtkImageViewer2里。

#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)

#include <vtkSmartPointer.h>
#include <vtkPNGReader.h>
#include <vtkJPEGWriter.h>
#include <vtkImageViewer2.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

//测试文件:data/VTK-logo.png
int main(int argc, char* argv[])
{
    char * fileName = (char*)"C:/Users/jbyyy/Desktop/icon2-1.png";
    //读取PNG图像
    vtkSmartPointer<vtkPNGReader> reader = vtkSmartPointer<vtkPNGReader>::New();
    reader->SetFileName(fileName);

    vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();

    //显示读取的单幅PNG图像
    vtkSmartPointer<vtkImageViewer2> imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
    imageViewer->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetInteractorStyle(style);

    imageViewer->SetupInteractor(renderWindowInteractor);
    imageViewer->Render();
    imageViewer->GetRenderer()->ResetCamera();
    imageViewer->Render();

    imageViewer->SetSize(640, 480);
    imageViewer->GetRenderWindow()->SetWindowName("ReadWriteSingleImage");

    //保存成JPG图像
    vtkSmartPointer<vtkJPEGWriter> writer = vtkSmartPointer<vtkJPEGWriter>::New();
    writer->SetFileName("VTK-logo.jpg");
    writer->SetInputConnection(reader->GetOutputPort());
    writer->Write();

    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}

vtkImageViewer2
vtkImageViewer2主要是针对二维图像(特别是医学图像)显示设计的,实现了图像缩放、旋转、平移、窗宽窗位调节等功能;除了可以用于单幅二维图像的显示之外,也可以显示三维图像的某个切片,还可以设置不同的显示方向。
vtkImageReader2Factory
在读取图像文件时,如果无法确定所读取的图像是什么格式,可以使用类 vtkImageReader2Factory来读取要导入的文布,该类会试着寻找最适合的类对图像做读取操作,这个类可以读取大部分标准格式的图像文件。

	//读取图像
	vtkSmartPointer<vtkImageReader2Factory> readerFactory = vtkSmartPointer<vtkImageReader2Factory>::New();
	vtkImageReader2 * reader = readerFactory->CreateImageReader2("../data/VTK-logo");		//不需要填写文件后缀名
	reader->SetFileName(argv[1]);
	reader->Update();

读取序列图像文件
医学图像应用程序中常常会处理序列的图像文件,比如计算机断层成像或者磁共振成像所成的 图像一般都是由多个有顺序的二维图像组成,应用程序需要一次性导入一个序列的二维图像。
程序功能:首先读取 个JPG的序列图像Head,该序列图像包含100张大小为256X256像素的二维图像,由这100 张二维图像组成一个三维数据体

#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)


#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageViewer2.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkStringArray.h>
#include <vtkRenderWindow.h>

int main()
{
    vtkSmartPointer< vtkStringArray > fileArray = vtkSmartPointer< vtkStringArray >::New();
    //生成图像序列的文件名数组
    //方法一
//    char fileName[128];
//    for(int i = 1; i < 100; i++)
//    {
//        sprintf(fileName, "C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap04/data/Head/head%03d.jpg", i);
//        /*
//         * VTKstd在VTK7版本中不再使用,用std替代
//         * VTK7中需添加命名空间
//        vtkstd::string fileStr(fileName);
//        fileArray->InsertNextValue(fileStr);
//        */
//        std::string fileStr(fileName);
//        fileArray->InsertNextValue(fileStr);
//    }
//    读取JPG序列图像
//    vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
//    reader->SetFileNames(fileArray);
    
    //方法二     //读取JPG序列图像
    vtkSmartPointer<vtkJPEGReader>reader =  vtkSmartPointer<vtkJPEGReader>::New();
    reader->SetFilePrefix ("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap04/data/Head/head");
    reader->SetFilePattern("%s%03d.jpg");
    reader ->SetDataExtent (0,255,0,255,1,99);//get 99 slice of pic with 256 * 256
    reader->Update();




    vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();

    //显示读取的JPG图像
    vtkSmartPointer<vtkImageViewer2> imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
    imageViewer->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetInteractorStyle(style);

    imageViewer->SetSlice(50); //默认显示第50个切片(即第50层)
    imageViewer->SetSliceOrientationToXY();
    //imageViewer->SetSliceOrientationToYZ();
    //imageViewer->SetSliceOrientationToXZ();
    imageViewer->SetupInteractor(renderWindowInteractor);
    imageViewer->Render();

    imageViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
    imageViewer->SetSize(640, 480);
    imageViewer->GetRenderWindow()->SetWindowName("ReadSeriesImages1");

    renderWindowInteractor->Start();
    return EXIT_SUCCESS;
}

方法一:SetFileNames中传递一个路径数组

    //生成图像序列的文件名数组
    vtkSmartPointer< vtkStringArray > fileArray = vtkSmartPointer< vtkStringArray >::New();
    char fileName[128];
    for(int i = 1; i < 100; i++)
    {
        sprintf(fileName, "C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap04/data/Head/head%03d.jpg", i);
        /*
         * VTKstd在VTK7版本中不再使用,用std替代
         * VTK7中需添加命名空间
        vtkstd::string fileStr(fileName);
        fileArray->InsertNextValue(fileStr);
        */
        std::string fileStr(fileName);
        fileArray->InsertNextValue(fileStr);
    }

方法二:SetFilePrefix/SetFilePattern搭配
在示例中,先使用SetFilePrefix。设置文件名相同的部分(可 包含路径信息),再用SetFilePattem()设置图像文件名中的序号变化的部分。

    vtkSmartPointer<vtkJPEGReader>reader =  vtkSmartPointer<vtkJPEGReader>::New();
    reader->SetFilePrefix ("C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap04/data/Head/head");
    reader->SetFilePattern("%s%03d.jpg");
    reader ->SetDataExtent (0,255,0,255,1,99);//get 99 slice of pic with 256 * 256
    reader->Update();

vtkPolyData 类型

vtkPolyData是图形处理中使用非常广泛的一种数据集类
在这里插入图片描述

vtkRectilinearGrid 类型

在这里插入图片描述

vtkStructuredGrid 类型

输出/输入类型为vtkStructuredGrid类型的ReaderAVriter。

vtkUnstructuredGrid 类型

在这里插入图片描述

场景的导入与导出

场景的导入(Import)与导出(Export)是指将渲染场景中的对象,包括光照、相机、Actor、 属性、变换矩阵等信息写入文件中,或者从外部文件中将这些对象导入渲染场景中。

在这里插入图片描述
程序源码

#include <QApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)


#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtk3DSImporter.h>
#include <vtkDataSet.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>

//测试文件:data/R8.3ds
int main ( int argc, char *argv[])
{
    std::string filename = "C:/Users/jbyyy/Desktop/work/QTDEMO/jbyyy/VTK/学习资料/VTK图形图像开发进阶+张晓东+PDF+源码/VTK图形图像开发进阶随书代码/VTK图形图像开发进阶随书代码/Examples/Chap04/data/R8.3ds";
    std::cout << "Reading " << filename << std::endl;

    // 3DS Import
    vtkSmartPointer<vtk3DSImporter> importer = vtkSmartPointer<vtk3DSImporter>::New();
    importer->SetFileName ( filename.c_str() );
    importer->ComputeNormalsOn();   //开启法向量
    importer->Read();

    vtkSmartPointer<vtkRenderer> renderer = importer->GetRenderer();
    vtkSmartPointer<vtkRenderWindow> renderWindow = importer->GetRenderWindow();
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);

    //渐变色背景
    renderer->GradientBackgroundOn();
    renderer->SetBackground(0.0, 0.0, 1.0);
    renderer->SetBackground2(0.0, 0.0, 0.0);
    renderWindow->Render();
    renderWindow->SetSize(640, 480);
    renderWindow->SetWindowName("Import3DS");
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}

THE END
< <上一篇
下一篇>>