vtkImageViewer2
vtkImageViewer2类用来显示二维图像;vtk的版本更新,使用vtkImageViewer2替代vtkImageViewer类;
vtkImageViewer2封装了VTK图像显示的可视化渲染引擎,包括vtkActor、vtkRender、vtkRenderWindow、vtkInteractorStyleImage等对象,可以方便地完成图像显示和交互,还提供了图像缩放、窗宽窗位调节,并提供切片选择以及切片方向设置的接口,尤其适合三维图像的切片显示;
一、vtkImageViewer2类成员
1.1 成员变量
vtkImageViewer2中封装的渲染引擎的对象有如下几个:
vtkImageMapToWindowLevelColors* WindowLevel;
vtkRenderWindow* RenderWindow;
vtkRenderer* Renderer;
vtkImageActor* ImageActor;
vtkRenderWindowInteractor* Interactor;
vtkInteractorStyleImage* InteractorStyle;
1.2 对外接口
设置输入数据来源:
virtual void SetInputData(vtkImageData* in);
virtual void SetInputConnection(vtkAlgorithmOutput* input);
设置切图显示方向:
virtual void SetSliceOrientation(int orientation);
virtual void SetSliceOrientationToXY();
virtual void SetSliceOrientationToYZ();
virtual void SetSliceOrientationToXZ();
SetSliceOrientation中的三个参数分别为:
枚举名称 | 枚举值 | 含义 |
---|---|---|
SLICE_ORIENTATION_YZ | 0 | 垂直于YZ面,X轴方向 |
SLICE_ORIENTATION_XZ | 1 | 垂直于XZ面,Y轴方向 |
SLICE_ORIENTATION_XY | 2 | 垂直于XY面,Z轴方向 |
默认情况下,切片的方向是垂直与XY平面,沿着Z轴方向;
SetSliceOrientationToXY、SetSliceOrientationToYZ、SetSliceOrientationToXZ分别调用了不同参数的SetSliceOrientation;
设置当前显示方向上的当前切片索引:
virtual void SetSlice(int s);
int s的输入范围在对于显示方向的切片范围内,一般从0开始到切片个数-1;
获取当前显示方向上的切片索引范围:
virtual int GetSliceMin();
virtual int GetSliceMax();
virtual void GetSliceRange(int range[2]) { this->GetSliceRange(range[0], range[1]); }
virtual void GetSliceRange(int& min, int& max);
virtual int* GetSliceRange();
窗宽窗位相关:
根据设定的窗宽窗位把数值映射到颜色上;
virtual double GetColorWindow();
virtual double GetColorLevel();
virtual void SetColorWindow(double s);
virtual void SetColorLevel(double s);
注意:设定不同的窗宽和窗位,可能会出现不一样的显示效果,可能会将彩色图显示为灰度图;
图像尺寸和坐标:
virtual int* GetPosition() VTK_SIZEHINT(2);
virtual void SetPosition(int x, int y);
virtual void SetPosition(int a[2]) { this->SetPosition(a[0], a[1]); }
virtual int* GetSize() VTK_SIZEHINT(2);
virtual void SetSize(int width, int height);
virtual void SetSize(int a[2]) { this->SetSize(a[0], a[1]); }
设置渲染引擎相关:
virtual void SetRenderWindow(vtkRenderWindow* arg);
virtual void SetRenderer(vtkRenderer* arg);
virtual void SetupInteractor(vtkRenderWindowInteractor*);
使用vtkImageViewer2中的vtkImageActor等对象对图像,对相机等信息进行控制改变;
例如,对vtkImageViewer2内的图像进行旋转180°操作;
vtkNew<vtkTransform> transform;
transform->RotateZ(180);
vtkNew<vtkImageViewer2> imageViewer;
imageViewer->GetImageActor()->SetUserTransform(transform);
二、实例
2.1 具体使用步骤
使用SetInputConnection设置输入数据来源;
使用SetupInteractor设置交互器,用来实现鼠标、键盘消息响应;
使用SetColorLevel设置窗位;
使用SetColorWindow设置窗宽;
使用SetSliceOrientationToXY设置切片显示方向;
使用SetSlice当前显示切片索引;
渲染Render;
2.2 完整代码
#include "vtkStringArray.h"
#include "vtkJPEGReader.h"
#include "vtkImageViewer2.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;
int main()
{
vtkSmartPointer<vtkStringArray> fileArray = vtkSmartPointer<vtkStringArray>::New();
char fileName[128] = { 0 };
for (size_t i = 0; i < 100; i++)
{
memset(fileName, 0, 128);
sprintf(fileName, "./data/Head/head%03d.jpg", i);
// vtkstd::string fileStr(fileName);
// vtkstd在VTK7版本中不再使用,用std替代
fileArray->InsertNextValue(fileName);
}
// 读取JPG序列图像
vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileNames(fileArray);
// 显示读取的JPG图像
vtkSmartPointer<vtkImageViewer2> imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
imageViewer->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
imageViewer->SetupInteractor(renderWindowInteractor);
imageViewer->SetColorLevel(500);
imageViewer->SetColorWindow(2000);
imageViewer->SetSlice(50);
imageViewer->SetSliceOrientationToXY();
imageViewer->Render();
renderWindowInteractor->Start();
return 0;
}
三、相关知识
3.1窗宽窗位
窗宽是图像显示的灰度范围。一般显示器的灰度范围为256级,医学图像的灰度范围远远大于这个范围,所以显示器不足以显示所有的灰度级,需要使用窗宽来定义想要显示的灰度范围;
一般情况下,可以将灰度值高于窗宽范围的最大值时,将像素值显示为白色值(255);将灰度值低于窗宽范围的最小值时,将像素值显示为黑色值(0);增大窗宽范围,可以显示更多不同灰度组织结构,但会减低组织之间的对比度;减小窗宽范围,可以减少所显示不同灰度组织结构,也就增大了组织结构之间的对比度;
窗位时窗宽的中心位置;窗宽只是确定了像素上的可视化的范围,是一个具体值,单独依靠窗宽不能确定这个范围的上限是多少和下限是多少,需要配合使用窗位来确定;比如上一代码中:窗宽为2000,只能说明窗宽的范围是2000,不能说明是从0到2000,还是-1000到1000,设置窗位为500时,窗宽2000,就能表示可视灰度范围为-500到1500;
手动进行像素换算灰度值时,可以参照上图。
void ConvertDigitImageToGrayImageByWindowLevelAndWindowWidth(short* digitImage, short* grayImage, int size, int window_level, int window_width){
double rate = 256.0 / window_width;
for (size_t i = 0; i < size; i++){
int tmp = 128.0 + (grayImage[i] - window_level)*rate;
if (tmp < 0){
tmp = 0;
}
else if (tmp > 255) {
tmp = 255;
}
digitImage[i] = tmp;
}
}
读彩色bmp图像
读取一张雷娜的彩色bmp图像;
vtkNew<vtkBMPReader> bmp_reader;
bmp_reader->SetFileName("G:\\Data\\lena.bmp");
bmp_reader->Update();
vtkNew<vtkImageViewer2> imageViewer;
imageViewer->SetInputData(bmp_reader->GetOutput());
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
imageViewer->SetupInteractor(renderWindowInteractor);
imageViewer->SetColorLevel(500);
imageViewer->SetColorWindow(2000);
imageViewer->Render();
renderWindowInteractor->Start();
显示效果
vtkNew<vtkBMPReader> bmp_reader;
bmp_reader->SetFileName("G:\\Data\\lena.bmp");
bmp_reader->Update();
vtkNew<vtkImageViewer2> imageViewer;
imageViewer->SetInputData(bmp_reader->GetOutput());
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
imageViewer->SetupInteractor(renderWindowInteractor);
imageViewer->SetColorWindow(255.0);
imageViewer->SetColorLevel(127.5);
imageViewer->Render();
renderWindowInteractor->Start();
vtkImageViewer2内部使用一个vtkWindowLevelLookupTable类型的成员变量,用于将图像数值转换为颜色值RGB或者RGBA值;
3.2医学图像二维视图
上文中设置切片方向是通过不同的方向来观察人体内部组织结构;
医学图像中,不同方向的切面都有特定的名字;
XY面:横断面(Transverse/Axial Plane),是指身体与地面平行的切面;
XZ面:冠状面(Coronal Plane),是沿着身体左右径所作的与地面垂直的切面,也可以看作是从左胳膊到右胳膊为行,以从头到脚为列,生成的切面;
YZ面:矢状面(Sagital Plane),是沿着身体的前后径所作的与地面垂直的切面,也可以看作是从后背到前胸为行,以从头到脚为列,生成的切面;