前面的知识总结
vtkXXXSource:一组类派生自vtkPolyDataAlgorithm,它们输出的数据类型都是vtkPolyData,都些类都是VTK预定义好的图形模型。
接着,把vtkXXXSource的输出作为vtkPolyDataMapper的输入,Mapper的作用是将输入的数据转换为几何图元(点、线、多边形)进行渲染。
然后,实例化一个Actor对象。VTK渲染场景中**数据的可视化**表达是**通过vtkProp的子类负责**的。
通过Actor的方法SetMapper()可以设置对应的Mapper。
接着,实例化渲染窗口(renderWindow)、渲染器(Renderer)、交互器(Interactor)、交互类型(Style)等对象。
**渲染窗口**既是VTK窗口;可以通过渲染窗口的AddRenderer()将渲染器(Renderer)加入到渲染窗口里;
**交互器**则是用方法SetRenderWindow()给它指定交互的窗口;交互风格与交互器是用方法SetInteractorStyle()关联在一起;
若干个Actor对象可以用方法AddActor()加入到渲染器里渲染。
可以发现:这些对象之间头、尾相接,可以连成一条线结构,这就是VTK里非常重要的概念:VTK管线结构。
1. VTK图像数据结构
图像可以看做是空间中的一个规则网格,在医学图像中,每个图像有内部坐标和世界坐标(?)。
**内部坐标**:像素索引(每个像素在图像网格中的位置);
**世界坐标系三元素**:原点(Origin),像素间隔(space)和图像维数(dimension),如下图
**图像数据**:图像像素的像素值,由像素索引和图像维数计算可得
**像素值类别**:标量(e.g. 一般灰度图像),向量(e.g. 彩色图像),张量(e.g.梯度场图像)
医学图像处理中大部分的图像都是灰度图像,需要注意,在医学图像处理中,一般的unsigned char类型,256灰度级远远不能满足要求,常见的医学图像的像素数据类型为unsigned short,灰度范围为0-65536。
2. VTK图像创建
2.1 Source创建源图像
TK中内置了多个创建图像的Source,其中以vtkImageCanvasSource2D为代表,该Source功能是创建一个画布(空白图像),并提供了多种几何图形(点、线段、圆、矩形以及图像等)的绘制填充功能。
#include
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include
#include
#include
#include
#include
#include
#include
#include
//#include < >引用的是编译器类库路径里面的头文件
//#include" " 引用的是程序目录的相对路径中的头文件
int main()
{
vtkSmartPointer canvas =
vtkSmartPointer::New();
canvas->SetScalarTypeToUnsignedChar(); //设置画布的像素数据类型
//SetNumberOfScalarComponents则指定了每个像素值的数据成分为1,每个像素值为1个标量值,
canvas->SetNumberOfScalarComponents(1);
canvas->SetExtent(0, 100, 0, 100, 0, 0);
//利用FillBox绘制两个填充矩形,SetDrawColor()来设置两个矩形的颜色。
canvas->SetDrawColor(0, 0, 0, 0);
canvas->FillBox(0, 100, 0, 100);
canvas->SetDrawColor(255, 0, 0, 0);
canvas->FillBox(20, 40, 20, 40);
canvas->Update(); //这一步还必不可少! why? 数据流?
//Mapper的作用是将输入的数据转换为几何图元(点、线、多边形)进行渲染。
//创建演员
vtkSmartPointer actor =
vtkSmartPointer::New();
actor->SetInputData(canvas->GetOutput());
//定义视窗
double viewport[4] = { 0,0,1,1 }; //?
vtkSmartPointer renderer =
vtkSmartPointer::New();
//renderer->SetViewport(viewport); //?
renderer->AddActor(actor);
//renderer->ResetCamera();//?
renderer->SetBackground(1.0, 1.0, 1.0);
//设置渲染窗口(搬上舞台)
vtkSmartPointer renderwindow =
vtkSmartPointer::New();
renderwindow->AddRenderer(renderer);
renderwindow->SetSize(640, 480);
renderwindow->Render();//ask each renderer render its images
renderwindow->SetWindowName("ImageCanvasSource2D");
//设置窗口交互(演员-观众)
vtkSmartPointer rwi =
vtkSmartPointer::New();
vtkSmartPointer style =
vtkSmartPointer::New();
rwi->SetInteractorStyle(style);
rwi->SetRenderWindow(renderwindow);
rwi->Initialize();
rwi->Start();//循环前,必须先初始化 rwi->Initialize();
return 0;
}
#include
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
//vtk的新版本在vtkImageData类中取消了SetScalarTypeToUnsignedChar()方法;
//现在仅能用如下方法设置:
//static void SetScalarType(int, vtkInformation* meta_data);
vtkSmartPointer img =
vtkSmartPointer::New();
vtkSmartPointer info =
vtkSmartPointer::New();
img->SetDimensions(16, 16, 1); //指定图像的维数,图像的原点和像素间隔都采用默认值
//指定图像的每个像素值的数据类型为unsigned char
img->SetScalarType(VTK_UNSIGNED_CHAR, info); //img->SetScalarTypeToUnsignedChar();
//指定图像像素为标量
img->SetNumberOfScalarComponents(1, info);//每个像素需要表示的组份 =1是指标量图
//分配内存,生成图像数据
img->AllocateScalars(info);//很重要
//图像生成后,默认所有像素值为0,可以通过访问图像数据数组来设置每个像素值
unsigned char* ptr = NULL;
ptr = (unsigned char*)img->GetScalarPointer();
//GetScalarPointer()即返回图像的数据数组(图像数据数组都采用一维数组)
//然后根据图像的大小,访问每个像素并为其赋值:0-256
for (int i = 0; i < 16 * 16 * 1; i++)
{
*ptr++ = (i+1000) % 256; //*ptr++ = i % 256;
}
//创建演员
vtkSmartPointer actor =
vtkSmartPointer::New();
actor->SetInputData(img); //actor->SetInputData(canvas->GetOutput());啥区别?
//启动渲染引擎
double viewport[4] = { 0,0,1,1 };
vtkSmartPointer render =
vtkSmartPointer::New();
render->SetViewport(viewport);
render->AddActor(actor);
render->ResetCamera();
render->SetBackground(1, 1, 1);
//VTK窗口
vtkSmartPointer window =
vtkSmartPointer::New();
window->AddRenderer(render);
window->SetSize(640, 480);
window->Render();
window->SetWindowName("CreateVTKImageData");
//交互
vtkSmartPointer rwi =
vtkSmartPointer::New();
vtkSmartPointer style =
vtkSmartPointer::New(); //??不可以直接设置为默认吗
rwi->SetInteractorStyle(style);
rwi->SetRenderWindow(window);
rwi->Initialize();
rwi->Start();
return 0;
}
3 图像显示
3.1单幅图像的读写
从外部存储介质里导入相关的数据文件,(如vtkBMPReader读取 BMP图像,vtkDicomImageReader可用于读取DICOM图像,vtkPNGReader 读取 PNG图像 )
在外部存储介质中存如入以下图片,图片名为 logo.png
读取代码:
#include
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include
#include
#include
#include
#include
#include //定义了Camera
int main()
{
//读取PNG图像
vtkSmartPointer pngread =
vtkSmartPointer::New();
pngread->SetFileName("../logo.png"); //相对路径
//显示该幅图像
vtkSmartPointer ImageViewer =
vtkSmartPointer::New();
ImageViewer->SetInputConnection(pngread->GetOutputPort());
vtkSmartPointer renderWindowInter =
vtkSmartPointer::New();
ImageViewer->SetupInteractor(renderWindowInter);
ImageViewer->Render();
ImageViewer->GetRenderer()->ResetCamera();
ImageViewer->Render();
renderWindowInter->Start();
}
读取成功后,如下:
如果要对图片进行写操作,使用 Writer类 进行以下步骤
//写图像
vtkSmartPointer writer =
vtkSmartPointer::New();
writer->SetFileName("VTK-logo.jpg");
writer->SetInputConnection(pngread->GetOutputPort());
writer->Write();
renderWindowInter->Start();
3.2 vtkImageViewer2
vtkImageViewer2中封装了VTK图像显示的管线,包括vtkActor,vtkRender,vtkRenderWindow,vtkInteractorStypeImage等对象,可以方便的完成图像显示和交互。
该类提供的主要交互操作有:图像放缩,窗宽窗位调节,并提供切片选择,切片方向设置接口,尤其适合三维图像的显示。
#include
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include
#include
#include
#include
#include
#include
int main(int argc, char* argv[])
{
vtkSmartPointer reader =
vtkSmartPointer::New();
reader->SetFileName("../brain.mhd");
reader->Update();
vtkSmartPointer viewer =
vtkSmartPointer::New();
viewer->SetInputConnection(reader->GetOutputPort());
//设置基本属性
viewer->SetSize(640, 480);
viewer->SetColorLevel(500);
viewer->SetColorWindow(2000);
viewer->SetSlice(40);
viewer->SetSliceOrientationToXZ();//viewer->SetSliceOrientationToYZ();//viewer->SetSliceOrientationToXY();横断面
viewer->Render();
viewer->GetRenderer()->SetBackground(1, 1, 1);
viewer->GetRenderWindow()->SetWindowName("ImageViewer2D");
vtkSmartPointer rwi =
vtkSmartPointer::New();
//设置交互属性
viewer->SetupInteractor(rwi);
rwi->Start();
}
其中也设置了四个参数,窗位(ColorLevel)、窗宽(ColorWindow)、切片(Slice)和切片方向(Orientation)。了解磁共振图像的窗宽窗位按下鼠标左键拖动鼠标,可以调节图像的窗宽窗位,从而显示不同灰度范围内容;
注:有一点,在教材中没有强调,要生成.mhd 还需要有一个 .raw文件,这个数据可以在
brain.mhd 付积分下载
显示三维图像时,需要确定当前显示切片和方向, 形象的说,修改上面的viewer->SetSliceOrientationToXY();为viewer->SetSliceOrientationToYZ();和 viewer->SetSliceOrientationToXZ();可以分别获得大脑的失状面、冠状面,如下:
参考文献:
VTK修炼之道14:图像处理_创建
VTK修炼之道15:图像处理_显示(vtkImageViewer2 & vtkImageActor)
05-VTK在图像处理中的应用(1)