SmoothDiscreteMarchingCubes 多边形网格数据的平滑

一:主要的知识点

1、说明

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

2、知识点纪要

本段代码主要涉及的有①vtkSampleFunction函数采样器,②vtkWindowedSincPolyDataFilter 多边形网格的平滑滤波器

二:代码及注释

python 复制代码
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkLookupTable, vtkMinimalStandardRandomSequence
from vtkmodules.vtkCommonDataModel import vtkImageData, vtkSphere
from vtkmodules.vtkFiltersCore import vtkWindowedSincPolyDataFilter
from vtkmodules.vtkFiltersGeneral import 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
 
    max_r = 50 - 2.0 * radius
    blob_image = vtkImageData()
    random_sequence = vtkMinimalStandardRandomSequence()
    random_sequence.SetSeed(5071)
    for i in range(0, n):
        sphere = vtkSphere()
        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 
        创建一个 函数采样器,它会在一个三维规则网格里对隐函数(比如球、平面、布尔组合)进行采样,
        生成 vtkImageData 格式的体数据
        
        指定要采样的隐函数,这里是一个 vtkSphere
        隐函数的规则是:
            点在球面上 → 函数值 = 0
            点在球内 → 函数值 < 0
            点在球外 → 函数值 > 0
        如果设置的隐函数是一个平面呢?
            在平面上:值 = 0
            在平面的一边:值 = 正数   
            在另一边:值 = 负数
        """
        sampler = vtkSampleFunction()
        sampler.SetImplicitFunction(sphere)
        sampler.SetOutputScalarTypeToFloat()
        sampler.SetModelBounds(-50, 50, -50, 50, -50, 50)
        sampler.SetSampleDimensions(100, 100, 100)
 
        thres = vtkImageThreshold()
        thres.SetInputConnection(sampler.GetOutputPort())
        thres.ThresholdByLower(radius * radius)
        """
        SetInValue(i+1) 所有符合阈值条件的(即球体内部的)体素值替换为当前的循环索引 i 加 1
        SetOutValue(0):将所有不符合阈值条件的(即球体外部的)体素值替换为0
        """
        thres.SetInValue(i + 1)
        thres.SetOutValue(0)
        """
        ReplaceInOn() 启用对符合阈值条件的体素的替换
        ReplaceOutOn() 启用对不符合阈值条件的体素的替换
        """
        thres.ReplaceInOn()
        thres.ReplaceOutOn()
        """
        启用对符合阈值条件的体素的替换
        """
        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()
        max_value.Modified()
        max_value.Update()
 
        blob_image.DeepCopy(max_value.GetOutput())
 
    discrete = vtkDiscreteMarchingCubes()
    discrete.SetInputData(blob_image)
    discrete.GenerateValues(n, 1, n)
 
    smoothing_iterations = 15
    pass_band = 0.01
    feature_angle = 120.0
 
    """
    vtkWindowedSincPolyDataFilter 多边形网格的平滑滤波器
    普通的平滑算法(比如 vtkSmoothPolyDataFilter,基于 Laplacian 平滑)在迭代多次后,会让模型逐渐 变小,因为顶点会不断往邻居点的"平均位置"收缩。
    而 vtkWindowedSincPolyDataFilter 使用频域滤波的思想,通过 Sinc 函数 + 窗口函数来控制平滑程度,使得模型不会过度收缩,同时还能去掉高频噪声
    """
    smoother = vtkWindowedSincPolyDataFilter()
    smoother.SetInputConnection(discrete.GetOutputPort())
    smoother.SetNumberOfIterations(smoothing_iterations)
    smoother.BoundarySmoothingOff()  # 是否对边界也进行平滑
    smoother.SetFeatureAngle(feature_angle)
    smoother.FeatureEdgeSmoothingOff()  # 是否允许锐利特征边界被平滑
    """
    设置滤波器的通带宽度(0~2之间的浮点数),值越小平滑越强
    """
    smoother.SetPassBand(pass_band)
    """
    NonManifoldSmoothingOn  对非流行网格也进行平滑
    """
    smoother.NonManifoldSmoothingOn()
    """
    NormalizeCoordinatesOn  
    启用后,滤波器会 在内部把坐标归一化到一个标准范围([-1,1] 或 [0,1] 之类的范围) 再进行计算,
    最后再还原回原始范围
    """
    smoother.Update()
 
    lut = vtkLookupTable()
    lut.SetNumberOfColors(n)
    lut.SetTableRange(0, n - 1)
    lut.SetRampToLinear()
    lut.Build()  # 构建查找表
    lut.SetTableValue(0, 0, 0, 0, 1)  # 设置索引为0的颜色值为纯黑色+不透明
    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(smoother.GetOutputPort())
    mapper.SetLookupTable(lut)
    mapper.SetScalarRange(0, lut.GetNumberOfColors())
 
    ren = vtkRenderer()
    ren_win = vtkRenderWindow()
    ren_win.AddRenderer(ren)
    ren_win.SetWindowName('SmoothDiscreteMarchingCubes')
 
    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()
相关推荐
3DVisionary13 小时前
掌控发动机“心脏”精度:蓝光3D扫描在凸轮轴全尺寸检测中的应用
3d·图形渲染·汽车发动机·精密测量·蓝光3d扫描·凸轮轴检测·形位公差
好家伙VCC14 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
前端玖耀里15 小时前
如何使用python的boto库和SES发送电子邮件?
python
serve the people15 小时前
python环境搭建 (十二) pydantic和pydantic-settings类型验证与解析
java·网络·python
小天源15 小时前
Error 1053 Error 1067 服务“启动后立即停止” Java / Python 程序无法后台运行 windows nssm注册器下载与报错处理
开发语言·windows·python·nssm·error 1053·error 1067
喵手16 小时前
Python爬虫实战:HTTP缓存系统深度实战 — ETag、Last-Modified与requests-cache完全指南(附SQLite持久化存储)!
爬虫·python·爬虫实战·http缓存·etag·零基础python爬虫教学·requests-cache
喵手16 小时前
Python爬虫实战:容器化与定时调度实战 - Docker + Cron + 日志轮转 + 失败重试完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·容器化·零基础python爬虫教学·csv导出·定时调度
2601_9491465316 小时前
Python语音通知接口接入教程:开发者快速集成AI语音API的脚本实现
人工智能·python·语音识别
寻梦csdn17 小时前
pycharm+miniconda兼容问题
ide·python·pycharm·conda
Java面试题总结18 小时前
基于 Java 的 PDF 文本水印实现方案(iText7 示例)
java·python·pdf