DiscreteMarchingCubes离散等值面提取算法

一:主要的知识点

1、说明

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

2、知识点纪要

本段代码主要涉及的有①vtkImageData的基本信息及基本使用

二:代码及注释

python 复制代码
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkLookupTable, vtkMinimalStandardRandomSequence
from vtkmodules.vtkCommonDataModel import vtkImageData, vtkSphere
from vtkmodules.vtkFiltersGeneral import vtkDiscreteFlyingEdges3D, vtkDiscreteMarchingCubes
from vtkmodules.vtkImagingCore import vtkImageThreshold
from vtkmodules.vtkImagingHybrid import vtkSampleFunction
from vtkmodules.vtkImagingMath import vtkImageMathematics
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)
 
 
def main():
    n = 20
    radius = 8
 
    """
    这里只创建了一个空壳的vtkImageData,因为这里不需要直接设置范围
    在 VTK 里,vtkImageData 自己本身可以设置 extent(索引范围) 和 spacing(体素间距),然后你才能在它里面放数据
    但是在本示例代码中,sampler 已经 决定了采样范围和分辨率
    SetModelBounds(-50, 50, -50, 50, -50, 50) = 空间边界
    SetSampleDimensions(100, 100, 100) = 每个方向的体素数量
    
    当 sampler.Update() 时,它会 创建一个新的 vtkImageData,范围就是 [-50,50]³  
    也就是说,这里的 vtkImageData 是 sampler 输出的结果,范围由 sampler 决定
    """
    blob_image = vtkImageData()
 
    max_r = 50 - 2.0 * radius
    random_sequence = vtkMinimalStandardRandomSequence()
    random_sequence.SetSeed(5071)
    for i in range(0, n):
        sphere = vtkSphere()
        sphere.SetRadius(radius)
        x = random_sequence.GetRangeValue(-max_r, max_r)
        random_sequence.Next()
        y = random_sequence.GetRangeValue(-max_r, max_r)
        random_sequence.Next()
        z = random_sequence.GetRangeValue(-max_r, max_r)
        random_sequence.Next()
 
        sphere.SetCenter(int(x), int(y), int(z))
 
        """
        创建一个 采样器 (vtkSampleFunction)
        它的作用是:在给定的空间范围内,均匀采样某个 隐式函数 (implicit function),
        并把结果存成 vtkImageData(体素格子)
        """
        sample = vtkSampleFunction()
        sample.SetImplicitFunction(sphere)
        """
        指定采样结果的标量类型。
        这里设置为 float,表示每个体素的值是浮点数(而不是整型)。
        好处是可以表示连续的函数值,而不仅仅是 0/1
        """
        sample.SetOutputScalarTypeToFloat()
        """
        指定采样网格的分辨率。
        在 X、Y、Z 三个方向各采样 100 个点 → 得到 100万 个体素。
        分辨率越高,结果越精细,但内存和计算也更大
        """
        sample.SetSampleDimensions(100, 100, 100)
        """
        设置采样空间的边界框(bounding box)
        也就是说,它会在这个立方体范围内均匀布置采样点,然后对球体函数进行采样
        """
        sample.SetModelBounds(-50, 50, -50, 50, -50, 50)
 
        """
        整段代码的含义是
        如果某个体素值 ≤ radius² → 说明它在球体内 → 标记为 i+1
        如果 > radius² → 说明它在球体外 → 标记为 0
        """
        thres = vtkImageThreshold()
        thres.SetInputConnection(sample.GetOutputPort())
        """
        表示保留所有 距离平方 ≤ radius² 的体素,也就是在球体内的体素
        """
        thres.ThresholdByLower(radius * radius)
        thres.ReplaceInOn()
        thres.ReplaceOutOn()
        thres.SetInValue(i + 1)
        thres.SetOutValue(0)
        thres.Update()
 
        if i == 0:
            blob_image.DeepCopy(thres.GetOutput())
 
        # 图像的像素级处理
        max_value = vtkImageMathematics()
        max_value.SetInputData(0, blob_image)
        max_value.SetInputData(1, thres.GetOutput())
        """
        做"逐体素最大值"运算.也就是说,球体之间的标签会取最大值,避免覆盖
        """
        max_value.SetOperationToMax()
        """
        Modified
        强制标记这个 filter 已经被修改,确保在调用 Update() 时重新执行图像运算,而不是复用旧缓存
        """
        max_value.Modified()
        max_value.Update()
 
        blob_image.DeepCopy(max_value.GetOutput())
 
    discrete = vtkDiscreteFlyingEdges3D()
    discrete.SetInputData(blob_image)
    """
    GenerateValues  指定要生成的等值面范围
    GenerateValues(numContours, rangeStart, rangeEnd) 的含义是:
    在 [rangeStart, rangeEnd] 之间 平均分布 numContours 个等值面值
    """
    discrete.GenerateValues(n, 1, n)
 
    lut = vtkLookupTable()
    lut.SetNumberOfColors(n)
    lut.SetTableRange(0, n - 1)
    """
    指定查找表的标量映射是线性的(而不是对数)
    """
    lut.SetScaleToLinear()
    lut.Build()
    """
    SetTableValue  把第 0 号颜色设为 (R=0, G=0, B=0, A=1),也就是 黑色,不透明
    """
    lut.SetTableValue(0, 0, 0, 0, 1)
 
    random_sequence = vtkMinimalStandardRandomSequence()
    random_sequence.SetSeed(5071)
    for i in range(1, n):
        r = random_sequence.GetRangeValue(0.4, 1)
        random_sequence.Next()
        g = random_sequence.GetRangeValue(0.4, 1)
        random_sequence.Next()
        b = random_sequence.GetRangeValue(0.4, 1)
        random_sequence.Next()
        lut.SetTableValue(i, r, g, b, 1.0)
 
    mapper = vtkPolyDataMapper()
    mapper.SetInputConnection(discrete.GetOutputPort())
    mapper.SetLookupTable(lut)
    mapper.SetScalarRange(0, lut.GetNumberOfColors())
 
    # Create the RenderWindow, Renderer and both Actors
    #
    ren = vtkRenderer()
    ren_win = vtkRenderWindow()
    ren_win.AddRenderer(ren)
    ren_win.SetWindowName('DiscreteMarchingCubes')
 
    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(ren_win)
 
    actor = vtkActor()
    actor.SetMapper(mapper)
 
    ren.AddActor(actor)
 
    colors = vtkNamedColors()
    ren.SetBackground(colors.GetColor3d('Burlywood'))
 
    ren_win.Render()
 
    iren.Start()
 
 
if __name__ == '__main__':
    main()
相关推荐
nanawinona6 小时前
2026年下半年量化学习,不同基础要查不同缺口
人工智能·python
CTA量化套保6 小时前
最新量化表达入门,从概念规则到简单实现
人工智能·python
吃饱了得干活7 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
ikun_文7 小时前
Python进阶—函数编程
python·pycharm
MC皮蛋侠客7 小时前
uv 系列(三):依赖、锁文件与环境同步——可重复构建的核心
python·uv
量化吞吐机7 小时前
2026年交易想法转Python,中间先补规则转译
人工智能·python
用户298698530147 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
决战灬7 小时前
langgraph之interrupt(事例篇)
人工智能·python·agent
IPdodo_7 小时前
Codex 总是 Reconnecting?从 401 到响应流中断的排查方法
python·requests
京和动物医院·总院7 小时前
2026年未央区宠物医院:如何挑选最适合您爱宠的健康守护者
大数据·人工智能·python