很高兴在雪易的CSDN遇见你 ,给你糖糖
欢迎大家加入雪易社区-CSDN社区云
前言
本文总结VTK中图像的系列功能,包括图像的导入(读取)、显示、交互和导出(保存)等。详细讲解VTK中提供的各种解决思路,各位小伙伴按需领取!
感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!
你的点赞就是我的动力(^U^)ノ~YO
目录
前言
1. 图像的导入(读取)
2.vtkImageData解析
3.图像的可视化(图像的显示)
窗宽窗位
vtkImageViewer2
vtkImageActor
vtkImagePlaneWidget
4. 切片图像数据的提取
结论
如果用一句话来介绍VTK的话,那就是图像和图形库。VTK包含了对图像的各种处理,我们今天来详细梳理一遍。
1. 图像的导入(读取)
source路径: ...VTK-9.*.*\IO\Image
常见的二维图像有PNG、JPG、BMP等,VTK为这类图像的导入提供了接口如
VTK: vtkPNGReader Class Reference、
VTK: vtkJPEGReader Class Reference
VTK: vtkBMPReader Class Reference
上述导入的图像数据的维度为(X,Y,1),可直接赋予vtkImageActor对象进行显示。
* 提示:若图像的维度为(X,1,Z)直接赋予vtkImageActor时,Actor为一条线,无法显示出理想的图像数据。
VTK常见的应用领域为医学,在医学图像如CT图像、mha、mhd图像等的导入,vtk也提供了相应的接口,如VTK: vtkMetaImageReader Class Reference、VTK: vtkDICOMImageReader Class Reference
示例:可视化CT图像
读取CT图像数据后,可以使用VTK提供的各种可视化工具对图像进行可视化处理。例如,可以使用vtkImageMapper3D将图像数据映射成3D模型。以下是示例代码:
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageMapper3D.h>
#include <vtkImageData.h>
int main(int argc, char* argv[])
{
// 读取图像数据
vtkSmartPointer<vtkDICOMImageReader> reader = vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName("path/to/dicom/files"); // 设置DICOM文件路径
reader->Update(); // 读取DICOM文件
vtkSmartPointer<vtkImageData> imageData = reader->GetOutput(); // 获取图像数据
// 创建渲染器和可视化窗口
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(800, 800);
// 将图像数据映射成3D模型,并添加到渲染器中
vtkSmartPointer<vtkImageMapper3D> imageMapper = vtkSmartPointer<vtkImageMapper3D>::New();
imageMapper->SetInputData(imageData);
vtkSmartPointer<vtkActor> imageActor = vtkSmartPointer<vtkActor>::New();
imageActor->SetMapper(imageMapper);
renderer->AddActor(imageActor);
// 启动可视化窗口
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
renderWindow->Render();
interactor->Start();
return 0;
}
以上是基于VTK读取CT图像的基础代码示例,可以根据实际需要进行修改和扩展。
2.vtkImageData解析
VTK图像数据结构由两部分组成:图像头信息和数据。图像头信息定义了图像的基本信息,主要包括起点位置(Origin)、像素间隔(Spacing)和维数(Dimension),通过这三个参数即可确定图像空间位置和大小。
图像数据即为图像像素的像素值,一般采用一维数组来表示和存储。已知像素索引和图像维数的情况下,即可计算每个像素对应的像素值。一般来讲灰度图像的像素范围为0~255,可以采用一个unsigned char类型表示。医学图像数据的灰度范围为0~65536,数据类型为unsigned short。
VTK中提供了多个创建图像的Source类,位置在 VTK-9.*.*\Imaging\Sources,可以利用此类快速创建图像。
示例:创建VTK图像
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderWindow.h>
int main()
{
vtkSmartPointer<vtkImageData> img = vtkSmartPointer<vtkImageData>::New();
img->SetDimensions(16,16,1);
img->SetScalarTypeToUnsignedChar();
img->SetNumberOfScalarComponents(1);
img->AllocateScalars();
unsigned char *ptr = (unsigned char*)img->GetScalarPointer();
for(int i=0; i<16*16*1; i++)
{
*ptr ++ =i%256;
}
vtkSmartPointer<vtkImageActor> redActor =
vtkSmartPointer<vtkImageActor>::New();
redActor->SetInput(img);
double redViewport[4] = {0.0, 0.0, 1.0, 1.0};
vtkSmartPointer<vtkRenderer> redRenderer =
vtkSmartPointer<vtkRenderer>::New();
redRenderer->SetViewport(redViewport);
redRenderer->AddActor(redActor);
redRenderer->ResetCamera();
redRenderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(redRenderer);
renderWindow->SetSize( 640, 480 );
renderWindow->Render();
renderWindow->SetWindowName("CreateVTKImageData");
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style =
vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
3.图像的可视化(图像的显示)
窗宽窗位
窗宽为图像显示的灰度范围,窗位是窗宽的中心位置。窗宽只是确定了CT图像灰度范围上可视部分范围,还需要窗位来确定可视灰度范围的具体位置。比如,窗宽为200,窗位为100时,可视范围为0~200;当窗位为500时,可视范围为400~600。
vtkImageViewer2
目前的VTK版本中使用vtkImageViewer2来进行图像显示。vtkImageViewer2封装了图像显示的可视化渲染引擎,包括vtkActor、vtkRenderer 、vtkRenderWindow、vtkInteractorStyleImage等对象,方便地完成图像显示和交互。包括图像缩放、窗宽窗位调整、切片切换等。
#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkMetaImageReader.h>
//测试图像:../data/brain.mhd
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout<<argv[0]<<" "<<"ImageFile(*.mhd)"<<std::endl;
return EXIT_FAILURE;
}
vtkSmartPointer<vtkMetaImageReader> reader =
vtkSmartPointer<vtkMetaImageReader>::New();
reader->SetFileName(argv[1]);
reader->Update();
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(40);
imageViewer->SetSliceOrientationToXY();
imageViewer->Render();
imageViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
imageViewer->SetSize(640, 480);
imageViewer->GetRenderWindow()->SetWindowName("DisplayImageExample");
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
vtkImageActor
vtkImageActor是一个三维图像渲染Actor,通过纹理映射将图像映射到一个多边形上进行显示。使用vtkImageActor需要建立完整的渲染管线包括vtkImageActor、vtkRenderer 、vtkRenderWindow、vtkInteractorStyleImage。
示例
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkBMPReader.h>
#include <vtkImageActor.h>
//测试图像:../data/lena.bmp
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout<<argv[0]<<" "<<"ImageFile(*.bmp)"<<std::endl;
return EXIT_FAILURE;
}
vtkSmartPointer<vtkBMPReader> reader =
vtkSmartPointer<vtkBMPReader>::New();
reader->SetFileName ( argv[1] );
reader->Update();
vtkSmartPointer<vtkImageActor> imgActor =
vtkSmartPointer<vtkImageActor>::New();
imgActor->SetInput(reader->GetOutput());
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(imgActor);
renderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize( 640, 480 );
renderWindow->Render();
renderWindow->SetWindowName("DisplayImageExample2");
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style =
vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
注意: 若图像的维度为(X,1,Z)直接赋予vtkImageActor时,Actor为一条线,无法显示出理想的图像数据。
注意2:vtkImageActor接收的像素数据类型必须为unsigned char,如果类型不符合要求,需要提前转换为unsigned char类型图像。
vtkImagePlaneWidget
vtkImagePlaneWidget采用vtkImageReslice将切片数据取出,并通过纹理映射将切片图像数据映射到对应的Plane上,从而显示图像。
4. 切片图像数据的提取
vtk中vtkImageReslice类可以实现图像切片的提取。
示例
#include <vtkSmartPointer.h>
#include <vtkMatrix4x4.h>
#include <vtkImageReslice.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkImageData.h>
#include <vtkMetaImageReader.h>
#include <vtkImageCast.h>
#include <vtkLookupTable.h>
#include <vtkImageMapToColors.h>
//测试图像:..\\data\\brain.mhd
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout<<argv[0]<<" "<<"ImageFile(*.mhd)"<<std::endl;
return EXIT_FAILURE;
}
vtkSmartPointer<vtkMetaImageReader> reader =
vtkSmartPointer<vtkMetaImageReader>::New();
reader->SetFileName(argv[1]);
reader->Update();
int extent[6];
double spacing[3];
double origin[3];
reader->GetOutput()->GetExtent(extent);
reader->GetOutput()->GetSpacing(spacing);
reader->GetOutput()->GetOrigin(origin);
double center[3];
center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);
center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);
center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);
static double axialElements[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
vtkSmartPointer<vtkMatrix4x4> resliceAxes =
vtkSmartPointer<vtkMatrix4x4>::New();
resliceAxes->DeepCopy(axialElements);
resliceAxes->SetElement(0, 3, center[0]);
resliceAxes->SetElement(1, 3, center[1]);
resliceAxes->SetElement(2, 3, center[2]);
vtkSmartPointer<vtkImageReslice> reslice =
vtkSmartPointer<vtkImageReslice>::New();
reslice->SetInputConnection(reader->GetOutputPort());
reslice->SetOutputDimensionality(2);
reslice->SetResliceAxes(resliceAxes);
reslice->SetInterpolationModeToLinear();
vtkSmartPointer<vtkLookupTable> colorTable =
vtkSmartPointer<vtkLookupTable>::New();
colorTable->SetRange(0, 1000);
colorTable->SetValueRange(0.0, 1.0);
colorTable->SetSaturationRange(0.0, 0.0);
colorTable->SetRampToLinear();
colorTable->Build();
vtkSmartPointer<vtkImageMapToColors> colorMap =
vtkSmartPointer<vtkImageMapToColors>::New();
colorMap->SetLookupTable(colorTable);
colorMap->SetInputConnection(reslice->GetOutputPort());
vtkSmartPointer<vtkImageActor> imgActor =
vtkSmartPointer<vtkImageActor>::New();
imgActor->SetInput(colorMap->GetOutput());
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(imgActor);
renderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->Render();
renderWindow->SetSize(640, 480);
renderWindow->SetWindowName("ImageResliceExample");
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> imagestyle =
vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(imagestyle);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
结论:
本文主要介绍了VTK中Image图像数据的使用方法以及一些心得体会,希望对各位小伙伴有所帮助。
感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!
你的赞赏是我的最最最最大的动力(^U^)ノ~YO