VTK 的可视化方法:等值面

VTK 的可视化方法:等值面

等值面是指一组具有相同标量值的点所构成的表面。

等值面(线)提取是一种常用的可视化技术,常应用于医学、地质、气象等领域。例如,在医学图像处理中,由于CT、MRI等图像分辨率越来越高,虽然体绘制技术可以清晰地对数据内部结构进行可视化,但是其计算量和效率却制约了其使用。此时可通过等值面提取技术,仅提取感兴趣的一个或者几个组织轮廓,并生成网格模型以供后续的处理和研究。

例子:

在这里插入图片描述

VTK 中的数据表达

  • Image Data:最基本的网格数据,存储复杂度是 O(1)。
  • Rectilinear Grid:放宽网格间距的限制,网格间距存储在 dx 和 dy 数组中,存储复杂度是 O(m+n)。

在这里插入图片描述

  • Structured Grid:放宽行列之间正交关系的约束,需要每个网格的 [px, py] 坐标,存储复杂度为 O(mn)。
  • Polygonal Data:网格拓扑结构的约束也不存在了,这时网格可以是离散的,需要更高的存储复杂度。

在这里插入图片描述

VTK 等值面提取类

根据数据类型的不同,VTK中提供了多个等值面提取类,其类图如图所示:

在这里插入图片描述

VTK中的等值面提取算法多基于MarchingCube算法来实现。MarchingCube是经典的移动立方体等值面提取算法。该算法是由W.E.Lorenson和H.E.Cline在1987年提出的。由于这一方法原理简单,易于实现,目前已经得到了较为广泛的应用,称为三维数据等值面生成的经典算法。

等值面提取类根据数据类型的不同而有所侧重:

  • vtkContourFilter:一个更加通用的等值面提取类,其可以接受任意的数据类型生成等值线或等值面。

  • vtkMarchingContourFilter:可以接受任何类型的数据,其内部根据数据不同生成不同的算法对象实现等值面/线的提取,具有较高的效率。

    • vtkDiscreteMarchingCubes:继承自vtkMarchingCubes,主要针对Label图像,比如利用图像分割算法对医学图像进行分割后得到含有不同Label值得数据,每个Label对应一个组织,如果想要得到其中一个或者几个组织的模型,则可以考虑使用该类。
  • vtkMarchingCubes:主要针对规则体数据生成等值面。

  • vtkImageMarchingCubes:主要处理三维图像数据。

  • vtkMarchingSquares:针对二维规则网格数据生成等值线。

实例1:模型数据的等值面提取

#include "VTKContour.h"

#include <vtkConeSource.h>
#include <vtkSTLReader.h>
#include <vtkMultiBlockPLOT3DReader.h>
#include <vtkDataSet.h>
#include <vtkMultiBlockDataSet.h>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkShrinkPolyData.h>
#include <vtkStructuredGridGeometryFilter.h>
#include <vtkStructuredGridOutlineFilter.h>
#include <vtkContourFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

VTKContour::VTKContour(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

	_pVTKWidget = new QVTKOpenGLNativeWidget();
	this->setCentralWidget(_pVTKWidget);
	// this->showMaximized();

	// 1. generate data
	// vtkSmartPointer<vtkConeSource> cone = vtkSmartPointer<vtkConeSource>::New();
	// or, read data
	// vtkMultiBlockPLOT3DReader 是一个读取器对象,用于读取 PLOT3D 格式的文件并在输出时生成结构化网格
	vtkSmartPointer<vtkMultiBlockPLOT3DReader> plot3dReader = vtkSmartPointer<vtkMultiBlockPLOT3DReader>::New();
	plot3dReader->SetXYZFileName("combxyz.bin");
	plot3dReader->SetQFileName("combq.bin");
	plot3dReader->SetScalarFunctionNumber(100);
	plot3dReader->SetVectorFunctionNumber(202);
	qDebug() << plot3dReader->GetOutput()->GetNumberOfBlocks(); // 0
	// 反向更新管线
	plot3dReader->Update();
	qDebug() << plot3dReader->GetOutput()->GetNumberOfBlocks(); // 1
	vtkDataSet* plot3dOutput = (vtkDataSet*)(plot3dReader->GetOutput()->GetBlock(0));
	// 获取标量数据
	vtkDataArray* scalars = plot3dOutput->GetPointData()->GetScalars();
	double* range = scalars->GetRange();
	qDebug() << range[0] << ":" << range[1];

	// 2. filter
	// 产生结构化栅格边界的一个线轮廓
	vtkSmartPointer<vtkStructuredGridOutlineFilter> outline = vtkSmartPointer<vtkStructuredGridOutlineFilter>::New();
	outline->SetInputData(plot3dOutput);
	// 等值面提取
	vtkSmartPointer<vtkContourFilter> contour = vtkSmartPointer<vtkContourFilter>::New();
	contour->SetInputData(plot3dOutput);
	// 在 range[0] 到 range[1] 的范围内提取 5 个等值面
	contour->GenerateValues(5, range[0], range[1]);

	// 3. mapper
	vtkSmartPointer<vtkPolyDataMapper> outlineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	vtkSmartPointer<vtkPolyDataMapper> contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();

	// 4. actor
	vtkSmartPointer<vtkActor> outlineActor = vtkSmartPointer<vtkActor>::New();
	vtkSmartPointer<vtkActor> contourActor = vtkSmartPointer<vtkActor>::New();

	// 5. renderer
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
	renderer->SetBackground(0.3, 0.6, 0.3); // Background Color: Green

	// 6. connect
	outlineMapper->SetInputConnection(outline->GetOutputPort());
	contourMapper->SetInputConnection(contour->GetOutputPort());
	outlineActor->SetMapper(outlineMapper);
	contourActor->SetMapper(contourMapper);
	renderer->AddActor(outlineActor);
	renderer->AddActor(contourActor);

	this->_pVTKWidget->renderWindow()->AddRenderer(renderer);
	this->_pVTKWidget->renderWindow()->Render();
}

VTKContour::~VTKContour()
{}

本程序首先获得了 plot3dOutput 的标量数据,从中得到了数据范围 range,使用 vtkContourFilter 等值面提取类,通过 contour->GenerateValues(5, range[0], range[1]) 提取了在 range[0] 到 range[1] 的范围内提取 5 个等值面。

运行结果:

在这里插入图片描述

空间函数数据的等值面提取

在本实例中,我们将用到vtkQuadric、vtkSampleFunction、vtkContourFilter三个类,分别是二次曲面函数、函数曲面抽样和等高滤波。

vtkQuadric负责二次曲面基本参数的设置,vtkSampleFunction则是对二次曲面进行等间隔逐点采样,在本例中采样点数为303030。vtkContourFilter负责将采集到空间点,转成vtkPolyData型对象。

#include "VTKContour.h"

#include <vtkConeSource.h>
#include <vtkSTLReader.h>
#include <vtkMultiBlockPLOT3DReader.h>
#include <vtkDataSet.h>
#include <vtkMultiBlockDataSet.h>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkShrinkPolyData.h>
#include <vtkStructuredGridGeometryFilter.h>
#include <vtkStructuredGridOutlineFilter.h>
#include <vtkContourFilter.h>
#include <vtkQuadric.h>
#include <vtkSampleFunction.h>
#include <vtkLookupTable.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>

VTKContour::VTKContour(QWidget* parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	_pVTKWidget = new QVTKOpenGLNativeWidget();
	this->setCentralWidget(_pVTKWidget);
	// this->showMaximized();

	// 1. generate data
	// 二次曲面
	vtkSmartPointer<vtkQuadric> quadric = vtkSmartPointer<vtkQuadric>::New();
	quadric->SetCoefficients(0.5, 1, 0.2, 0, 0.1, 0, 0, 0.2, 0, 0);
	// 对二次曲面进行等间隔逐点采样
	vtkSmartPointer<vtkSampleFunction> sample = vtkSmartPointer<vtkSampleFunction>::New();
	// 设置采样分辨率为 30*30*30
	sample->SetSampleDimensions(30, 30, 30);
	sample->SetImplicitFunction(quadric);

	// 2. filter
	// 等值面提取,将采集到的空间点,转成 vtkPolyData 型对象
	vtkSmartPointer<vtkContourFilter> contour = vtkSmartPointer<vtkContourFilter>::New();
	contour->SetInputConnection(sample->GetOutputPort());
	// 在 [0, 1.2] 的范围内提取 5 个等值面
	contour->GenerateValues(5, 0, 1.2);

	// 3. mapper
	vtkSmartPointer<vtkPolyDataMapper> contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();

	// 4. actor
	vtkSmartPointer<vtkActor> contourActor = vtkSmartPointer<vtkActor>::New();

	// 5. renderer
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
	renderer->SetBackground(0.3, 0.6, 0.3); // Background Color: Green

	// 6. connect
	contourMapper->SetInputConnection(contour->GetOutputPort());
	contourActor->SetMapper(contourMapper);
	renderer->AddActor(contourActor);

	this->_pVTKWidget->renderWindow()->AddRenderer(renderer);
	this->_pVTKWidget->renderWindow()->Render();
}

VTKContour::~VTKContour()
{}

运行结果:

在这里插入图片描述

资源下载

https://github.com/UestcXiye/VTKContour

参考

  1. https://www.bilibili.com/video/BV11K411C7j9
  2. https://blog.csdn.net/m0_45306991/article/details/124710932
  3. https://www.cnblogs.com/phoenixdsg/p/6193904.html
  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
VTK中,可以使用vtkContourFilter类来显示三维模型的等值线。vtkContourFilter是一种数据过滤器,可以根据给定的等值参数从输入数据集中提取等值线。以下是使用vtkContourFilter显示三维模型的等值线的基本步骤: 1. 加载三维模型数据集并创建vtkPolyData对象。 2. 创建vtkContourFilter对象并设置等值参数。 3. 将vtkPolyData对象作为vtkContourFilter对象的输入。 4. 使用vtkPolyDataMapper和vtkActor将vtkContourFilter对象的输出映射到可视化管道中。 下是一个简单的示例代码,演示如何在VTK中显示三维模型的等值线: ```python import vtk # 1.加载三维模型数据集并创建vtkPolyData对象 reader = vtk.vtkSTLReader() reader.SetFileName("example.stl") reader.Update() polydata = reader.GetOutput() # 2.创建vtkContourFilter对象并设置等值参数 contour = vtk.vtkContourFilter() contour.SetInputData(polydata) contour.SetValue(0, 0.5) # 设置等值参数为0.5 # 3.将vtkPolyData对象作为vtkContourFilter对象的输入 # 4.使用vtkPolyDataMapper和vtkActor将vtkContourFilter对象的输出映射到可视化管道中 mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(contour.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) # 创建可视化窗口和渲染器 renderer = vtk.vtkRenderer() renderer.AddActor(actor) renderWindow = vtk.vtkRenderWindow() renderWindow.AddRenderer(renderer) # 创建交互器并启动渲染 interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(renderWindow) interactor.Initialize() renderWindow.Render() interactor.Start() ``` 在上的示例中,我们加载了一个STL格式的三维模型数据集,并使用vtkContourFilter提取了等值线。然后,我们将vtkContourFilter对象的输出映射到可视化管道中,并通过vtkRenderWindowInteractor启动渲染。在渲染窗口中,我们可以看到三维模型的等值线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值