一:主要的知识点
1、说明
本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程------逐行解析官网所有Python示例-CSDN博客
2、知识点纪要
本段代码主要涉及的有①vtkLookupTable颜色映射表的运用,②vtkImageMapToColors图片的标量着色
二:代码及注释
python
import vtkmodules.vtkInteractionStyle
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkIOImage import vtkMetaImageReader
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkFiltersCore import vtkFlyingEdges3D, vtkStripper
from vtkmodules.vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow, \
vtkRenderWindowInteractor
from vtkmodules.vtkFiltersModeling import vtkOutlineFilter
from vtkmodules.vtkCommonCore import vtkLookupTable
from vtkmodules.vtkImagingCore import vtkImageMapToColors
from vtkmodules.vtkRenderingCore import (
vtkActor,
vtkCamera,
vtkImageActor,
vtkPolyDataMapper,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
def main():
colors = vtkNamedColors()
colors.SetColor('SkinColor', [240, 184, 160, 255])
colors.SetColor('BkgColor', [51, 77, 102, 255])
file_name = "Data/FullHead.mhd"
reader = vtkMetaImageReader()
reader.SetFileName(file_name)
reader.Update()
# 皮肤表面重建
skin_extractor = vtkFlyingEdges3D()
skin_extractor.SetInputConnection(reader.GetOutputPort())
skin_extractor.SetValue(0, 500)
skin_extractor.Update()
skin_mapper = vtkPolyDataMapper()
skin_mapper.SetInputConnection(skin_extractor.GetOutputPort())
skin_mapper.ScalarVisibilityOff()
skin_actor = vtkActor()
skin_actor.SetMapper(skin_mapper)
skin_actor.GetProperty().SetDiffuseColor(colors.GetColor3d("SkinColor"))
skin_actor.GetProperty().SetSpecular(0.3)
skin_actor.GetProperty().SetSpecularPower(20)
bone_extractor = vtkFlyingEdges3D()
bone_extractor.SetInputConnection(reader.GetOutputPort())
bone_extractor.SetValue(0, 1150)
bone_stripper = vtkStripper()
bone_stripper.SetInputConnection(bone_extractor.GetOutputPort())
bone_mapper = vtkPolyDataMapper()
bone_mapper.SetInputConnection(bone_stripper.GetOutputPort())
bone_mapper.ScalarVisibilityOff()
bone_actor = vtkActor()
bone_actor.SetMapper(bone_mapper)
bone_actor.GetProperty().SetDiffuseColor(colors.GetColor3d("Ivory"))
# outline
outline_data = vtkOutlineFilter()
outline_data.SetInputConnection(reader.GetOutputPort())
outline_data.Update()
map_outline = vtkPolyDataMapper()
map_outline.SetInputConnection(outline_data.GetOutputPort())
outline = vtkActor()
outline.SetMapper(map_outline)
outline.GetProperty().SetColor(colors.GetColor3d('Black'))
# 切片三个方向切片的颜色映射表
bw_lut = vtkLookupTable()
bw_lut.SetRange(0, 2000) # 输入的数据的灰度范围就是0~2000
bw_lut.SetSaturationRange(0, 0) # 将饱和度的范围设置为 0 到 0。饱和度为 0 意味着完全没有颜色,只有灰度
bw_lut.SetHueRange(0, 0) # 将色相(颜色类型,如红、绿、蓝)的范围设置为 0 到 0。由于饱和度为 0,色相设置在这里其实没有影响
bw_lut.SetValueRange(0, 1) # 将亮度的范围设置为 0(黑色)到 1(白色)
bw_lut.Build()
"""
总结上面的代码:定义了一个从黑到白的线性灰度查找表
0 黑色(0,0,0)
1000, 中灰(0.5, 0.5, 0.5)
2000, 白色(1, 1, 1)
"""
hue_lut = vtkLookupTable()
hue_lut.SetTableRange(0, 2000)
"""
SetHueRange 决定颜色在色环上的位置,范围通常为 [0,1],代表一个完整的彩色循环
| Hue 值 | 代表颜色 |
| ----- | ---------------- |
| 0.0 | 红色 (Red) |
| 0.16 | 黄色 (Yellow) |
| 0.33 | 绿色 (Green) |
| 0.66 | 蓝色 (Blue) |
| 0.83 | 紫色 (Magenta) |
| 1.0 | 回到红色 (Red again) |
所以 SetHueRange(0, 1) 表示:
标量值从 0 → 2000 时,颜色从红 → 橙 → 黄 → 绿 → 蓝 → 紫 → 红,
形成一个完整的彩虹过渡
"""
hue_lut.SetHueRange(0, 1)
"""
SetSaturationRange
这里设置为 1, 1 表示所有颜色都保持最鲜艳,不褪色
饱和度:表示颜色的纯度或鲜艳程度
可以把颜色想象成是"纯色 + 灰色"的混合
高饱和度(1) → 纯色,非常鲜艳
低饱和度(接近 0) → 被灰色稀释的颜色,显得"灰灰的"或"褪色"。
例如粉红色(红色 + 白灰),浅蓝(蓝色 + 灰白)
两个1表示表示整个查找表中,所有颜色的饱和度都恒定为 1
不管标量值是最小的还是最大的,颜色都保持完全饱和(最纯净),不进行从"灰色 → 纯色"的渐变
如果是SetSaturationRange(0, 1)->标量小的区域 → 饱和度低(灰白、淡)标量大的区域 → 饱和度高(纯色)会出现一种"从灰到彩色"的渐变
"""
hue_lut.SetSaturationRange(1, 1)
hue_lut.SetValueRange(1, 1)
hue_lut.Build()
sat_lut = vtkLookupTable()
sat_lut.SetTableRange(0, 2000)
sat_lut.SetHueRange(0.6, 0.6) # 固定了某种颜色
sat_lut.SetSaturationRange(0, 1)
sat_lut.SetValueRange(1, 1)
sat_lut.Build()
"""
vtkImageMapToColors 是vtk中非常常用的图像颜色映射类,主要是把灰度图转换成彩色图
它相当于"用查找表(Lookup Table)把标量值映射成颜色"的一个过滤器
"""
sagittal_colors = vtkImageMapToColors()
sagittal_colors.SetInputConnection(reader.GetOutputPort())
sagittal_colors.SetLookupTable(bw_lut)
sagittal_colors.Update()
sagittal = vtkImageActor()
sagittal.GetMapper().SetInputConnection(sagittal_colors.GetOutputPort())
sagittal.SetDisplayExtent(128, 128, 0, 255, 0, 92) # 设置展示的切片范围
"""
ForceOpaqueOn 强制渲染器将这个对象(sagittal 切片)视为完全不透明(Opaque),主要目的是为了优化渲染性能
在渲染复杂的 3D 场景时,VTK 渲染器通常会检查每个物体(Actor)的透明度属性 (Opacity)。
如果一个物体是透明的(Opacity < 1.0),渲染器必须进行额外的计算,
例如深度排序(将透明物体从后往前渲染),这会消耗大量性能
"""
sagittal.ForceOpaqueOn()
axial_colors = vtkImageMapToColors()
axial_colors.SetInputConnection(reader.GetOutputPort())
axial_colors.SetLookupTable(hue_lut)
axial_colors.Update()
axial = vtkImageActor()
axial.GetMapper().SetInputConnection(axial_colors.GetOutputPort())
axial.SetDisplayExtent(0, 255, 0, 255, 46, 46)
axial.ForceOpaqueOn()
coronal_colors = vtkImageMapToColors()
coronal_colors.SetInputConnection(reader.GetOutputPort())
coronal_colors.SetLookupTable(sat_lut)
coronal_colors.Update()
coronal = vtkImageActor()
coronal.GetMapper().SetInputConnection(coronal_colors.GetOutputPort())
coronal.SetDisplayExtent(0, 255, 128, 128, 0, 92)
coronal.ForceOpaqueOn()
a_camera = vtkCamera()
a_camera.SetViewUp(0, 0, -1)
a_camera.SetPosition(0, -1, 0)
a_camera.SetFocalPoint(0, 0, 0)
a_camera.ComputeViewPlaneNormal()
a_camera.Azimuth(30.0)
a_camera.Elevation(30.0)
a_renderer = vtkRenderer()
ren_win = vtkRenderWindow()
ren_win.AddRenderer(a_renderer)
iren = vtkRenderWindowInteractor()
iren.SetRenderWindow(ren_win)
a_renderer.AddActor(outline)
a_renderer.AddActor(sagittal)
a_renderer.AddActor(axial)
a_renderer.AddActor(coronal)
a_renderer.AddActor(skin_actor)
a_renderer.AddActor(bone_actor)
bone_actor.VisibilityOff()
skin_actor.GetProperty().SetOpacity(0.5)
a_renderer.SetActiveCamera(a_camera)
ren_win.SetWindowName('MedicalDemo3')
ren_win.Render()
a_renderer.ResetCamera()
a_camera.Dolly(1.5)
a_renderer.ResetCameraClippingRange()
ren_win.Render()
iren.Initialize()
iren.Start()
if __name__ == '__main__':
main()