【三维重建】三角网格中轴骨架线提取

三维网格中轴线提取

  • 方法介绍
  • 实现提取

三维网格中轴线提取是计算机图形学和三维建模领域中的一个重要技术,它对于理解三维形状的拓扑结构和几何特性具有重要意义。

方法介绍

以下是几种常见的三维网格中轴线提取方法:

  1. 基于距离变换的方法
    基本原理:首先计算三维网格中每个点到网格边界的距离,形成距离场。然后,根据距离场的分布,通过细化算法提取中轴线。这种方法的核心在于距离变换和细化操作的结合。
    步骤:
    对三维网格进行距离变换,计算每个点到最近边界的距离。
    对距离变换结果进行排序,优先处理距离较小的点。
    通过细化算法逐步剥离外层点,直至提取出中轴线。
  2. 基于中轴球的方法
    基本原理:为每个网格端点计算一个中轴球,中轴球的中心即为中轴点。通过计算所有网格端点的中轴球,最终生成中轴网格。
    步骤:
    估计网格上所有点的法向,以模拟平滑表面。
    将模型分割成体素,每个体素具有特定尺寸。
    计算每个网格端点的中轴球,包括中轴点和中轴半径。
    通过所有中轴点生成中轴网格。
  3. 基于局部曲面拟合的方法
    应用场景:特别适用于处理点云数据,如三维激光扫描数据。
    步骤:
    对原始点云数据进行预处理,包括配准和去噪。
    对点云进行横断面切片处理,得到多个切片点云。
    对每个切片点云进行局部曲面拟合,提取切片中心。
    将所有切片中心拟合得到整体的中轴线。
  4. 基于拓扑收缩的方法
    基本原理:通过定义一个收缩力函数,控制三维网格内表面的收缩过程,直至收缩成一维的中轴线。
    挑战:如何定义收缩力函数以平衡收缩和吸引约束,同时保留骨架线的拓扑性和中间轴的中心位置。
  5. 基于骨架提取的算法
    如Medial Axis Transform (MAT):这类算法通常涉及对三维网格进行骨架化处理,通过逐步剥离外层网格元素,最终得到中轴线或骨架结构。

实现提取

输入:半圆环网格

在这里插入图片描述

std::vector<Point> m_points;
std::vector<std::vector<int>> m_faces;
std::unordered_map<int, std::vector<int>> m_adjacency;
std::unordered_set<int> m_boundaryPoints;
std::unordered_set<int> m_skeletonPoints;
std::unordered_set<Edge, EdgeHash> m_skeletonEdges;void buildAdjacencyList() {for (const auto& face : m_faces) {for (int i = 0; i < 3; ++i) {int v1 = face[i];int v2 = face[(i + 1) % 3];m_adjacency[v1].push_back(v2);m_adjacency[v2].push_back(v1);}}
}void findBoundaryPoints() {std::unordered_set<Edge, EdgeHash> edges;for (const auto& face : m_faces) {for (int i = 0; i < 3; ++i) {Edge e(face[i], face[(i + 1) % 3]);if (edges.find(e) != edges.end()) {edges.erase(e);}else {edges.insert(e);}}}for (const auto& e : edges) {m_boundaryPoints.insert(e.v1);m_boundaryPoints.insert(e.v2);}
}
void grassfirePropagation() {// Distance initialization and boundary point queuestd::vector<float> distanceFromBoundary(m_points.size(), std::numeric_limits<float>::max());std::queue<int> queue;// Initialize boundary pointsfor (int idx : m_boundaryPoints) {distanceFromBoundary[idx] = 0;queue.push(idx);}// Distance update using BFSwhile (!queue.empty()) {int current = queue.front();queue.pop();for (int neighborIdx : m_adjacency[current]) {float newDistance = distanceFromBoundary[current] + distance(m_points[current], m_points[neighborIdx]);if (newDistance < distanceFromBoundary[neighborIdx]) {distanceFromBoundary[neighborIdx] = newDistance;queue.push(neighborIdx);}}}// Find local maxima (skeleton points)for (int i = 0; i < m_points.size(); ++i) {if (m_boundaryPoints.count(i) > 0) continue;  // Skip boundary pointsbool isLocalMaximum = true;for (int neighborIdx : m_adjacency[i]) {if (distanceFromBoundary[neighborIdx] > distanceFromBoundary[i]) {isLocalMaximum = false;break;}}if (isLocalMaximum) {m_skeletonPoints.insert(i);}}
}

在这里插入图片描述


http://www.ppmy.cn/embedded/103964.html

相关文章

Springboot + AOP + 注解做全局日志拦截并且排除敏感属性以及接口相应时间

前言 我们在使用接口的时候需要有日志记录&#xff0c;然后我们也希望一些敏感参数不要出现在我们的日志里面保护用户的隐私 废话不多说我们直接上代码开干 依赖的选择&#xff0c;我们可以直接使用Springboot继承的aop依赖&#xff0c;可以单独导入我们aop依赖织入包 然后我…

★ 算法OJ题 ★ 力扣1089 - 复写零

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将和大家一起做一道双指针算法题--复写零~ 目录 一 题目 二 算法解析 2.1 算法思路 2.2 算法流程 三 编写算法 一 题目 1089. 复写零 - 力扣&#xff08;LeetCode&#xff09; 二 算法解析 2.1 算法思路 …

Unity本地化id查找器,luaparser函数参数查找

前言&#xff1a; 适用范围&#xff1a;Unity 中需要查找所有预制体里面的某一个脚本的属性值&#xff0c;或者Lua脚本里面的某一个属性值 本文介绍如何查找预制体和Lua脚本里面调用的本地化id 下面首先介绍改插件的功能以及使用方法&#xff0c;然后对该插件的原理进行说明 使…

命令模式的实际应用案例:从电梯控制系统到文本编辑器

命令模式的实际应用案例&#xff1a;从电梯控制系统到文本编辑器 引言 设计模式是软件工程中解决特定问题的经典方案&#xff0c;它们提供了灵活、可扩展的代码结构&#xff0c;能够在应对复杂系统设计时发挥重要作用。命令模式&#xff08;Command Pattern&#xff09;作为行…

【时时三省】(C语言基础)指针进阶6qsort函数的使用

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 qsort函数的使用 冒泡排序 qsort() 快速排序 它什么类型都可以用 比如&#xff1a; 整形数据 字符串数据 结构体排序 void gsort ( void * base&#xff0c;// base中存放的是待排…

复变函数在大模型中的应用

1. 导入 说来惭愧&#xff0c;我研究生时的研究方向是复分析&#xff0c;但毕业近十年来几乎没用到它。 我还记得实习时做自我介绍时&#xff0c;我说我的研究方向是复分析。面试官不太了解&#xff0c;我便解释说&#xff0c;这是关于对 -1 开平方得到的虚数 i 的研究。 在…

海信电视与《黑神话 :悟空》合作,大屏端流畅游戏体验如何保障?

上线即巅峰 国产3A游戏引发热潮 近期&#xff0c;首款国产3A游戏《黑神话&#xff1a;悟空》自上线以来&#xff0c;便迅速在各大游戏平台占据热销榜首&#xff0c;其销量及在线人数均刷新历史记录。同时&#xff0c;该游戏在各大社交媒体中也拥有超高讨论度&#xff0c;其精湛…

125.验证回文串

125.验证回文串 思路 双指针扫描数组&#xff0c;不相等返回false&#xff0c;否则返回true 代码一 class Solution { public:bool isPalindrome(string s) {int less.size();for(int i0;i<les;i){s[i]tolower(s[i]);}string res;for(int i0;i<les;i){if((s[i]>a&am…

多重中断Multiple interrupt

一、处理流程 多重中断就是中断的时候还能响应中断 因为本质上中断服务程序也是一个程序而已 多增加了两个步骤&#xff0c;也即保护现场后的开中断和修改屏蔽字&#xff0c;以及执行中断服务后的关中断 屏蔽字是为了解决中断是否被中断中断的优先级问题 单重中断多重中断中断…

关于redux的一点记录

关于redux的一点记录 文字记录 state进入provide&#xff0c;也就进入组件树state 被mapStateToProps转换了&#xff0c;然后mapDispathToProps也转换了用dispatch实现的一些action再用connect把组合的props传入container使用 connect 并通过 mapDispatchToProps 映射 action…

【超详细】Linux开发环境搭建指南 | Ubuntu

文章目录 虚拟机安装对比Virtual Box 下载ubuntu 操作系统下载Virtual Box 安装安装ubuntu设置中文语言共享文件夹设置添加输入法安装步骤&#xff0c;参考官方教程 安装 vscode解决主机不能通过ssh连接宿主机网络连接几种网络连接区别主机和宿主机相互 ping通 网络代理 虚拟机…

项目实战-多子集循环嵌套 更新时的处理逻辑

项目实战 多子集循环嵌套 更新时的处理逻辑 商品多子集循环嵌套 更新场景时的处理逻辑 场景背景&#xff1a;业务中&#xff0c;套餐下面有多个商品&#xff0c;每个商-品又有多个sku。目前分为套餐表、商品表、sku表&#xff0c;现在更新套餐时 商品和sku都有可能出现增删改的…

利用 git hooks 实现一个 github workflow 文件的快速生成

Git hooks 是强大的脚本&#xff0c;它们在 Git 仓库中特定事件发生时自动触发。通过巧妙地使用这些钩子&#xff0c;你可以大大提高工作效率&#xff0c;确保代码质量&#xff0c;并自动化许多重复性任务。让我们深入探讨一下你可以用 Git hooks 做些什么。 自动化分支管理 …

07:【江科大stm32】:编码器通过定时器测速

编码器通过定时器测速 编码器的转动方向不同&#xff0c;则输出波形的相位也不同。如下图所示&#xff1a; 编码器标准库的编程接口&#xff1a; ①Encoder.c文件的代码如下&#xff1a; #include "stm32f10x.h" // Device header//使用PA6&…

SQL中的不等于

今天碰到一个Oracle不等于的问题&#xff0c;最后搜索了一下&#xff0c;发现下面资料&#xff0c;拿来跟大家分享一下 关于Oracle中的不等于号&#xff1a; 在Oracle中&#xff0c; <> ! ~ ^ 都是不等于号的意思。都可以使用。 但是奇怪是的&#xff0c; 我想拿出p…

布隆过滤器详解

布隆过滤器是什么? 布隆过滤器&#xff08;Bloom Filter&#xff09;是一种空间效率高的概率数据结构&#xff0c;主要用于测试一个元素是否在一个集合中。它的特点是可以快速判断某个元素是否在集合中&#xff0c;但可能会出现误判&#xff0c;即某个元素被判断为在集合中&a…

Android 14(API 级别 34)中,DexClassLoader 不再支持从可写文件加载 dex/jar 文件件

Android 14&#xff08;API 级别 34&#xff09;中&#xff0c;DexClassLoader 不再支持从可写文件加载 dex/jar 文件。这意味着从Android 14开始&#xff0c;你不能再使用 DexClassLoader 来动态加载位于内部存储中的dex/jar文件&#xff0c;除非这些文件被设置为只读。 解决…

Ansible的脚本:playbook

Ansible的脚本 一、playbook&#xff08;剧本&#xff09; 1、playbook的组成 1.1 tasks&#xff08;任务&#xff09;&#xff1a;每一个tasks就是一个模快 1.2 variables&#xff08;变量&#xff09;&#xff1a;存储和传递数据&#xff0c;可以自定义&#xff0c;也可以…

YeAudio音频工具的介绍和使用

夜雨飘零音频工具 这款Python音频处理工具功能强大&#xff0c;支持读取多种格式的音频文件。它不仅能够对音频进行裁剪、添加混响、添加噪声等多种处理操作&#xff0c;还广泛应用于语音识别、语音合成、声音分类以及声纹识别等多个项目领域。 安装 使用pip安装。 pip ins…

3133. 数组最后一个元素的最小值

3133. 数组最后一个元素的最小值 题目链接&#xff1a;3133. 数组最后一个元素的最小值 代码如下&#xff1a; class Solution { public:long long minEnd(int n, int x) {long long resx;int i0,j0;n--;while(n>>j){//x的第i个比特值是0if((res>>i&1)0){//…