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()
相关推荐
X56616 小时前
如何在 Laravel 中正确保存嵌套动态表单数据(主服务与子服务)
jvm·数据库·python
ZhengEnCi7 小时前
03ab-PyTorch安装教程 📚
python
狐狐生风7 小时前
LangChain 向量存储:Chroma、FAISS
人工智能·python·学习·langchain·faiss·agentai
狐狐生风8 小时前
LangChain RAG 基础
人工智能·python·学习·langchain·rag·agentai
老前端的功夫8 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
yaoxin5211239 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python
dFObBIMmai9 小时前
MySQL主从同步中大事务导致的延迟_如何拆分大事务优化同步
jvm·数据库·python
szccyw09 小时前
mysql如何限制特定存储过程执行权限_MySQL存储过程安全访问
jvm·数据库·python
小白学大数据9 小时前
Python 自动化爬取网易云音乐歌手歌词实战教程
爬虫·python·okhttp·自动化
风之所往_10 小时前
Python 3.0 新特性全面总结
python