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()
相关推荐
love530love19 小时前
LiveTalking 数字人项目 Windows 部署完全指南(EPGF 架构)
人工智能·windows·python·架构·livetalking·epgf
遇事不決洛必達19 小时前
【Python基础】GIL 锁是什么及其对爬虫的影响
爬虫·python·线程·进程·gil锁
CryptoPP20 小时前
快速对接东京证券交易所API数据:实战指南与代码示例
开发语言·人工智能·windows·python·信息可视化·区块链
探物 AI21 小时前
把 MambaOut 塞进 YOLOv11:会有什么样的反应
python·yolo·计算机视觉
如竟没有火炬21 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
阳区欠21 小时前
【LangChain】LLM基础介绍
开发语言·python·langchain
Cosolar21 小时前
保姆级 CrewAI 教程:从零构建多智能体协作系统
人工智能·python·架构
GDAL1 天前
使用 uv 管理 Python 版本
python·uv·版本
真实的菜1 天前
Redis 从入门到精通(十二):典型业务场景实战 —— 排行榜、限流器、秒杀系统、Session 共享
数据库·redis·python
cup111 天前
[开源] Meta Assistant / 告别命令行,我为一堆 Python 脚本做了一个 Windows 任务栏的“家”
windows·python·工具·nuitka·脚本运行