第5章 VTK图像处理
学习教程:《VTK图形图像开发进阶》张晓东,罗火灵
特别感谢:东灵工作室
5.2 VTK图像显示
5.2.1 vtkImageViewer2——显示二维图像
尤其适合三维图像的切片展示
示例——显示一个*.mhd格式的三维医学图像的某个切片
源码:
#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkMetaImageReader.h>
//测试图像:../data/brain.mhd
int main()
{
//使用vtkMetaImageReader读入一个*.mhd格式的图像
vtkSmartPointer<vtkMetaImageReader>reader = vtkSmartPointer<vtkMetaImageReader>::New();
reader->SetFileName("../data/brain.mhd");
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 0;
}
运行结果:
5.2.2 vtkImageActor——三维图像渲染
通过纹理映射将图像映射到一个多边形上进行显示。
使用vtkBMPReader读入图像后,依次建立vtkImageActor、vtkRender、vtkRenderWindow、vtkRenderWindowInteractor。还需定义一个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()
{
//读取图片
vtkSmartPointer<vtkBMPReader>reader = vtkSmartPointer<vtkBMPReader>::New();
reader->SetFileName("../data/lena.bmp");
reader->Update();
//渲染管线
vtkSmartPointer<vtkImageActor>imgActor = vtkSmartPointer<vtkImageActor>::New();
imgActor->SetInputData(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 0;
}
运行结果:
注意:vtkImageActor接收的图像数据vtkImageData像素类型必须为unsigned char,如果类型不符合要求,在显示图像前需先将图像数据类型转换为unsigned char。
在编译过程中遇到了“vktSmartPointer”: 未声明的标识符
错误。解决的办法竟然是!!把vs里报错这行删掉,在记事本里重写了一行一模一样的,然后再粘贴过来就ok了。Amazing!
5.2.3 vtkImageBlend——图像融合
图像融合:利用图像的不透明度来合成图像。使用类vtkImageBlend实现图像的融合。vtkImageBlend可以接受多个图像输入,其输出图像为融合图像。
两种融合模式:标准模式(默认)、混合模式
(1)标准模式
(2)混合模式
输出结果利用不透明度和做归一化。
示例:读入一幅灰度图像,另外生成一个二值图像,和融合图像(灰度图像与二值图像的融合)。最终在窗口内显示三张图像。
源码:
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkImageBlend.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkImageCast.h>
//测试图像:../data/lena-gray.jpg
int main()
{
//读入灰度图像
vtkSmartPointer<vtkJPEGReader>reader = vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName("../data/lena-gray.jpg");
reader->Update();
//生成二值图像
vtkSmartPointer<vtkImageCanvasSource2D>imageSource = vtkSmartPointer<vtkImageCanvasSource2D>::New();
imageSource->SetNumberOfScalarComponents(1);
imageSource->SetScalarTypeToUnsignedChar();
imageSource->SetExtent(0, 512, 0, 512, 0, 0);
imageSource->SetDrawColor(0.0);
imageSource->FillBox(0, 512, 0, 512);
imageSource->SetDrawColor(255.0);
imageSource->FillBox(100,400,100,400);
imageSource->Update();
//融合图像:两个输入(0:灰度图像;1:二值图像)
vtkSmartPointer<vtkImageBlend>imageBlend = vtkSmartPointer<vtkImageBlend>::New();
//imageBlend->SetInputData(0, (vtkDataObject*)reader->GetOutput());
//imageBlend->SetInputData(1, (vtkDataObject*)imageSource->GetOutput()); // 这样写不能显示融合图像
imageBlend->AddInputData(reader->GetOutput());
imageBlend->AddInputData(imageSource->GetOutput()); //修改为Add,然后取消编号就ok
imageBlend->SetOpacity(0, 0.4);
imageBlend->SetOpacity(1, 0.6); //用于设置对应id号的图像不透明度的大小
imageBlend->Update();
//显示三组图像
//(1)创建actors
vtkSmartPointer<vtkImageActor>originalActor1 = vtkSmartPointer<vtkImageActor>::New();
originalActor1->SetInputData(reader->GetOutput());
vtkSmartPointer<vtkImageActor>originalActor2 = vtkSmartPointer<vtkImageActor>::New();
originalActor2->SetInputData(imageSource->GetOutput());
vtkSmartPointer<vtkImageActor>blendActor = vtkSmartPointer<vtkImageActor>::New();
blendActor->SetInputData(imageBlend->GetOutput());
//(2)定义viewport范围 (xmin,ymin,xmax,ymax)
double leftViewport[4] = {
0.0,0.0,0.33,1.0 };
double midViewport[4] = {
0.33,0.0,0.66,1.0 };
double rightViewport[4] = {
0.66,0.0,1.0,1.0 };
//(3)创建渲染示例renderers
vtkSmartPointer<vtkRenderer>originalRenderer1 = vtkSmartPointer<vtkRenderer>::New();
originalRenderer1->SetViewport(leftViewport);
originalRenderer1->AddActor(originalActor1);
originalRenderer1->ResetCamera();
originalRenderer1->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer>originalRenderer2 = vtkSmartPointer<vtkRenderer>::New();
originalRenderer2->SetViewport(midViewport);
originalRenderer2->AddActor(originalActor2);
originalRenderer2->ResetCamera();
originalRenderer2->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer>blendRenderer = vtkSmartPointer<vtkRenderer>::New();
blendRenderer->SetViewport(rightViewport);
blendRenderer->AddActor(blendActor);
blendRenderer->ResetCamera();
blendRenderer->SetBackground(1.0, 1.0, 1.0);
//(4)创建渲染窗口renderWindow
vtkSmartPointer<vtkRenderWindow>renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(originalRenderer1);
renderWindow->AddRenderer(originalRenderer2);
renderWindow->AddRenderer(blendRenderer);
renderWindow->SetSize(640, 320);
renderWindow->Render();
renderWindow->SetWindowName("ImageBlendExample");
//(5)创建交互RenderWindowInteractor以及交互样式
vtkSmartPointer<vtkRenderWindowInteractor>renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return 0;
}
运行结果:
问题:不显示融合图像
报错信息:vtkCompositeDataPipeline (00000201D3E32960): Input for connection index 0 on input port index 1 for algorithm vtkImageBlend(00000201D3E1F930) is of type vtkImageData, but a vtkImageStencilData is required.
纠错参考:VTK笔记-图像融合-02-vtkImageBlend类
注意:VTK版本不兼容,会导致SetInput()无法使用。
- 如果要建立管道连接,使用SetInputConnection(),GetOutputPort()
- 如果要处理独立数据集,使用SetInputData()