面试 · 2024年2月19日 0

VTK 中 3D 图像的显示与渲染逻辑

VTK 中 3D 图像的显示与渲染逻辑,并附上一些示例代码。

  1. 数据加载与准备: 首先,需要加载或生成要显示的数据。例如,可以使用 vtkDICOMImageReader 从 DICOM 文件加载体数据,或者使用 vtkSphereSource 生成一个球体作为网格数据。
import vtk

# 从 DICOM 文件加载体数据
reader = vtk.vtkDICOMImageReader()
reader.SetFileName("path_to_dicom_folder")
reader.Update()

# 或者生成球体网格数据
sphereSource = vtk.vtkSphereSource()
sphereSource.Update()
  1. 创建渲染管线: 渲染管线是一系列的处理步骤,用于将数据转换为最终渲染的图像。这包括几何转换、光照模型、纹理贴图等。
# 创建等值面(isosurface)并添加到渲染管线中
contour = vtk.vtkContourFilter()
contour.SetInputConnection(reader.GetOutputPort())
contour.SetValue(0, 100)  # 设置等值面数值

# 添加法向量生成器
normals = vtk.vtkPolyDataNormals()
normals.SetInputConnection(contour.GetOutputPort())

# 设置光照属性
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(normals.GetOutputPort())

actor = vtk.vtkActor()
actor.SetMapper(mapper)
  1. 定义渲染窗口与渲染器: 创建渲染窗口,并添加一个渲染器,将演员(actors)添加到渲染器中。
# 创建渲染器
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)

# 创建渲染窗口
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)

# 创建交互器
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)

# 渲染并启动交互器
renderWindow.Render()
interactor.Start()
  1. 设置相机视角: 可以通过设置相机的位置、焦点和视角来控制渲染结果的呈现方式。
# 获取相机
camera = renderer.GetActiveCamera()

# 设置相机位置和焦点
camera.SetPosition(0, 0, 200)
camera.SetFocalPoint(0, 0, 0)

# 设置视角
camera.Zoom(1.0)
  1. 交互操作与用户控制: 使用交互器来启动交互功能,例如旋转、缩放、平移场景,以及选择对象等操作。
# 启动交互器
interactor.Start()
  1. 执行渲染循环: 渲染循环会持续执行,直到用户关闭窗口或退出程序。

——————————————————————————————-

VTk通过数据流实现变信息为图形数据的。

数据流一般为:source—filter——mapper——actor——render——renderwindow——interactor。

要理解工作原理,首先明确几个类型:

1.vtkSource(数据源)   这个就好比一个剧本里面的角色,让演员知道要演的是什么人物。

 数据源有:vtkConeSource,vtkSphereSource,vtkOutlineSource…等等。

 它们都继承与vtkPolyDataAlgorithm类,该类用于提供不同的类型的数据源

2.vtkMapper(映射器)   它就像是一个剧本,应该如何塑造角色的装扮

 映射器有:vtkDataSetMapper,vtkMultiGroupPolyDataMapper,vtkPolyDataMapper。

 它们都继承于vtkMapper类。所有的数据对象都要通过映射器Mapper映射到vtkActor中。

3.vtkActor(演员) 有了剧本,有了角色,得找个真人来演出这个剧本了。

 该类继承于vtkProp3D,有4个子类:vtkFollow,vtkLODActor,vtkMesaActor,vtkOpenGLActor.

4.vtkRenderer(渲染器)   这个过程就相当于对演员进行化妆并布置场景;

 该类继承于vtkViewport,有2个子类:vtkMesaRender,vtkOpenGLRender.

 该类另外一个作用是设置窗口vtkRenderWindow的背景.

5.vtkRenderWindow(窗口)    这个就相当于个舞台 ,把准备好的演员放进去,准备表演了;

 该类继承于vtkWindow,有2个子类:vtkMesaWindow,vtkOpenGLWindow.

6.vtkRenderWindowInteractor(窗口交互器)    这个像摄像机,用于捕捉演员的动作,然后传给导演看

 该类的继承关系在vtkRenderWindowInteractor文章中已给出。

7.vtkInteractorObserver(观察者)        有点导演的意思,导演通过观看录像后,做出一系列调整

 该类的继承关系在vtkRenderWindowInteractor文章中已给出

源Source对象:通过读取文件或重构数据对象产生数据。
过滤器Filter:将输入数据处理后生成新的数据,其中输入或输出数据可以单个,或多个Source object
绘图器Mapper:位于图形模型中,将数据转成图形数据(可由图形引擎渲染)
Writer:是一种Mapper,可以将数据写入文件或输出流中。


1.关于vtk

vtk是一个3D计算机图形学、图象处理及可视化工具包。

2.vtk可处理的数据类型

3.vtk使用流程

数据渲染时的流程:source→filter→mapper→actor→render→renderwindow→interactor

可视化流程

Source(数据源):各个类型的图像数据。

Filter(过滤器):对原始数据做一些操作,例如三角化、提取轮廓等。

Mapper(映射器):把不同的数据类型,转成图形数据。

Actor(演员):执行渲染mapper的对象。

Render(渲染器):用于渲染图像。

RenderWindow(窗口):可以理解成用于成像的一个平面。

Interactor(交互):用于获取渲染窗口上发生的鼠标,键盘事件,提供了独立于平台的与渲染窗口进行交互的机制

4.相机(camera)

相机投影示意图

从图可以看出与相机投影相关的因素主要有:

相机位置:即相机所在的位置,用方法vtkCamera.setPosition()设置。

相机焦点:用方法vtkCamera.setFocusPoint()设置,默认的焦点位置在世界坐标系的原点。

朝上方向:即哪个方向为相机朝上的方向。就好比我们直立看东西,方向为头朝上,看到的东西也是直立的,如果我们倒立看某个东西,这时方向为头朝下,看到的东西当然就是倒立的。相机位置、相机焦点和朝上方向三个因素确定了相机的实际方向,即确定相机的视图。

投影方向:相机位置到相机焦点的向量方向即为投影方向。

投影方法:确定Actor是如何映射到像平面的。vtkCamera定义了两种投影方法,一种是正交投影(OrthographicProjection),也叫平行投影(Parallel Projection),即进入相机的光线与投影方向是平行的。另一种是透视投影(PerspectiveProjection),即所有的光线相交于一点。

视角:透视投影时需要指定相机的视角(View Angle),默认的视角大小为30º,可以用方法vtkCamera.setViewAngle()设置。

前后裁剪平面:裁剪平面与投影方向相交,一般与投影方向也是垂直的。裁剪平面主要用于评估Actor与相机距离的远近,只有在前后裁剪平面之间的Actor才是可见的。裁剪平面的位置可以用方法vtkCamera.setClippingRange()设置。

如果你想获取vtkRenderer里默认的相机,可以用方法vtkRenderer.getActiveCamera()。

5.坐标系

计算机图形学里常用的坐标系统主要有四种,分别是:Model坐标系统、World坐标系统、View坐标系统和Display坐标系统,以及两种表示坐标点的方式:以屏幕像素值为单位和归一化坐标值(各坐标轴取值都为[-1, 1])。它们之间的关系如图所示。

Model、World、View和Display坐标系统

Model坐标系统是定义模型时所采用的坐标系统,通常是局部的笛卡尔坐标系。例如,我们要定义一个表示球体的Actor,一般的做法是将该球体定义在一个柱坐标系统里。使用的比较少。

World坐标系统是放置Actor的三维空间坐标系,Actor其中的一个功能就是负责将模型从Model坐标系统变换到World坐标系统。每一个模型可以定义有自己的Model坐标系统,但World坐标系只有一个,每一个Actor必须通过放缩、旋转、平移等操作将Model坐标系变换到World坐标系。World坐标系同时也是相机和光照所在的坐标系统。

View坐标系统表示的是相机所看见的坐标系统。X、Y、Z轴取值为[-1, 1],X、Y值表示像平面上的位置,Z值表示到相机的距离。相机负责将World坐标系变换到View坐标系。

Display坐标系统跟View坐标系统类似,但是各坐标轴的取值不是[-1, 1],而是使用屏幕像素值。屏幕上显示的不同窗口的大小会影响View坐标系的坐标值[-1, 1]到Display坐标系的映射。可以把不同的渲染场景放在同一个窗口进行显示,例如,在一个窗口里,分为左右两个渲染场景,这左右的渲染场景(vtkRenderer)就是不同的视口(Viewport)。例子Viewport演示了把一个窗口分为四个视口,用vtkRenderer.setViewport()来设置视口的范围(取值为[0, 1])。