VTK学习(一)SetInputData()和SetInputConnection()替换SetInput()

本文详细介绍了VTK6中向后不兼容的更改,重点解释了SetInputData()和SetInputConnection()替代SetInput()的原因。文章通过实例展示了如何在VTK6中正确建立管道连接和处理独立数据集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VTK6引入了一些向后不兼容的更改。这里更详细地描述了这些变化背后的原因。其中一个更改是使用SetInputData()和SetInputConnection()替换SetInput()。

VTK4中管道对象连接连接

someFilter - > SetInput ( someReader - > GetOutput ());
VTK5中更改为

someFilter - > SetInputConnection ( someReader - > GetOutputPort ());
SetInput()和相关方法被保留为向后兼容性。

VTK6中 此方法和所有相关功能(如SetSource)在VTK 6中已被删除。这背后的主要原因是在将数据对象与管道对象分离(参见此处有详细信息)时,不可能保留此方法。在VTK 5中,SetInput()是使用SetInputConnection()实现的,但这需要访问该算法及其输出端口给定一个数据对象。在VTK 6中,由于数据对象不再引用生成它的算法,所以不可能建立仅给出数据对象的流水线连接。


为了便于将独立数据对象分配给算法的输入,我们在VTK 6中引入了一组方便的功能。下面是一个例子:

someFilter - > SetInputData ( aDataObject );
请注意,即使下面的代码将被编译,它不会创建一个管道连接,也不应该用于代替SetInputConnection()。

someFilter - > SetInputData ( someReader - > GetOutput ());
将数据对象与管道对象分离的另一个优点是开发人员不再需要创建输入副本,以便使用内部过滤器。以前,这是算法正常运行所必需的:

  1. void MyFilter::RequestData(…)
  2. {
  3. vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT());
  4. vtkDataObject* copy = input->NewInstance();
  5. copy->ShallowCopy(input);
  6. this->InternalFilter->SetInput(copy);
  7. this->InternalFilter->Update();
  8. }
现在可以用以下代替

  1. void MyFilter::RequestData(…)
  2. {
  3. vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT());
  4. this->InternalFilter->SetInputData(input);
  5. this->InternalFilter->Update();
  6. }

另一个优点是,此更改会从管道中删除一些循环引用,从而无需使用垃圾回收器。这对使用大型管道时VTK的性能有明显的影响。

这种变化可能对VTK社区产生最大的影响。同时,这是最简单的解决方案。这是一个经验法则:

  • 如果要建立管道连接,请使用SetInputConnection
  • 如果要处理独立数据集,请使用SetInputData

以下是一些具体的例子。注意,即使我们在所有这些示例中使用SetInput(),类似的方法,如SetSource()也应该遵循相同的模式。查找SetSourceConnection()或SetSourceData()为例。此外,我们忽略这些示例中的端口号,但大多数应该使用端口号。

例子1

anotherFilter->SetInput(aFilter->GetOutput());
anotherFilter->SetInputConnection(aFilter->GetOutputPort());


例子2

  1. vtkDataObject* output = aFilter->GetOutput();
  2. anotherFilter->SetInput(output);
anotherFilter->SetInputConnection(aFilter->GetOutputPort());
例子3

  1. vtkPolyData *pd = vtkPolyData::New();
  2. aFilter->SetInput(pd);
  1. vtkPolyData *pd = vtkPolyData::New();
  2. aFilter->SetInputData(pd);
例子4
  1. vtkDataObject* output = aFilter->GetOutput();
  2. aFilter->Update();
  3. anotherFilter->SetInput(output);
  1. vtkDataObject* output = aFilter->GetOutput();
  2. aFilter->Update();
  3. anotherFilter->SetInputData(output);
例子5

  1. void myfunction(vtkDataObject* dobj)
  2. {
  3. vtkAFilter* aFilter = vtkAFilter::New();
  4. aFilter->SetInput(dobj);
  5. aFilter->Update();
  6. // …
  7. }
This example is also ambiguous. You need to trace it up to find the origin of dobj. If this is the common use:
myfunction(aFilter->GetOutput());
you will have to refactor myfunction to take an algorithm and an output port. For example:
  1. void myfunction(vtkAlgorithm* alg, int port)
  2. {
  3. vtkAFilter* aFilter = vtkAFilter::New();
  4. aFilter->SetInputConnection(alg->GetOutputPort(port));
  5. aFilter->Update();
  6. // …
  7. }
  8. myfunction(aFilter, 0);
If this is the common use:
  1. vtkPolyData* pd = vtkPolyData::New();
  2. // fill pd
  3. myfunction(pd);
then replacing SetInput() with SetInputData() would work.



https://www.vtk.org/Wiki/VTK/VTK_6_Migration/Replacement_of_SetInput


例子

  1. #include "vtkAutoInit.h"
  2. VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
  3. VTK_MODULE_INIT(vtkInteractionStyle);
  4. /**********************************************************************
  5. 文件名: 2.3_Viewport.cpp
  6. Copyright (c) 张晓东, 罗火灵. All rights reserved.
  7. 更多信息请访问:
  8. http://www.vtkchina.org (VTK中国)
  9. http://blog.youkuaiyun.com/www_doling_net (东灵工作室)
  10. **********************************************************************/
  11. /**********************************************************************
  12. 文件名: 2.3_Viewport.cpp
  13. Copyright (c) 张晓东, 罗火灵. All rights reserved.
  14. 更多信息请访问:
  15. http://www.vtkchina.org (VTK中国)
  16. http://blog.youkuaiyun.com/www_doling_net (东灵工作室)
  17. **********************************************************************/
  18. #include <vtkConeSource.h>
  19. #include <vtkCubeSource.h>
  20. #include <vtkCylinderSource.h>
  21. #include <vtkSphereSource.h>
  22. #include <vtkPolyDataMapper.h>
  23. #include <vtkRenderer.h>
  24. #include <vtkRenderWindow.h>
  25. #include <vtkActor.h>
  26. #include <vtkRenderWindowInteractor.h>
  27. #include <vtkSmartPointer.h>
  28. int main()
  29. {
  30. vtkSmartPointer<vtkConeSource> cone = vtkSmartPointer<vtkConeSource>::New();
  31. vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
  32. vtkSmartPointer<vtkCylinderSource> cylinder = vtkSmartPointer<vtkCylinderSource>::New();
  33. vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
  34. vtkSmartPointer<vtkPolyDataMapper> coneMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  35. coneMapper->SetInputData(cone->GetOutput());//SetInput改为SetInputData
  36. vtkSmartPointer<vtkPolyDataMapper> cubeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  37. cubeMapper->SetInputData(cube->GetOutput());
  38. vtkSmartPointer<vtkPolyDataMapper> cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  39. cylinderMapper->SetInputData(cylinder->GetOutput());
  40. vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  41. sphereMapper->SetInputData(sphere->GetOutput());
  42. vtkSmartPointer<vtkActor> coneActor = vtkSmartPointer<vtkActor>::New();
  43. coneActor->SetMapper(coneMapper);
  44. vtkSmartPointer<vtkActor> cubeActor = vtkSmartPointer<vtkActor>::New();
  45. cubeActor->SetMapper(cubeMapper);
  46. vtkSmartPointer<vtkActor> cylinderActor = vtkSmartPointer<vtkActor>::New();
  47. cylinderActor->SetMapper(cylinderMapper);
  48. vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();
  49. sphereActor->SetMapper(sphereMapper);
  50. vtkSmartPointer<vtkRenderer> renderer1 = vtkSmartPointer<vtkRenderer>::New();
  51. renderer1->AddActor(coneActor);
  52. renderer1->SetBackground(1.0, 0.0, 0.0);
  53. renderer1->SetViewport(0.0, 0.0, 0.5, 0.5);
  54. vtkSmartPointer<vtkRenderer> renderer2 = vtkSmartPointer<vtkRenderer>::New();
  55. renderer2->AddActor(cubeActor);
  56. renderer2->SetBackground(0, 0, 0);
  57. renderer2->SetViewport(0.5, 0.0, 1.0, 0.5);
  58. vtkSmartPointer<vtkRenderer> renderer3 = vtkSmartPointer<vtkRenderer>::New();
  59. renderer3->AddActor(cylinderActor);
  60. renderer3->SetBackground(0.0, 0.0, 1.0);
  61. renderer3->SetViewport(0.0, 0.5, 0.5, 1.0);
  62. vtkSmartPointer<vtkRenderer> renderer4 = vtkSmartPointer<vtkRenderer>::New();
  63. renderer4->AddActor(sphereActor);
  64. renderer4->SetBackground(1.0, 1.0, 0.0);
  65. renderer4->SetViewport(0.5, 0.5, 1.0, 1.0);
  66. vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
  67. renWin->AddRenderer(renderer1);
  68. renWin->AddRenderer(renderer2);
  69. renWin->AddRenderer(renderer3);
  70. renWin->AddRenderer(renderer4);
  71. renWin->SetSize(640, 480);
  72. renWin->Render();
  73. renWin->SetWindowName("Viewport");
  74. vtkSmartPointer<vtkRenderWindowInteractor> interactor =
  75. vtkSmartPointer<vtkRenderWindowInteractor>::New();
  76. interactor->SetRenderWindow(renWin);
  77. renWin->Render();
  78. interactor->Initialize();
  79. interactor->Start();
  80. return EXIT_SUCCESS;
  81. }




运行在运行《VTK图形图像进阶》第五章5.3_ImageResliceExample.cpp时,会提示MetaImage cannot read data from file或者显示窗口是空白,后来搜索了VTKExample中的例子,发现可以这样解决:

imgActor->SetInput(colorMap->GetOutput());
改为
imgActor->GetMapper()->SetInputConnection(colorMap->GetOutputPort());

同时添加头文件

#include <vtkImageMapper3D.h>
参考链接https://heliublog.com/2017/05/10/VTK%E6%8F%90%E7%A4%BAMetaImage%20cannot%20read%20data%20from%20file/

<think>首先,用户的问题是:“我想在MITK中保存分割结果并在VTK中绘制 请问使用VTK绘制从MITK中保存的分割结果”。这是个关于MITKVTK集成的问题。 用户提到在MITK中保存分割结果,然后在VTK中绘制。我需要基于提供的引用系统指令来构建回答。 回顾提供的引用: - 引用[1]: 介绍MITK的功能,它结合了ITKVTK,用于医学图像分析。 - 引用[2]: 提到MITK的核心框架,允许与其他库如VTK无缝集成。 - 引用[3]: 展示了个简单的MITK图像分割代码示例(阈值分割)。 - 引用[4]: 展示了如在MITK中设置查找表(Lookup Table),涉及VTK对象。 - 引用[5]: 讨论图像分割在MIMICS中的过程,但这不是直接相关;重点是分割是基础步骤。 用户的问题焦点是:保存MITK分割结果并用VTK绘制。分割结果可能是图像数据或表面数据(如网格)。 在MITK中,分割结果通常表示为mitk::Image或mitk::Surface对象: - mitk::Image: 用于体积图像数据。 - mitk::Surface: 用于表面网格数据,基于VTKvtkPolyData。 由于MITK使用VTK作为底层渲染,保存的结果可以很容易地在VTK中使用。 关键步骤: 1. **在MITK中保存分割结果**:用户需要将分割结果导出为VTK兼容的格式。 2. **在VTK中绘制**:读取保存的文件并使用VTK渲染。 可能的格式: - 对于图像数据:保存为.vtkVTK图像格式)或.raw等。 - 对于表面数据:保存为.vtk, .vtp, .stl等。 从引用[3]中,有MITK分割的代码示例: ```cpp mitk::Image::Pointer segmentation = mitk::Image::New(); segmentation->Initialize(ctImage); // ... 分割逻辑 ... ``` 这创建了个mitk::Image对象。 在MITK中,保存数据可以使用mitk::IOUtils::Save函数。 然后,在VTK中,可以使用vtkImageReader或vtkPolyDataReader读取文件。 引用[4]展示了如VTK对象集成到MITK中,特别是使用vtkLookupTable。这表明VTKMITK对象可以互操作。 所以,回答应该包括: - 如保存分割结果(如mitk::Image或mitk::Surface)为VTK格式。 - 如VTK中读取绘制。 步骤概述: 1. **在MITK中保存分割结果**: - 如果分割结果是mitk::Image,保存为VTK图像文件(如.vtk)。 - 如果分割结果是mitk::Surface(例如,从分割中提取的表面),保存为VTK多边形数据文件(如.vtp)。 2. **在VTK中绘制**: - 使用VTK读取器(如vtkImageReader或vtkXMLPolyDataReader)读取文件。 - 创建映射器(mapper)演员(actor)来渲染。 - 设置渲染器渲染窗口。 系统指令要求: - 使用中文回答。 - 结构清晰,逐步解决问题。 - 行内数学表达式用$...$,独立公式用$$...$$(但这个问题可能不需要数学公式)。 - 生成相关问题。 - 在引用的段落末尾添加引用标识。 参考引用: - 引用[2]说MITK允许与其他库无缝集成,如VTK。[^2] - 引用[3]提供分割示例。[^3] - 引用[4]展示VTK对象在MITK中的使用。[^4] 回答结构: 1. 介绍:简要解释如实现。 2. 步骤: a. 在MITK中保存分割结果。 b. 在VTK中绘制。 3. 代码示例(如果可能)。 4. 注意事项。 5. 生成相关问题。 代码示例:由于引用中有C++代码,我可以提供类似的代码片段。 确保回答真实可靠:基于MITKVTK的文档,MITK确实使用VTK,所以数据共享是直接的。 最终回答: - 中文。 - 清晰结构。</think>### 在MITK中保存分割结果并在VTK中绘制的方法 要实现从MITK保存分割结果并在VTK中绘制,需要分两步进行:首先在MITK中完成分割并导出结果,然后在VTK中读取渲染数据。MITK 基于 VTK 构建,因此两者可以无缝集成。分割结果可以是体积图像(如 `mitk::Image`)或表面网格数据(如 `mitk::Surface`,其底层为 VTK 的 `vtkPolyData`)。以下是详细步骤,基于 MITK VTK 的标准工作流程。 #### 步骤 1: 在 MITK 中保存分割结果 在 MITK 中,分割结果通常通过 `mitk::Image`(体积数据)或 `mitk::Surface`(表面网格)表示。保存时,需导出为 VTK 兼容的格式: - **体积图像**(如阈值分割结果):保存为 `.vtk`(VTK 结构化点格式)或 `.vti`(VTK XML 图像格式)。 - **表面网格**(如从分割中提取的 3D 模型):保存为 `.vtp`(VTK XML 多边形数据格式)或 `.stl`。 以下是个 MITK 代码示例(基于引用[3]的分割逻辑),展示如执行分割并保存结果: ```cpp #include <mitkImage.h> #include <mitkIOUtil.h> #include <mitkSurface.h> #include <mitkImageToSurfaceFilter.h> // 假设已有个分割后的 mitk::Image 对象(例如通过阈值分割) mitk::Image::Pointer segmentation = mitk::Image::New(); segmentation->Initialize(ctImage); // ctImage 是输入图像,分割逻辑在此省略[^3] // 选项1: 直接保存体积图像(如 .vtk 格式) mitk::IOUtil::Save(segmentation, "segmentation_volume.vtk"); // 选项2: 如果需要表面网格(例如用于 3D 渲染),先转换为 mitk::Surface mitk::ImageToSurfaceFilter::Pointer surfaceFilter = mitk::ImageToSurfaceFilter::New(); surfaceFilter->SetInput(segmentation); surfaceFilter->Update(); mitk::Surface::Pointer surface = surfaceFilter->GetOutput(); // 保存表面网格为 .vtp 格式 mitk::IOUtil::Save(surface, "segmentation_surface.vtp"); ``` **关键点**: - 使用 `mitk::IOUtil::Save` 函数导出数据,支持多种 VTK 格式[^1][^2]。 - 如果分割结果是二值图像(如前景/背景),保存为 `.vtk` 即可;如果需要渲染 3D 表面,建议转换为 `mitk::Surface` 并保存为 `.vtp`。 - MITK 的分割工具(如交互式分割)可直接导出结果,无需手动代码[^5]。 #### 步骤 2: 在 VTK 中绘制分割结果 在 VTK 中,读取保存的文件并使用渲染管线进行绘制。以下是 Python 示例(也可用 C++),展示如读取可视化: - **对于体积图像(.vtk 文件)**:使用 `vtkStructuredPointsReader` 或 `vtkXMLImageDataReader`。 - **对于表面网格(.vtp 文件)**:使用 `vtkXMLPolyDataReader`。 ```python import vtk # 读取体积图像文件 reader_volume = vtk.vtkStructuredPointsReader() reader_volume.SetFileName("segmentation_volume.vtk") reader_volume.Update() # 创建体积渲染的映射器(mapper)演员(actor) mapper_volume = vtk.vtkGPUVolumeRayCastMapper() mapper_volume.SetInputConnection(reader_volume.GetOutputPort()) actor_volume = vtk.vtkVolume() actor_volume.SetMapper(mapper_volume) # 或者:读取表面网格文件(.vtp) reader_surface = vtk.vtkXMLPolyDataReader() reader_surface.SetFileName("segmentation_surface.vtp") reader_surface.Update() # 创建表面渲染的映射器演员 mapper_surface = vtk.vtkPolyDataMapper() mapper_surface.SetInputConnection(reader_surface.GetOutputPort()) actor_surface = vtk.vtkActor() actor_surface.SetMapper(mapper_surface) # 设置渲染器 renderer = vtk.vtkRenderer() renderer.AddActor(actor_surface) # 或 actor_volume,取决于数据类型 renderer.SetBackground(0.1, 0.2, 0.4) # 背景色 # 创建渲染窗口 render_window = vtk.vtkRenderWindow() render_window.AddRenderer(renderer) render_window.SetSize(800, 600) # 启动交互式渲染 interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(render_window) interactor.Initialize() interactor.Start() ``` **关键点**: - 体积图像适合内部结构可视化(如 CT 数据),使用 `vtkGPUVolumeRayCastMapper` 进行渲染。 - 表面网格适合快速 3D 模型显示(如器官表面),使用 `vtkPolyDataMapper`[^4]。 - 如果需要调整颜色或透明度,参考 VTK 的 `vtkLookupTable`(类似 MITK 的 LookupTableProperty[^4])。 #### 注意事项 - **数据兼容性**:MITK VTK 共享相同的数据结构(如 `vtkImageData` `vtkPolyData`),因此导出/导入过程高效且无数据丢失[^2]。 - **性能优化**:对于大型医学图像,保存为 `.vti` 或 `.vtp`(XML 格式)比二进制格式更可靠。 - **错误处理**:确保 MITK 分割结果有效(如非空指针),并在 VTK 中使用 `Update()` 方法验证读取成功。 - **引用示例**:MITK 的分割导出功能可直接用于手术规划或放射治疗场景[^1][^5]。 通过以上步骤,您可以在 MITK 中处理分割任务,并在 VTK 中实现高质量的可视化。MITK 的框架设计使其与 VTK 集成简单,适用于医学影像分析[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值