AnatomicalOrientation 3D人体模型及三个人体标准解剖学平面展示

一:主要的知识点

1、说明

本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程------逐行解析官网所有Python示例-CSDN博客

2、知识点纪要

本段代码主要涉及的有①vtkOrientationMarkerWidget控制相机的小部件

二:代码及注释

python 复制代码
import vtkmodules.vtkRenderingOpenGL2
import vtkmodules.vtkInteractionStyle
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkRenderingCore import vtkActor, vtkRenderWindow, vtkRenderWindowInteractor, vtkRenderer, \
    vtkPolyDataMapper, vtkPropAssembly
from vtkmodules.vtkRenderingAnnotation import vtkAnnotatedCubeActor, vtkAxesActor
from vtkmodules.vtkInteractionWidgets import vtkOrientationMarkerWidget
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader
from vtkmodules.vtkFiltersSources import vtkPlaneSource
from vtkmodules.vtkCommonTransforms import vtkTransform
from vtkmodules.vtkFiltersGeneral import vtkTransformPolyDataFilter
from vtkmodules.vtkRenderingFreeType import vtkVectorText

def main():
    colors = vtkNamedColors()
    fileName = "Data/Human.vtp"

    ren = vtkRenderer()
    renWin = vtkRenderWindow()
    renWin.SetSize(780, 780)
    renWin.AddRenderer(ren)

    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    xyzLabels = ['X', 'Y', 'Z']
    scale = [1.5, -1.5, 1.5]
    axes = MakeCubeActor(scale, xyzLabels, colors)

    """
    vtkOrientationMarkerWidget  一个可以显示在渲染窗口角落的小部件,可以用来指示当前相机的方向
    典型用法是在屏幕右下角显示一个小的三维坐标轴(X、Y、Z)
    也可以自定义设置方向标识,如在本案例中是设置了cube与axes的结合体作为方向标识
    """
    om = vtkOrientationMarkerWidget()
    om.SetOrientationMarker(axes)  # 设置方向标识(可以是任何 vtkProp)
    om.SetViewport(0.0, 0.8, 0.2, 1.0)  # 设置小部件的显示区域,Xmin, Ymin, Xmax, Ymax
    om.SetInteractor(iren)
    om.EnabledOn()  # 启用
    om.InteractiveOn()  # 允许被用户拖动

    scale = [1.5, 1.5, 1.5]
    axes1 = MakeCubeActor(scale, xyzLabels, colors)
    om1 = vtkOrientationMarkerWidget()
    om1.SetOrientationMarker(axes1)
    om1.SetViewport(0, 0, 0.2, 0.2)
    om1.SetInteractor(iren)
    om1.EnabledOn()
    om1.InteractiveOn()

    scale = (-1.5, -1.5, 1.5)
    axes2 = MakeCubeActor(scale, xyzLabels, colors)
    om2 = vtkOrientationMarkerWidget()
    om2.SetOrientationMarker(axes2)
    # Position lower right in the viewport.
    om2.SetViewport(0.8, 0, 1.0, 0.2)
    om2.SetInteractor(iren)
    om2.EnabledOn()
    om2.InteractiveOn()

    axes3 = MakeAnnotatedCubeActor(colors)
    om3 = vtkOrientationMarkerWidget()
    om3.SetOrientationMarker(axes3)
    # Position upper right in the viewport.
    om3.SetViewport(0.8, 0.8, 1.0, 1.0)
    om3.SetInteractor(iren)
    om3.EnabledOn()
    om3.InteractiveOn()

    reader = vtkXMLPolyDataReader()
    reader.SetFileName(fileName)
    reader.Update()

    huamnMapper = vtkPolyDataMapper()
    huamnMapper.SetInputConnection(reader.GetOutputPort())
    huamnMapper.SetScalarModeToUsePointFieldData()
    huamnMapper.SelectColorArray("Color")
    huamnMapper.SetColorModeToDirectScalars()

    humanActor = vtkActor()
    humanActor.SetMapper(huamnMapper)
    bounds = humanActor.GetBounds()
    # Scale the actor
    humanActor.SetScale(1.0 / max(bounds))
    ren.AddActor(humanActor)

    # 三个界面的actor
    actors = MakePlanesActors(colors)
    for actor in actors:
        ren.AddViewProp(actor)

    # 给每个平面添加一个标签
    textActors = AddTextToPlanes()
    for actor in textActors:
        ren.AddViewProp(actor)

    ren.SetBackground2(colors.GetColor3d('OldLace'))
    ren.SetBackground(colors.GetColor3d('MistyRose'))
    ren.GradientBackgroundOn()
    ren.ResetCamera()
    ren.GetActiveCamera().Zoom(1.6)
    ren.GetActiveCamera().SetPosition(-2.3, 4.1, 4.2)
    ren.GetActiveCamera().SetViewUp(0.0, 0.0, 1.0)
    ren.ResetCameraClippingRange()
    renWin.Render()
    renWin.SetWindowName('AnatomicalOrientation')

    iren.Initialize()
    iren.Start()

def AddTextToPlanes():
    textActors = []
    scale = [0.04, 0.04, 0.04]

    text1 = vtkVectorText()
    text1.SetText('Transverse\nPlane\n\nSuperior\nCranial')
    trnf1 = vtkTransform()
    trnf1.RotateZ(-90)
    tpdPlane1 = vtkTransformPolyDataFilter()
    tpdPlane1.SetTransform(trnf1)
    tpdPlane1.SetInputConnection(text1.GetOutputPort())
    textMapper1 = vtkPolyDataMapper()
    textMapper1.SetInputConnection(tpdPlane1.GetOutputPort())
    textActor1 = vtkActor()
    textActor1.SetMapper(textMapper1)
    textActor1.SetScale(scale)
    textActor1.AddPosition(0.4, 0.49, 0.01)
    textActors.append(textActor1)

    text2 = vtkVectorText()
    text2.SetText('Transverse\nPlane\n\nInferior\n(Caudal)')
    trnf2 = vtkTransform()
    trnf2.RotateZ(270)
    trnf2.RotateWXYZ(*[180, 0, 1, 0])
    tpdPlane2 = vtkTransformPolyDataFilter()
    tpdPlane2.SetTransform(trnf2)
    tpdPlane2.SetInputConnection(text2.GetOutputPort())
    textMapper2 = vtkPolyDataMapper()
    textMapper2.SetInputConnection(tpdPlane2.GetOutputPort())
    textActor2 = vtkActor()
    textActor2.SetMapper(textMapper2)
    textActor2.SetScale(scale)
    textActor2.AddPosition(0.4, -0.49, -0.01)
    textActors.append(textActor2)

    text3 = vtkVectorText()
    text3.SetText('Sagittal\nPlane\n\nLeft')
    trnf3 = vtkTransform()
    trnf3.RotateX(90)
    trnf3.RotateWXYZ(*[-90, 0, 1, 0])
    tpdPlane3 = vtkTransformPolyDataFilter()
    tpdPlane3.SetTransform(trnf3)
    tpdPlane3.SetInputConnection(text3.GetOutputPort())
    textMapper3 = vtkPolyDataMapper()
    textMapper3.SetInputConnection(tpdPlane3.GetOutputPort())
    textActor3 = vtkActor()
    textActor3.SetMapper(textMapper3)
    textActor3.SetScale(scale)
    textActor3.AddPosition(-0.01, 0.49, 0.4)
    textActors.append(textActor3)

    text4 = vtkVectorText()
    text4.SetText('Sagittal\nPlane\n\nRight')
    trnf4 = vtkTransform()
    trnf4.RotateX(90)
    trnf4.RotateWXYZ(*[-270, 0, 1, 0])
    tpdPlane4 = vtkTransformPolyDataFilter()
    tpdPlane4.SetTransform(trnf4)
    tpdPlane4.SetInputConnection(text4.GetOutputPort())
    textMapper4 = vtkPolyDataMapper()
    textMapper4.SetInputConnection(tpdPlane4.GetOutputPort())
    textActor4 = vtkActor()
    textActor4.SetMapper(textMapper4)
    textActor4.SetScale(scale)
    textActor4.AddPosition(0.01, -0.49, 0.4)
    textActors.append(textActor4)

    text5 = vtkVectorText()
    text5.SetText('Coronal\nPlane\n\nAnterior')
    trnf5 = vtkTransform()
    trnf5.RotateY(-180)
    trnf5.RotateWXYZ(*[-90, 1, 0, 0])
    tpdPlane5 = vtkTransformPolyDataFilter()
    tpdPlane5.SetTransform(trnf5)
    tpdPlane5.SetInputConnection(text5.GetOutputPort())
    textMapper5 = vtkPolyDataMapper()
    textMapper5.SetInputConnection(tpdPlane5.GetOutputPort())
    textActor5 = vtkActor()
    textActor5.SetMapper(textMapper5)
    textActor5.SetScale(scale)
    textActor5.AddPosition(0.49, 0.01, 0.20)
    textActors.append(textActor5)

    text6 = vtkVectorText()
    text6.SetText('Coronal\nPlane\n\nPosterior')
    trnf6 = vtkTransform()
    trnf6.RotateWXYZ(*[90, 1, 0, 0])
    tpdPlane6 = vtkTransformPolyDataFilter()
    tpdPlane6.SetTransform(trnf6)
    tpdPlane6.SetInputConnection(text6.GetOutputPort())
    textMapper6 = vtkPolyDataMapper()
    textMapper6.SetInputConnection(tpdPlane6.GetOutputPort())
    textActor6 = vtkActor()
    textActor6.SetMapper(textMapper6)
    textActor6.SetScale(scale)
    textActor6.AddPosition(-0.49, -0.01, 0.3)
    textActors.append(textActor6)
    return textActors



def MakePlanesActors(colors):
    planes = []
    mappers = []
    actors = []
    resolution = [10, 10]
    origin = [0.0, 0.0, 0.0]
    point1 = [1, 0, 0]
    point2 = [0, 1, 0]

    planes.append(MakePlane(resolution, origin, point1, point2, [0, 0, 0, 0], [-0.5, -0.5, 0]))  # x-y plane
    planes.append(MakePlane(resolution, origin, point1, point2, [-90, 1, 0, 0], [-0.5, -0.5, 0.0]))  # x-z plane
    planes.append(MakePlane(resolution, origin, point1, point2, [-90, 0, 1, 0], [-0.5, -0.5, 0.0]))  # y-z plane
    for plane in planes:
        mapper = vtkPolyDataMapper()
        mapper.SetInputConnection(plane.GetOutputPort())
        actor = vtkActor()
        actor.SetMapper(mapper)
        mappers.append(mapper)
        actors.append(actor)
    actors[0].GetProperty().SetColor(colors.GetColor3d('SeaGreen'))  # Transverse plane
    actors[1].GetProperty().SetColor(colors.GetColor3d('DeepSkyBlue'))  # Coronal plane
    actors[2].GetProperty().SetColor(colors.GetColor3d('Tomato'))  # Saggital plane
    return actors


def MakePlane(resolution, origin, point1, point2, wxyz, translate):
    plane = vtkPlaneSource()
    plane.SetResolution(*resolution)
    plane.SetOrigin(origin)
    plane.SetPoint1(point1)
    plane.SetPoint2(point2)

    trnf = vtkTransform()
    trnf.RotateWXYZ(*wxyz)
    trnf.Translate(translate)
    tpdPlane = vtkTransformPolyDataFilter()
    tpdPlane.SetTransform(trnf)
    tpdPlane.SetInputConnection(plane.GetOutputPort())
    return tpdPlane

def MakeCubeActor(scale, xyzLabels, colors):
    cube = MakeAnnotatedCubeActor(colors)  # 生成一个vtkAnnotatedCubeActor对象
    axes = MakeAxesActor(scale, xyzLabels)  # 生成一个vtkAxesActor对象
    """
    vtkPropAssembly  用来组织和管理多个可渲染对象(actors),作用非常类似于"父节点 / 组(Group or Hierarchy Node)" 概念
    可以把多个 vtkProp(比如 vtkActor, vtkVolume, vtkAxesActor 等)组合在一起,当作一个整体来操作
    它本身继承自 vtkProp3D,所以可以像单个 vtkActor 一样被渲染、平移、旋转、缩放
    """
    assembly = vtkPropAssembly()
    assembly.AddPart(axes)
    assembly.AddPart(cube)
    return assembly


def MakeAxesActor(scale, xyzLabels):
    axes = vtkAxesActor()
    axes.SetScale(scale)
    axes.SetShaftTypeToCylinder()  # 设置坐标轴主体(轴身)的几何形状
    axes.SetXAxisLabelText(xyzLabels[0])  # 设置X轴末端显示的文字标签
    axes.SetYAxisLabelText(xyzLabels[1])
    axes.SetZAxisLabelText(xyzLabels[2])

    axes.SetCylinderRadius(0.5 * axes.GetCylinderRadius())  # 设置轴身半径
    axes.SetConeRadius(1.025 * axes.GetConeRadius())  # 设置轴尖半径
    axes.SetSphereRadius(1.5 * axes.GetSphereRadius())  # 设置中心点的球体半径

    tprop = axes.GetXAxisCaptionActor2D().GetCaptionTextProperty()  # 提取出控制X轴标签外观的属性对象
    tprop.ItalicOn()  # 设置为斜体
    tprop.ShadowOn()  # 开启阴影功能
    tprop.SetFontFamilyToTimes()  # 设置字体为Times字体

    axes.GetYAxisCaptionActor2D().GetCaptionTextProperty().ShallowCopy(tprop)
    axes.GetZAxisCaptionActor2D().GetCaptionTextProperty().ShallowCopy(tprop)
    return axes


def MakeAnnotatedCubeActor(colors):
    """
    vtkAnnotatedCubeActor  在三维场景中显示方向表示的类。
    每个面上都带有文字标签(Annotation),通常用于显示 坐标方向(如 +X、-Y、+Z)
    功能:
        显示立方体六个面,模拟坐标方位
        每个面都有文字,默认是 X, Y, Z, -X, -Y, -Z
        可交互显示,一般固定在角落(不随模型旋转)
    """
    cube = vtkAnnotatedCubeActor()
    cube.SetXPlusFaceText("R")
    cube.SetXMinusFaceText("L")
    cube.SetYPlusFaceText('A')  # 前部
    cube.SetYMinusFaceText('P')  # 后部
    cube.SetZPlusFaceText('S')  # 上面/头部
    cube.SetZMinusFaceText('I')  # 下面/尾部

    cube.SetFaceTextScale(0.5)  # 设置字体大小

    cube.GetCubeProperty().SetColor(colors.GetColor3d("Gainsboro"))
    cube.GetTextEdgesProperty().SetColor(colors.GetColor3d("LightSlateGray"))

    cube.GetXPlusFaceProperty().SetColor(colors.GetColor3d('Tomato'))
    cube.GetXMinusFaceProperty().SetColor(colors.GetColor3d('Tomato'))
    cube.GetYPlusFaceProperty().SetColor(colors.GetColor3d('DeepSkyBlue'))
    cube.GetYMinusFaceProperty().SetColor(colors.GetColor3d('DeepSkyBlue'))
    cube.GetZPlusFaceProperty().SetColor(colors.GetColor3d('SeaGreen'))
    cube.GetZMinusFaceProperty().SetColor(colors.GetColor3d('SeaGreen'))
    return cube


if __name__ == '__main__':
    main()
相关推荐
deephub9 分钟前
告别脆弱的单体应用,用多智能体网络构建稳定的生产力工具
人工智能·python·大语言模型·多智能体
烟雨江南aabb11 分钟前
Python第六弹:python爬虫篇:什么是爬虫
开发语言·爬虫·python
MomentYY15 分钟前
第 1 篇:Agent 到底是什么?别被概念唬住了
人工智能·python·agent
Python大数据分析@22 分钟前
对你而言, Vibe Coding 的乐趣是什么?
python
WL_Aurora22 分钟前
Python 算法基础篇之排序算法(一):冒泡、选择、插入
python·算法·排序算法
龙腾AI白云23 分钟前
中国人工智能培训网—AI系列录播课
python·beautifulsoup
AI算法沐枫26 分钟前
大一学生如何入门机器学习,深度学习,学习顺序如何?
人工智能·python·深度学习·学习·线性代数·算法·机器学习
用户67570498850229 分钟前
Python 统一大业:uv 如何整合 Pip、Pyenv 和 Venv?
后端·python
SilentSamsara40 分钟前
运算符重载:让自定义对象支持 +、[]、in 操作
开发语言·python·算法·青少年编程·pycharm
wuxinyan12341 分钟前
工业级大模型学习之路020:LangChain零基础入门教程(第三篇):提示词工程与提示模板系统
人工智能·python·学习·langchain