VTK 数据处理:特征边提取

2024-05-26 16:04
文章标签 提取 特征 数据处理 vtk

本文主要是介绍VTK 数据处理:特征边提取,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

VTK 数据处理:特征边提取

  • VTK 数据处理:特征边提取
    • 原理
    • 实例 1:边界边提取
    • 实例 2:模型特征边提取
    • 实例 3:利用 vtkFeatureEdges 提取的边界补洞
    • 实例 4:利用 vtkFillHolesFilter 补洞

VTK 数据处理:特征边提取

原理

VTK 的特征边提取只针对 PolyData,属于拓扑操作。

可以提取出 4 种类型的边:

  1. 边界边:只被 1 个网格使用的边;
  2. 流形边:被 2 个网格使用的边;
  3. 非流形边:被 2 个以上网格使用的边,一般不会在 PolyData 中出现;
  4. 特征边:属于流形边的一种,当一条流形边关联的两个面片的夹角大于特征角的话,它就是特征边。

实例 1:边界边提取

本实例创建了一个 vtkDiskSource 对象 disk,通过 vtkFeatureEdges 类提取 disk 的边界边,并设置不提取流形边、非流形边和特征边,并显示边界边的颜色以作区分。

VTKBoundaryEdge.h:

#pragma once#include <QtWidgets/QMainWindow>
#include "ui_VTKFeatureEdge.h"#include <QVTKOpenGLNativeWidget.h>class VTKBoundaryEdge : public QMainWindow
{Q_OBJECTpublic:VTKBoundaryEdge(QWidget* parent = nullptr);~VTKBoundaryEdge();private:Ui::VTKFeatureEdgeClass ui;QVTKOpenGLNativeWidget* _pVTKWidget = nullptr;
};

VTKBoundaryEdge.cpp:

#include "VTKBoundaryEdge.h"#include <vtkDiskSource.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkPolyData.h>
#include <vtkFeatureEdges.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>VTKBoundaryEdge::VTKBoundaryEdge(QWidget* parent) : QMainWindow(parent)
{ui.setupUi(this);_pVTKWidget = new QVTKOpenGLNativeWidget();this->setCentralWidget(_pVTKWidget);vtkNew<vtkRenderer> renderer;this->_pVTKWidget->renderWindow()->AddRenderer(renderer);this->_pVTKWidget->renderWindow()->Render();vtkNew<vtkDiskSource> disk;disk->Update();vtkNew<vtkFeatureEdges> featureEdges;featureEdges->SetInputConnection(disk->GetOutputPort());featureEdges->BoundaryEdgesOn(); // 提取边界边设置打开featureEdges->ManifoldEdgesOff();featureEdges->NonManifoldEdgesOff();featureEdges->FeatureEdgesOff();featureEdges->ColoringOn(); // 显示颜色vtkNew<vtkPolyDataMapper> diskMapper;diskMapper->SetInputConnection(disk->GetOutputPort());vtkNew<vtkPolyDataMapper> edgeMapper;edgeMapper->SetInputConnection(featureEdges->GetOutputPort());vtkNew<vtkActor> diskActor;diskActor->SetMapper(diskMapper);vtkNew<vtkActor> edgeActor;edgeActor->SetMapper(edgeMapper);renderer->AddActor(diskActor);renderer->AddActor(edgeActor);
}VTKBoundaryEdge::~VTKBoundaryEdge()
{
}

运行结果:

在这里插入图片描述

实例 2:模型特征边提取

前面提到特征边的识别取决于两个面片的夹角,如下图所示,指针指着的角就是夹角,VTK 默认将该角大于 30 度的都视为特征边。可以看出,连续性不是很好的边都被视为特征边。

在这里插入图片描述

本实例使用 vtkBYUReader 读取了一个牛的模型,并用 vtkFeatureEdges 类提取了模型的特征边,并设置不提取流形边、非流形边和边界边,并显示特征边的颜色以作区分。

VTKFeatureEdge.h:

#pragma once#include <QtWidgets/QMainWindow>
#include "ui_VTKFeatureEdge.h"#include <QVTKOpenGLNativeWidget.h>class VTKFeatureEdge : public QMainWindow
{Q_OBJECTpublic:VTKFeatureEdge(QWidget* parent = nullptr);~VTKFeatureEdge();private:Ui::VTKFeatureEdgeClass ui;QVTKOpenGLNativeWidget* _pVTKWidget = nullptr;
};

VTKFeatureEdge.cpp:

#include "VTKFeatureEdge.h"#include <vtkBYUReader.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkPolyData.h>
#include <vtkFeatureEdges.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>VTKFeatureEdge::VTKFeatureEdge(QWidget* parent): QMainWindow(parent)
{ui.setupUi(this);_pVTKWidget = new QVTKOpenGLNativeWidget();this->setCentralWidget(_pVTKWidget);vtkNew<vtkRenderer> renderer;this->_pVTKWidget->renderWindow()->AddRenderer(renderer);this->_pVTKWidget->renderWindow()->Render();vtkNew<vtkBYUReader> reader;reader->SetFileName("cow.g");reader->Update();vtkNew<vtkFeatureEdges> featureEdges;featureEdges->SetInputConnection(reader->GetOutputPort());featureEdges->BoundaryEdgesOff();featureEdges->ManifoldEdgesOn(); // 提取特征边设置打开featureEdges->NonManifoldEdgesOff();featureEdges->FeatureEdgesOff();featureEdges->ColoringOn(); // 显示颜色vtkNew<vtkPolyDataMapper> cowMapper;cowMapper->SetInputConnection(reader->GetOutputPort());vtkNew<vtkPolyDataMapper> edgeMapper;edgeMapper->SetInputConnection(featureEdges->GetOutputPort());vtkNew<vtkActor> cowActor;cowActor->SetMapper(cowMapper);vtkNew<vtkActor> edgeActor;edgeActor->SetMapper(edgeMapper);renderer->AddActor(cowActor);renderer->AddActor(edgeActor);
}VTKFeatureEdge::~VTKFeatureEdge()
{}

实例 3:利用 vtkFeatureEdges 提取的边界补洞

建立一个 vtkPlane 类对象作为截面, 设置好 plane 的法向量。利用 vtkClipPolyData 类将模型作为输入,将 plane 设为 clipper 的截取函数。再用 vtkFeatureEdges 类提取截取后模型 clipper 的边界边。将边界边作为 vtkStripper 类对象 boundaryStrips 的输入,将 featureEdges 生成的三角片连接成三角带,再转换成多边形数据 boundaryPolyData。最后把 clipper、featureEdges、boundaryPolyData 全部显示出来。

#include "VTKFeatureEdge.h"#include <vtkBYUReader.h>
#include <vtkPlane.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkPolyData.h>
#include <vtkClipPolyData.h>
#include <vtkFeatureEdges.h>
#include <vtkStripper.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>VTKFeatureEdge::VTKFeatureEdge(QWidget* parent): QMainWindow(parent)
{ui.setupUi(this);_pVTKWidget = new QVTKOpenGLNativeWidget();this->setCentralWidget(_pVTKWidget);vtkNew<vtkRenderer> renderer;this->_pVTKWidget->renderWindow()->AddRenderer(renderer);this->_pVTKWidget->renderWindow()->Render();vtkNew<vtkBYUReader> reader;reader->SetFileName("cow.g");reader->Update();// 截面vtkNew<vtkPlane> plane;plane->SetOrigin(reader->GetOutput()->GetCenter());plane->SetNormal(1.0, -1.0, -1.0); // 设置截面的法向量// 截取模型vtkNew<vtkClipPolyData> clipper;clipper->SetInputData(reader->GetOutput());clipper->SetClipFunction(plane); // 将 plane 设为 clipper 的截取函数clipper->SetValue(0.0);vtkNew<vtkFeatureEdges> featureEdges;featureEdges->SetInputConnection(clipper->GetOutputPort());featureEdges->BoundaryEdgesOn();featureEdges->ManifoldEdgesOff(); // 提取特征边设置打开featureEdges->NonManifoldEdgesOff();featureEdges->FeatureEdgesOff();featureEdges->ColoringOn(); // 显示颜色// 建立三角带对象vtkNew<vtkStripper> boundaryStrips;boundaryStrips->SetInputConnection(featureEdges->GetOutputPort()); // 将 featureEdges 生成的三角片连接成三角带boundaryStrips->Update();vtkNew<vtkPolyData> boundaryPolyData;boundaryPolyData->SetPoints(boundaryStrips->GetOutput()->GetPoints());boundaryPolyData->SetPolys(boundaryStrips->GetOutput()->GetLines());vtkNew<vtkPolyDataMapper> clipperMapper;clipperMapper->SetInputConnection(clipper->GetOutputPort());vtkNew<vtkPolyDataMapper> edgeMapper;edgeMapper->SetInputConnection(featureEdges->GetOutputPort());vtkNew<vtkPolyDataMapper> boundaryMapper;boundaryMapper->SetInputData(boundaryPolyData);vtkNew<vtkActor> clipperActor;clipperActor->SetMapper(clipperMapper);vtkNew<vtkActor> edgeActor;edgeActor->SetMapper(edgeMapper);vtkNew<vtkActor> boundaryActor;boundaryActor->SetMapper(boundaryMapper);renderer->AddActor(clipperActor);renderer->AddActor(edgeActor);renderer->AddActor(boundaryActor);
}VTKFeatureEdge::~VTKFeatureEdge()
{}

运行结果:

在这里插入图片描述

实例 4:利用 vtkFillHolesFilter 补洞

vtkFillHolesFilter 是 VTK 中用于自动填充三角网格模型中洞的过滤器。vtkFillHolesFilter 支持多种数据格式,包括 vtkPolyData、vtkUnstructuredGrid、vtkStructuredGrid、vtkImageData 等。它还支持多种洞填充算法,包括 Delaunay 三角剖分、路径填充、平面填充等。使用 vtkFillHolesFilter 进行填洞时,可以保持原始模型的拓扑结构,避免生成不良的三角形。

vtkFillHolesFilter 的内部执行过程是首先检测出网格中的所有边界边,然后找出这些边界边中的每一个闭合回路,最后将这些闭合回路进行三角化(即生成三角网格)以实现填补的目的。这个类也是非常简单的,只需要设置需要填补的网格数据即可。

需要注意的是,有些边界的闭合回路是不需要三角化的,例如一个平面网格,若填补其四周的边界边,则会与原网格产生覆盖。vtkFillHolesFilters 中的 SetHoleSize() 函数可用于控制需要修补的漏洞面积的最大值,大于该值的漏洞则不需要填补处理。

#include "VTKFeatureEdge.h"#include <vtkBYUReader.h>
#include <vtkPlane.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkPolyData.h>
#include <vtkClipPolyData.h>
#include <vtkFeatureEdges.h>
#include <vtkStripper.h>
#include <vtkFillHolesFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>VTKFeatureEdge::VTKFeatureEdge(QWidget* parent): QMainWindow(parent)
{ui.setupUi(this);_pVTKWidget = new QVTKOpenGLNativeWidget();this->setCentralWidget(_pVTKWidget);vtkNew<vtkRenderer> renderer;this->_pVTKWidget->renderWindow()->AddRenderer(renderer);this->_pVTKWidget->renderWindow()->Render();vtkNew<vtkBYUReader> reader;reader->SetFileName("cow.g");reader->Update();// 截面vtkNew<vtkPlane> plane;plane->SetOrigin(reader->GetOutput()->GetCenter());plane->SetNormal(1.0, -1.0, -1.0); // 设置截面的法向量// 截取模型vtkNew<vtkClipPolyData> clipper;clipper->SetInputData(reader->GetOutput());clipper->SetClipFunction(plane); // 将 plane 设为 clipper 的截取函数clipper->SetValue(0.0);/*vtkNew<vtkFeatureEdges> featureEdges;featureEdges->SetInputConnection(clipper->GetOutputPort());featureEdges->BoundaryEdgesOn();featureEdges->ManifoldEdgesOff(); // 提取特征边设置打开featureEdges->NonManifoldEdgesOff();featureEdges->FeatureEdgesOff();featureEdges->ColoringOn(); // 显示颜色// 建立三角带对象vtkNew<vtkStripper> boundaryStrips;boundaryStrips->SetInputConnection(featureEdges->GetOutputPort()); // 将 featureEdges 生成的三角片连接成三角带boundaryStrips->Update();vtkNew<vtkPolyData> boundaryPolyData;boundaryPolyData->SetPoints(boundaryStrips->GetOutput()->GetPoints());boundaryPolyData->SetPolys(boundaryStrips->GetOutput()->GetLines());vtkNew<vtkPolyDataMapper> clipperMapper;clipperMapper->SetInputConnection(clipper->GetOutputPort());vtkNew<vtkPolyDataMapper> edgeMapper;edgeMapper->SetInputConnection(featureEdges->GetOutputPort());vtkNew<vtkPolyDataMapper> boundaryMapper;boundaryMapper->SetInputData(boundaryPolyData);vtkNew<vtkActor> clipperActor;clipperActor->SetMapper(clipperMapper);vtkNew<vtkActor> edgeActor;edgeActor->SetMapper(edgeMapper);vtkNew<vtkActor> boundaryActor;boundaryActor->SetMapper(boundaryMapper);renderer->AddActor(clipperActor);renderer->AddActor(edgeActor);renderer->AddActor(boundaryActor);*/vtkNew<vtkFillHolesFilter> fillHolesFilter;fillHolesFilter->SetInputConnection(clipper->GetOutputPort());fillHolesFilter->SetHoleSize(1000.0); // 大于该值的漏洞则不需要填补处理vtkNew<vtkPolyDataMapper> fillHolesMapper;fillHolesMapper->SetInputConnection(fillHolesFilter->GetOutputPort());vtkNew<vtkActor> fillHolesActor;fillHolesActor->SetMapper(fillHolesMapper);renderer->AddActor(fillHolesActor);
}VTKFeatureEdge::~VTKFeatureEdge()
{}

运行结果:

在这里插入图片描述

这篇关于VTK 数据处理:特征边提取的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1004930

相关文章

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

Python对PDF书签进行添加,修改提取和删除操作

《Python对PDF书签进行添加,修改提取和删除操作》PDF书签是PDF文件中的导航工具,通常包含一个标题和一个跳转位置,本教程将详细介绍如何使用Python对PDF文件中的书签进行操作... 目录简介使用工具python 向 PDF 添加书签添加书签添加嵌套书签Python 修改 PDF 书签Pytho

MySQL重复数据处理的七种高效方法

《MySQL重复数据处理的七种高效方法》你是不是也曾遇到过这样的烦恼:明明系统测试时一切正常,上线后却频频出现重复数据,大批量导数据时,总有那么几条不听话的记录导致整个事务莫名回滚,今天,我就跟大家分... 目录1. 重复数据插入问题分析1.1 问题本质1.2 常见场景图2. 基础解决方案:使用异常捕获3.

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Python实现常用文本内容提取

《Python实现常用文本内容提取》在日常工作和学习中,我们经常需要从PDF、Word文档中提取文本,本文将介绍如何使用Python编写一个文本内容提取工具,有需要的小伙伴可以参考下... 目录一、引言二、文本内容提取的原理三、文本内容提取的设计四、文本内容提取的实现五、完整代码示例一、引言在日常工作和学

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并