3D 医学扫描同时显示患者的皮肤、骨骼的 3D 模型(通过等值面提取),以及三个正交切片

一:主要的知识点

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()
相关推荐
彼岸花开了吗2 小时前
构建AI智能体:六十五、模型智能训练控制:早停机制在深度学习中的应用解析
人工智能·python
一只小鱼儿吖2 小时前
从代理ip的底层逻辑探讨下如何选择代理ip商。
网络·python·网络协议·tcp/ip
山沐与山3 小时前
【设计模式】Python工厂模式与依赖注入:FastAPI的Depends到底在干嘛
python·设计模式·fastapi
写代码的【黑咖啡】3 小时前
Python常用数据处理库全解析
开发语言·python
2401_841495643 小时前
【Python高级编程】图着色动态可视化 APP
python·算法·matplotlib·tkinter·回溯法·图着色算法·动态可视化工具
南风微微吹4 小时前
【2026年3月最新】计算机二级Python题库下载安装教程~共19套真题
开发语言·python·计算机二级python
阿蔹4 小时前
Python基础语法三---函数和数据容器
开发语言·python
xingzhemengyou14 小时前
Python 多线程同步
开发语言·python
3824278274 小时前
python3网络爬虫开发实战 第二版:绑定回调
开发语言·数据库·python