VTK 数据读写_图像数据的读写

1.前言

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

前面我们已经接触到了 VTK的 Reader类,将数据导入可视化管道的流程:

  • 实例化 Reader对象;
  • 指定所要读取的文件名;
  • 调用 Update()方法促使管线执行。当管线后续的 Fiter有 Update0请求时,如调用Render()方法管线就会读取相应的图像文件, 所以这一步可省略 。

类似地, 使用 Writer类的主要步骤如下:

  • 实例化 Writer对象;
  • 输入要写盘的数据以及指定待写盘的文件名;
  • 调用 Write()方法促使 Writer类开始写盘操作。

2.vtkImageData类

 图像数据在 VTK 中是用vtkImageData类表示的,对于不同的图像文件类型, VTK提供相对应的类对图像文件进行读写操作。比如,前面章节中所提的vtkBMPReader是用于读取 BMP图像, vtkJPEGReader用于读取 JPG图像。 VTK除了支持 BMP、 JPG图像格式之外,还支持其他多种图像格式的读写。例如:

注意:
1.值得注意的是vtkImageReader/vtkImageWriter用于读写RAW格式的数据(即俗称的“裸数据”) ,该类型的图像没有文件信息,因此在读取此类图像时,需要指定图像各个维度的大小、字节顺序(是大端字节序还是小端字节序)、存储像素値的类型等信息,只有指定这些信息、,类vtkImageReader才能正确读取图像。
2.类vtkDicomImageReader可用于读取DICOM图像,但该类的功能很不完善,虽然VTK 最初是因医学图像可视化而诞生。但VTK对DICOM图像的读写操作却很不支持,比如该类不支持多帧DICOM图像的读取,而且VTK 也没有实现对 DICOM图像的写操作, 即没有提供类vlkDlCOMlmageWriter。
对 DICOM图像支持较好的函数库主要有 GDCM和 DCMTK。著名的医学图像分割与配准工具包 ITK 就是封装了 GDCM函数库进行 DICOM图像的读写。

3.单幅图像的读写

 1 #include <vtkAutoInit.h>    
 2 VTK_MODULE_INIT(vtkRenderingOpenGL);  
 3  
 4 #include <vtkSmartPointer.h>
 5 #include <vtkPNGReader.h>
 6 #include <vtkImageViewer2.h>
 7 #include <vtkRenderWindowInteractor.h>
 8 #include <vtkJPEGWriter.h>
 9 #include <vtkRenderer.h> //定义了Camera
10  
11 int main()
12 {
13     //读取PNG图像
14     vtkSmartPointer<vtkPNGReader> pngread = 
15         vtkSmartPointer<vtkPNGReader>::New();
16     pngread->SetFileName("logo.png");
17     //显示该幅图像
18     vtkSmartPointer<vtkImageViewer2> ImageViewer =
19         vtkSmartPointer<vtkImageViewer2>::New();
20     ImageViewer->SetInputConnection(pngread->GetOutputPort());
21  
22     vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInter = 
23         vtkSmartPointer<vtkRenderWindowInteractor>::New();
24     ImageViewer->SetupInteractor(renderWindowInter);
25     ImageViewer->Render();
26     ImageViewer->GetRenderer()->ResetCamera();
27     ImageViewer->Render();
28  
29     //写图像
30     vtkSmartPointer<vtkJPEGWriter> writer = 
31         vtkSmartPointer<vtkJPEGWriter>::New();
32     writer->SetFileName("VTK-logo.jpg");
33     writer->SetInputConnection(pngread->GetOutputPort());
34     writer->Write();
35  
36     renderWindowInter->Start();
37 }

        
该段代码先使用vtkPNGReader读入 PNG图像,然后用VTK 窗口显示读取的 PNG图像,最后使用类vtkJPEGWriter将读入的文件写成JPG图像。程序中使用 SetFileName方法设置要读写的图像名, 在写文件操作时要调用方法 Write方法才会将内存中的数据写入到存储介质中。 

可能我们会感觉到很奇怪,数据管线已经铺设好了,可是我们是怎么样实现引擎渲染的呢?已到最后完成了与Windows操作系统完成了交互?在显示图像时并没有用到,vtkRenderWindow、 vtkRenderer、 vtkActor等类,而只是使用了vtkImageViewer2以及设置了交互样式。其实, VTK 可视化管线相关的几个类都已经封装在vtkImageViewer2 里。vtkImageViewer2主要是针对二维图像(特别是医学图像)显示设计的,实现了图像缩放、转、平移、窗宽窗位调节等功能: 除了可以用于单幅二维图像的显示之外, 也可以显示三维图像的某个切片, 还可以设置不同的显示方向。

4.读取序列图像文件

医学图像应用程序中常常会处理序列的图像文件,比如计算机断层成像或者磁共振成像所成图像一般都是由多个有顺序的二维图像组成, 应用程序需要一次性导入一个序列的二维图像。VTK没有提供专门的类读取序列图像文件,但是VTK的图像Reader类都有提供方法SetFileNames()来设置多个图像文件名,利用该方法可以实现序列图像的读取。
 1 #include <vtkAutoInit.h>    
 2 VTK_MODULE_INIT(vtkRenderingOpenGL);  
 3  
 4 #include <stdio.h>
 5 #include <vtkSmartPointer.h>
 6 #include <vtkStringArray.h>
 7 #include <vtkJPEGReader.h>
 8 #include <vtkImageViewer2.h>
 9 #include <vtkRenderWindowInteractor.h>
10 #include <vtkRenderer.h>
11  
12 int main()
13 {
14     //生成文件序列组名
15     vtkSmartPointer <vtkStringArray> fileArray =
16         vtkSmartPointer <vtkStringArray>::New();
17     char fileName[128];
18     for(int i=1; i<100; i++)
19     {
20         sprintf(fileName,"Head/head%03d.jpg",i);
21         vtkstd::string fileStr(fileName);
22         fileArray->InsertNextValue(fileStr);
23     }
24     //读取JPG序列图像
25     vtkSmartPointer <vtkJPEGReader> reader = 
26         vtkSmartPointer <vtkJPEGReader>::New();
27     reader->SetFileNames(fileArray);
28  
29     //显示
30     vtkSmartPointer<vtkImageViewer2> viewer = 
31         vtkSmartPointer<vtkImageViewer2>::New();
32     viewer->SetInputConnection(reader->GetOutputPort());
33     vtkSmartPointer<vtkRenderWindowInteractor> interact =
34         vtkSmartPointer<vtkRenderWindowInteractor>::New();
35     //默认选择第50张切片
36     viewer->SetSlice(50);
37     //viewer->SetSliceOrientationToXY();
38     viewer->SetSliceOrientationToXZ();
39     //viewer->SetSliceOrientationToYZ();
40     viewer->SetupInteractor(interact);
41     viewer->Render();
42  
43     interact->Start();
44     return 0;
45 }

程序中使用 vtkStringArray生成文件名列表, 然后调用 vtkJPEGReader的方法。SetFileNames()设置符读取的序列图像的文件名 。初始显示该序列图像的第50个切片,显示的方向为 SetSliceOrientationToXY()。
还可以使用 Reader类里的 SetFilePrefix()和 SetFilePattem()等方法读取序列图像。

原文地址:https://www.cnblogs.com/ybqjymy/p/14241048.html