参考链接
基于面绘制的MC算法以及基于体绘制的 Ray-casting 实现Dicom图像的三维重建(python实现) - 控球强迫症 - 博客园 (cnblogs.com)
Python VTK numpy数据3D可视化_numpy_to_vtk-CSDN博客
体绘制是将三维数据场直接转换为屏幕上的二维图像,不必生成中间几何图元(面绘制需要),能够展示空间体细节,简单来说就是能够更完整的展示出整个物体,而不仅仅是表面。
中心思想是为每一个体素指定一个不透明度A和颜色值RGB,并考虑每一个体素对光线的透射、发射和反射作用。
光线投射算法(Ray-casting)是VTK的主要算法
光线投射算法(Ray-casting)原理:从图像平面的每个像素都沿着视线方向发出一条射线,此射线穿过体数据集,按一定步长进行采样,由内插计算每个采样点的颜色值和不透明度,然后由前向后或由后向前逐点计算累计的颜色值和不透明度值,直至光线完全被吸收或穿过物体。
在光线投射算法中,主要涉及到的是传递函数(transfer function)的概念。传递函数通常被用来对不同的单元加上颜色(RGB)和不透明度(opacity)属性。
该方法能很好地反映物质边界的变化,使用Phong模型,引入镜面反射(Specular)、漫反射(diffuse)和环境反射(Ambient coefficien)能得到很好的光照效果。
这个算法集成在vtkVolumeMapper,包括vtkVolumeRayCastMapper、vtkFixedPointVolumeRayCastMapper、vtkGPUVolumeRayCastMapper等。
把vtkImageData经过volumeMapper,再放入vtkVolume,经过vtkRenderer、vtkRenderWindow、vtkRenderWindowInteractor显示出体绘制图像。
附上官方算例:
# https://kitware.github.io/vtk-examples/site/Python/VolumeRendering/SimpleRayCast/
import vtk
def main():
fileName = get_program_parameters()
colors = vtk.vtkNamedColors() #创建vtkNamedColors,为对象和背景选择颜色
# This is a simple volume rendering example that
# uses a vtkFixedPointVolumeRayCastMapper
# Create the standard renderer, render window
# and interactor.
ren1 = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
# Create the reader for the data.
reader = vtk.vtkStructuredPointsReader()
reader.SetFileName(fileName)
# Create transfer mapping scalar value to opacity.
opacityTransferFunction = vtk.vtkPiecewiseFunction()
opacityTransferFunction.AddPoint(20, 0.0)
opacityTransferFunction.AddPoint(255, 0.2)
# Create transfer mapping scalar value to color.
colorTransferFunction = vtk.vtkColorTransferFunction()
colorTransferFunction.AddRGBPoint(0.0, 0.0, 0.0, 0.0)
colorTransferFunction.AddRGBPoint(64.0, 1.0, 0.0, 0.0)
colorTransferFunction.AddRGBPoint(128.0, 0.0, 0.0, 1.0)
colorTransferFunction.AddRGBPoint(192.0, 0.0, 1.0, 0.0)
colorTransferFunction.AddRGBPoint(255.0, 0.0, 0.2, 0.0)
# The property describes how the data will look.
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorTransferFunction)
volumeProperty.SetScalarOpacity(opacityTransferFunction)
volumeProperty.ShadeOn()
volumeProperty.SetInterpolationTypeToLinear()
# The mapper / ray cast function know how to render the data.
volumeMapper = vtk.vtkFixedPointVolumeRayCastMapper()
volumeMapper.SetInputConnection(reader.GetOutputPort())
# The volume holds the mapper and the property and
# can be used to position/orient the volume.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)
ren1.AddVolume(volume)
ren1.SetBackground(colors.GetColor3d('Wheat'))
ren1.GetActiveCamera().Azimuth(45) #将当前摄影机的方位角(水平旋转)增加45度。这将导致摄影机围绕其方向向右旋转45度,改变观察角度。
ren1.GetActiveCamera().Elevation(30) #设置相机的仰角为30度。通过这行代码,可以改变相机的视角来观察场景。
ren1.ResetCameraClippingRange() #用于重置相机的裁剪范围。它根据场景中的对象位置和大小自动调整相机的裁剪范围,以确保整个场景都能在视图中显示
ren1.ResetCamera() #将相机重置为默认位置和方向。它会根据场景中的对象自动调整相机的位置和放大缩小比例,以确保所有对象都能被完整显示
renWin.SetSize(600, 600)
renWin.SetWindowName('SimpleRayCast')
renWin.Render()
#补充
for i in range(0, 360):
# 渲染图片
renWin.Render()
# 调用摄像机,一度一度旋转视角
ren1.GetActiveCamera().Azimuth(1)
iren.Start()
def get_program_parameters():
import argparse
description = 'Volume rendering of a high potential iron protein.'
epilogue = '''
This is a simple volume rendering example that uses a vtkFixedPointVolumeRayCastMapper.
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('filename', help='ironProt.vtk.')
args = parser.parse_args()
return args.filename
if __name__ == '__main__':
main()