PolyDataContourToImageData 3D集合图像转换成等效3D二值图像

一:主要的知识点

1、说明

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

2、知识点纪要

本段代码主要涉及的有①三维图形转换为3D体素数据

二:代码及注释

python 复制代码
import math

import vtkmodules.vtkRenderingOpenGL2
import vtkmodules.vtkInteractionStyle
from vtkmodules.vtkFiltersSources import vtkSphereSource
from vtkmodules.vtkFiltersCore import vtkCutter, vtkStripper
from vtkmodules.vtkCommonDataModel import vtkImageData, vtkPlane
from vtkmodules.vtkIOXML import vtkXMLPolyDataWriter
from vtkmodules.vtkCommonCore import VTK_UNSIGNED_CHAR
from vtkmodules.vtkFiltersModeling import vtkLinearExtrusionFilter
from vtkmodules.vtkImagingStencil import vtkImageStencil, vtkPolyDataToImageStencil
from vtkmodules.vtkIOImage import vtkMetaImageWriter, vtkPNGWriter


def main():
    # 创建一个3D图形
    sphereSource = vtkSphereSource()
    sphereSource.SetPhiResolution(30)
    sphereSource.SetThetaResolution(30)
    sphereSource.SetCenter(40, 40, 40)
    sphereSource.SetRadius(20)

    # 切割数据集的"刀"
    # 首先先定义这个刀是什么,需要使用隐函数定义
    cutPlane = vtkPlane()
    cutPlane.SetOrigin(sphereSource.GetCenter())
    cutPlane.SetNormal(0, 0, 1)

    circleCutter = vtkCutter()
    circleCutter.SetInputConnection(sphereSource.GetOutputPort())
    circleCutter.SetCutFunction(cutPlane)

    stripper = vtkStripper()
    stripper.SetInputConnection(circleCutter.GetOutputPort())
    stripper.Update()

    circle = stripper.GetOutput()
    # 写入vtp文件
    polyDataWriter = vtkXMLPolyDataWriter()
    polyDataWriter.SetInputData(circle)
    polyDataWriter.SetFileName("circle.vtp")
    polyDataWriter.SetCompressorTypeToNone()  # 不适用任何压缩
    polyDataWriter.SetDataModeToAscii()  # 设置输出文件中的数据以ASCII(文本)格式存储
    polyDataWriter.Write()

    # 准备一个体素数据
    whiteImage = vtkImageData()
    bounds = [0] * 6
    circle.GetBounds(bounds)
    spacing = [0.5, 0.5, 0.5]
    whiteImage.SetSpacing(spacing)

    # 计算这个体素数据的维度
    dim = [0] * 3
    for i in range(3):
        dim[i] = int(math.ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i])) + 1
        if dim[i] < 1:
            dim[i] = 1
    whiteImage.SetDimensions(dim)  # 算是设置了图像体素的数量
    # SetExtent 设置了图像的索引范围 确保了生成的 3D 图像的体素网格是最小且精确的,既不浪费内存,又能完整地覆盖输入的几何体
    whiteImage.SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1)
    origin_shift = 5 * 0.5
    origin = [0] * 3
    origin[0] = bounds[0] - origin_shift
    origin[1] = bounds[2] - origin_shift
    origin[2] = bounds[4] - origin_shift
    # 上述添加origin_shift是为了vtkImageData能够完全包裹住mesh
    whiteImage.SetOrigin(origin)
    # AllocateScalars # 为图像的体素数据分配内存。VTK_UNSIGNED_CHAR(无符号字符,范围 0-255),1 表示每个体素有一个分量(即灰度值)
    whiteImage.AllocateScalars(VTK_UNSIGNED_CHAR, 1)

    # 将 整个 3D 图像(体素网格)预先填充为前景值(即白色)
    # inval = 255
    outval = 0
    # count = whiteImage.GetNumberOfPoints()
    # for i in range(count):
    #     whiteImage.GetPointData().GetScalars().SetTuple1(i, inval)

    # 上述for循环的简便替代方法
    whiteImage.GetPointData().GetScalars().Fill(255)

    extrude = vtkLinearExtrusionFilter()
    extrude.SetInputData(circle)
    extrude.SetScaleFactor(1.0)  # 设置挤压的比例因子
    extrude.SetExtrusionTypeToVectorExtrusion()  # 设置为向量挤压,而非几何体表面的法线定义
    extrude.SetVector(0, 0, 1)  # 设置挤压的向量
    extrude.Update()

    pol2stenc = vtkPolyDataToImageStencil()
    pol2stenc.SetInputConnection(extrude.GetOutputPort())
    pol2stenc.SetTolerance(0)  # 帮助过滤垂直面
    pol2stenc.SetOutputOrigin(origin)
    pol2stenc.SetOutputSpacing(spacing)
    pol2stenc.SetOutputWholeExtent(whiteImage.GetExtent())
    pol2stenc.Update()

    imgstenc = vtkImageStencil()
    """
    tkImageStencil 是另一个关键过滤器,它接收一个图像作为输入,并根据一个模板(Stencil)修改该图像的像素值。
    """
    imgstenc.SetInputData(whiteImage)
    imgstenc.SetStencilConnection(pol2stenc.GetOutputPort())
    imgstenc.ReverseStencilOff()
    imgstenc.SetBackgroundValue(outval)
    imgstenc.Update()

    imageWriter = vtkMetaImageWriter()
    imageWriter.SetFileName('labelImage.mhd')
    imageWriter.SetInputConnection(imgstenc.GetOutputPort())
    imageWriter.Write()

    imageWriter = vtkPNGWriter()
    imageWriter.SetFileName('labelImage.png')
    imageWriter.SetInputConnection(imgstenc.GetOutputPort())
    imageWriter.Write()

if __name__ == '__main__':
    main()
相关推荐
金銀銅鐵2 小时前
[Python] 基于欧几里得算法,实现分数约分计算器
python·数学
Lyn_Li4 小时前
Kaggle Top 5 | 198只股票、200条数据的金融预测——BattleFin高分方案从零复现
python·kaggle·比赛复盘·金融预测
小九九的爸爸9 小时前
前端想要入门Agent开发,要具备哪些Python基础?
python·agent·ai编程
阿耶同学10 小时前
手把手教你用 LangGraph 搭建三层嵌套 Agent 架构
python·程序员
花酒锄作田1 天前
Pydantic校验配置文件
python
hboot1 天前
AI工程师第四课 - 深度学习入门
pytorch·python·神经网络
ZhengEnCi2 天前
P2M-Matplotlib折线图完全指南-从数据可视化到趋势分析的Python绘图利器
python·matlab·数据可视化
ZhengEnCi2 天前
P2L-Matplotlib饼图完全指南-从数据可视化到图表定制的Python绘图利器
python·matlab
曲幽2 天前
你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南
python·fastapi·web·graphql·route·cors·rest·strawberry
用户8358086187912 天前
基于 Self-RAG 与列表级重排序的进阶 RAG 系统设计与实现
python