GenerateCubesFromLabels 提取和可视化特定标签所代表的 3D 结构

一:主要的知识点

1、说明

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

2、知识点纪要

本段代码主要涉及的有①体素数据读取vtkMetaImageReader的使用,②vtkGeometryFilter三维网格数据转换为可渲染的polydata

二:代码及注释

python 复制代码
import vtkmodules.vtkRenderingOpenGL2
import vtkmodules.vtkInteractionStyle
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkIOImage import vtkMetaImageReader
from vtkmodules.vtkImagingCore import vtkImageWrapPad
from vtkmodules.vtkFiltersCore import vtkThreshold
from vtkmodules.vtkCommonTransforms import vtkTransform
from vtkmodules.vtkFiltersGeneral import vtkTransformFilter
from vtkmodules.vtkFiltersGeometry import vtkGeometryFilter
from vtkmodules.vtkCommonDataModel import (
    vtkDataObject,
    vtkDataSetAttributes
)
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)

def main():
    colors = vtkNamedColors()

    file_name = "Data/Frog/frogtissue.mhd"
    start_label = 1
    end_label = 29

    reader = vtkMetaImageReader()
    reader.SetFileName(file_name)
    reader.Update()

    """
    vtkMetaImageReader 返回的是一个体积数据(vtkImageData 或 vtkStructuredPoints 的基类)
    返回一个包含 6 个整数的元组或列表 [Imin, Imax, Jmin, Jmax, Kmin, Kmax]
    描述的是 3D 网格在三个维度上的体素/点索引范围
    """
    extent = reader.GetOutput().GetExtent()
    print("extent: ", extent)

    """
    vtkImageWrapPad 主要作用是扩展(或填充)图像的边界,并使用"环绕"(Wrap)模式来决定填充的值
    "Wrap"是它区别于其他填充模式(如常数填充 ConstantPad 或重复填充 ClampPad)的关键
    填充值来源: 当它填充新添加的边界体素时,它会从图像另一侧的现有数据中获取数值
    
    包裹填充的原因:在一些算法中,比如图像卷积(滤波),计算梯度或导数周期性模拟(如流体边界循环)
    需要图像在边界是"周期连续"的,这时候不能用零填充(那会引入边缘效应),而是要从另一侧"包裹"过来
    """
    pad = vtkImageWrapPad()
    pad.SetInputConnection(reader.GetOutputPort())
    pad.SetOutputWholeExtent(extent[0], extent[1] + 1, extent[2], extent[3] + 1, extent[4], extent[5] + 1)
    pad.Update()

    """
    数据属性(标量数据)从点到单元(cell)的"拷贝映射" 操作
    为什么这么做:
    一些滤波器、mapper、渲染器期望标量值在 cell 上;
    而输入的原始数据标量通常存在于 points 上;
    所以必须手动把标量从 PointData 复制到 CellData
    """
    pad.GetOutput().GetCellData().SetScalars(reader.GetOutput().GetPointData().GetScalars())

    """
    vtkThreshold  主要用于对数据集(如 vtkUnstructuredGrid, vtkPolyData, vtkImageData 等)中的标量值进行阈值筛选(Thresholding)
    从而提取出满足某个标量范围条件的单元(cells)或点(points)
    """
    selector = vtkThreshold()
    """
    SetInputArrayToProcess 参数详解
    第0个0: 代表输入端口索引
    第1个0: 代表连接的输入数据索引
    第2个0:表示"时间步索引",一般不用改
    vtkDataObject().FIELD_ASSOCIATION_CELLS  表示要使用单元(cell)数据,而不是点(Point)数据
    vtkDataSetAttributes().SCALARS 表示使用当前单元数据中的 标量数组(Scalars)
    """
    selector.SetInputArrayToProcess(0, 0, 0, vtkDataObject().FIELD_ASSOCIATION_CELLS,
                                    vtkDataSetAttributes().SCALARS)
    selector.SetInputConnection(pad.GetOutputPort())
    selector.SetLowerThreshold(start_label)
    selector.SetUpperThreshold(end_label)
    # 只保留标量值在 [start_label, end_label] 之间的单元
    selector.Update()

    transform = vtkTransform()
    transform.Translate(-0.5, -0.5, -0.5)

    transform_model = vtkTransformFilter()
    transform_model.SetTransform(transform)
    transform_model.SetInputConnection(selector.GetOutputPort())

    """
    vtkGeometryFilter  把 任意数据类型(体数据、结构化网格、非结构化网格等)提取成表面几何数据(vtkPolyData)
    简单来说就是把三维网格或体数据转换为可渲染的表面(PolyData)
    """
    geometry = vtkGeometryFilter()
    geometry.SetInputConnection(transform_model.GetOutputPort())

    mapper = vtkPolyDataMapper()
    mapper.SetInputConnection(geometry.GetOutputPort())
    mapper.SetScalarRange(start_label, end_label)
    mapper.SetScalarModeToUseCellData()
    mapper.SetColorModeToMapScalars()

    actor = vtkActor()
    actor.SetMapper(mapper)

    renderer = vtkRenderer()
    render_window = vtkRenderWindow()
    render_window.AddRenderer(renderer)
    render_window.SetSize(640, 480)
    render_window.SetWindowName('GenerateCubesFromLabels')

    render_window_interactor = vtkRenderWindowInteractor()
    render_window_interactor.SetRenderWindow(render_window)

    renderer.AddActor(actor)
    renderer.SetBackground(colors.GetColor3d('DarkSlateBlue'))
    render_window.Render()

    camera = renderer.GetActiveCamera()
    camera.SetPosition(42.301174, 939.893457, -124.005030)
    camera.SetFocalPoint(224.697134, 221.301653, 146.823706)
    camera.SetViewUp(0.262286, -0.281321, -0.923073)
    camera.SetDistance(789.297581)
    camera.SetClippingRange(168.744328, 1509.660206)

    render_window_interactor.Start()

if __name__ == '__main__':
    main()
相关推荐
智算菩萨2 小时前
【Python进阶】数据结构的精巧与算法的智慧:AI提速的关键
开发语言·人工智能·python
liwulin05062 小时前
【PYTHON】视频转图片
开发语言·python·音视频
惆怅客1232 小时前
libuvc初探
python·c·libuvc
渡我白衣2 小时前
Python 与数据科学工具链入门:NumPy、Pandas、Matplotlib 快速上手
人工智能·python·机器学习·自然语言处理·numpy·pandas·matplotlib
love530love2 小时前
【笔记】把已有的 ComfyUI 插件发布到 Comfy Registry(官方节点商店)全流程实录
人工智能·windows·笔记·python·aigc·comfyui·torchmonitor
星火飞码iFlyCode2 小时前
iFlyCode实践规范驱动开发(SDD):招考平台报名相片质量抽检功能开发实战
java·前端·python·算法·ai编程·科大讯飞
以为不会掉头发的詹同学2 小时前
【TCP通讯加密】TLS/SSL 证书生成、自签名证书、请求 CA 签发证书以及使用 Python TCP 服务器与客户端进行加密通讯
服务器·python·tcp/ip·ssl
世界唯一最大变量2 小时前
此算法能稳定求出柏林52城问题最优解7540.23(整数时为7538),比传统旅行商问题的算法7544.37还优
前端·python·算法
superman超哥2 小时前
仓颉高性能实践:内存布局优化技巧深度解析
c语言·开发语言·c++·python·仓颉