前言
“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 类型
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;
}