网格简化(QEM)学习笔记

文章目录

  • 网格简化(QEM)
    • 1 概述与原理
      • 1.1 网格简化的应用
      • 1.2 常见的简化操作
      • 1.3 二次误差度量
    • 2 算法流程
      • 2.1 逐步分析
    • 3 Python代码实现
      • 3.1 测试结果
    • 4 总结
    • 参考

网格简化(QEM)

1 概述与原理

网格简化,通过减少复杂网格数据的顶点、边和面的数量简化模型的表达,在图形学领域,这种技术也叫做Level of details(LOD,多层次细节)。

1.1 网格简化的应用

  • 多分辨率渲染:对于投影尺寸较小(远距离显示)的模型,可以渲染它的简化版本替代原本丰富细节的高复杂度网格,提高渲染效率。
  • 代理仿真:在简化模型上进行仿真,然后通过插值方法得到原本复杂网格的近似仿真结果,提高仿真效率。 [ 1 ] ^{[1]} [1]

1.2 常见的简化操作

  • Vertex Decimation(顶点抽取)

    选择一个顶点进行删除,移除该顶点相邻的面,然后对产生的孔洞重新三角化。

  • Vertex Clustering(顶点聚类)

    image-20230730150803895

    划分原始网格的包围盒成一个grid,将每个cell中的顶点聚类成一个,然后依据聚类后得到的顶点更新网格的面。

  • Edge Contraction(边收缩)

    image-20230730151429110

    ( v 1 , v 2 ) → v ‾ (v_1,v_2)\rightarrow{\overline{v}} (v1,v2)v,将一条边收缩为一个点,删除退化的面(上图中阴影所示)。

  • Pair Contraction(点对收缩)

    image-20230730162827401作为边收缩的推广,如果点对 ( v 1 , v 2 ) (v_1,v_2) (v1,v2)是一条边,那么等同于边收缩;如果点对 ( v 1 , v 2 ) (v_1,v_2) (v1,v2)不是一条边,那么对该点对进行收缩会使原本不相连的部分连接到一起。

1.3 二次误差度量

为了保证收缩后的顶点与原始网格之间的局部距离不要太远,我们选择一种基于二次距离度量的方式寻找最优的收缩点。

根据二次距离寻找最优收缩点

image-20230730174452604

此处公式推导请移步至网格简化 QEM 方法详解,文中讲得十分清晰。

考虑一次边收缩。对于两个点 v 1 , v 2 v_1, v_2 v1,v2 ,收缩成一个点 v ˉ \bar{v} vˉ 。定义 plane ( v i ) \left(v_i\right) (vi) 表示 v i v_i vi 对应的那些原始三角面,则我们的优化目标是
v ˉ = arg ⁡ min ⁡ v ∑ p ∈  plane  ( v 1 ) ∪  plane  ( v 2 ) distance ⁡ ( v , p ) 2 \bar{v}=\underset{v}{\arg \min } \sum_{p \in \text { plane }\left(v_1\right) \cup \text { plane }\left(v_2\right)} \operatorname{distance}(v, p)^2 vˉ=vargminp plane (v1) plane (v2)distance(v,p)2
下面一步步化简。令平面 p p p 的表达式为 a x + b y + c z + d = 0 a x+b y+c z+d=0 ax+by+cz+d=0 ,其中 a 2 + b 2 + c 2 = 1 a^2+b^2+c^2=1 a2+b2+c2=1 。 记 v = [ x , y , z , 1 ] T , p = [ a , b , c , d ] T v=[x, y, z, 1]^T, p=[a, b, c, d]^T v=[x,y,z,1]T,p=[a,b,c,d]T ,可得
distance ⁡ ( v , p ) 2 = ( v T p ) 2 = v T p p T v = v T K p v \operatorname{distance}(v, p)^2=\left(v^T p\right)^2=v^T p p^T v=v^T K_p v distance(v,p)2=(vTp)2=vTppTv=vTKpv
其中 K p = p p T K_p=p p^T Kp=ppT ,则原式简化为
v ˉ = arg ⁡ min ⁡ v   v T ( ∑ p ∈  plane  ( v 1 ) ∪ p l a n e ( v 2 ) K p ) v \bar{v}=\underset{v}{\arg \min }\space v^T\left(\sum_{p \in \text { plane }\left(v_1\right) \cup p l a n e\left(v_2\right)} K_p\right) v vˉ=vargmin vT p plane (v1)plane(v2)Kp v
此处取约等于
v ˉ ≈ arg ⁡ min ⁡ v   v T ( ∑ p ∈ plane ⁡ ( v 1 ) K p + ∑ p ∈ plane ⁡ ( v 2 ) K p ) v \bar{v} \approx \underset{v}{\arg \min }\space v^T\left(\sum_{p \in \operatorname{plane}\left(v_1\right)} K_p+\sum_{p \in \operatorname{plane}\left(v_2\right)} K_p\right) v vˉvargmin vT pplane(v1)Kp+pplane(v2)Kp v
Q i = ∑ p ∈  plane  ( v i ) K p Q_i=\sum_{p \in \text { plane }\left(v_i\right)} K_p Qi=p plane (vi)Kp ,则有
v ˉ = arg ⁡ min ⁡ v   v T ( Q 1 + Q 2 ) v \bar{v}=\underset{v}{\arg \min }\space v^T\left(Q_1+Q_2\right) v vˉ=vargmin vT(Q1+Q2)v
初始化时,将 plane ⁡ ( v ) \operatorname{plane}(v) plane(v) 设为点 v \mathrm{v} v 周围的三角形面即可。此时上面的约等号并无大碍,因为一个 三角形面至多重复三次 (三个顶点),不仅不会带来较大的误差,而且简化了计算。
另外, K p K_p Kp 是对称矩阵,故 Q Q Q 也是,所以只需要存储 10 个元素即可。
此时求解 v ˉ \bar{v} vˉ 的坐标变成求解二次函数极值点。 [ 2 ] ^{[2]} [2]

Q = Q 1 + Q 2 Q=Q_1+Q_2 Q=Q1+Q2,通过解如下方程求解 v ˉ \bar{v} vˉ的坐标:
[ q 11 q 12 q 13 q 14 q 12 q 22 q 23 q 24 q 13 q 23 q 33 q 34 0 0 0 1 ] v ˉ = [ 0 0 0 1 ] \left[{\begin{array}{cccc}q_{11}&q_{12}&q_{13}&q_{14}\\q_{12}&q_{22}&q_{23}&q_{24}\\q_{13}&q_{23}&q_{33}&q_{34}\\0&0&0&1\end{array}}\right]\bar{v}=\left[{\begin{array}{c}0\\0\\0\\1\end{array}}\right] q11q12q130q12q22q230q13q23q330q14q24q341 vˉ= 0001
上式中, q 11 q_{11} q11表示 Q Q Q的第一行的第一个元素的值,这里 v ˉ \bar{v} vˉ使用的是齐次坐标。如果上式中左侧矩阵可逆,则
v ˉ = [ q 11 q 12 q 13 q 14 q 12 q 22 q 23 q 24 q 13 q 23 q 33 q 34 0 0 0 1 ] − 1 [ 0 0 0 1 ] \bar{v}=\left[{\begin{array}{cccc}q_{11}&q_{12}&q_{13}&q_{14}\\q_{12}&q_{22}&q_{23}&q_{24}\\q_{13}&q_{23}&q_{33}&q_{34}\\0&0&0&1\end{array}}\right]^{-1}\left[{\begin{array}{c}0\\0\\0\\1\end{array}}\right] vˉ= q11q12q130q12q22q230q13q23q330q14q24q341 1 0001
如果不可逆,则 [ 4 ] ^{[4]} [4]
v = ( 1 − k ) v 1 + k v 2 , where  k ∈ [ 0 , 1 ] v ˉ = arg ⁡ min ⁡ v   v T ( Q 1 + Q 2 ) v v=(1-k)v_1+kv_2,\text{where}\space{k}\in[0,1]\\ \bar{v}=\underset{v}{\arg \min }\space v^T\left(Q_1+Q_2\right) v v=(1k)v1+kv2,where k[0,1]vˉ=vargmin vT(Q1+Q2)v
如果还是不行,就选择端点 v 1 , v 2 v_1,v_2 v1,v2或者中点 v 1 + v 2 2 \frac{v_1+v_2}2 2v1+v2三者中误差( Δ ( v ) = v T Q v \Delta(v)=v^TQv Δ(v)=vTQv)最小的作为 v ˉ \bar{v} vˉ [ 3 ] ^{[3]} [3]

2 算法流程

img

图源自:QEM网格简化 - 简书 (jianshu.com)

2.1 逐步分析

  • 计算所有初始顶点的 Q Q Q矩阵

    令平面 p p p 的表达式为 a x + b y + c z + d = 0 a x+b y+c z+d=0 ax+by+cz+d=0 ,其中 a 2 + b 2 + c 2 = 1 a^2+b^2+c^2=1 a2+b2+c2=1 。记 p = [ a , b , c , d ] T p=[a, b, c, d]^T p=[a,b,c,d]T。由此,我们定义 Q i Q_i Qi(4x4,顶点 v i v_i vi Q Q Q矩阵)如下:
    Q i = ∑ p ∈ p l a n e s ( v i ) p p T Q_i=\sum_{p\in planes(v_i)}pp^T Qi=pplanes(vi)ppT

  • 选择合法点对

    一个顶点对 ( v i , v j ) (v_i,v_j) (vi,vj)是合法点对的条件为:

    • ( v i , v j ) (v_i,v_j) (vi,vj)是一条边;
    • ‖ v i − v j ‖ < t ‖v_i − v_j‖ < t vivj<t t t t为阈值参数。

    以上条件满足其一即可。

  • 计算每个合法点对 ( v i , v j ) (v_i,v_j) (vi,vj)的最小收缩误差 c o s t i j cost_{ij} costij,以及最佳收缩点 v o p t v_{opt} vopt的位置

    首先计算 v o p t v_{opt} vopt对应的 Q o p t Q_{opt} Qopt
    Q o p t = Q i + Q j = [ q 11 q 12 q 13 q 14 q 12 q 22 q 23 q 24 q 13 q 32 q 33 q 34 q 14 q 24 q 34 q 44 ] . Q_{opt}=Q_i+Q_j=\begin{bmatrix}q_{11}&q_{12}&q_{13}&q_{14}\\q_{12}&q_{22}&q_{23}&q_{24}\\q_{13}&q_{32}&q_{33}&q_{34}\\q_{14}&q_{24}&q_{34}&q_{44}\end{bmatrix}. Qopt=Qi+Qj= q11q12q13q14q12q22q32q24q13q23q33q34q14q24q34q44 .
    定义 c o s t i j cost_{ij} costij如下:
    c o s t i j = v T Q o p t v cost_{ij}=v^TQ_{opt}v costij=vTQoptv
    最小化收缩误差,得到 v o p t v_{opt} vopt。具体计算参见上一节[二次误差度量](#1.3 二次误差度量)。

  • 将所有合法点对按其对应的 c o s t i j cost_{ij} costij的顺序放置在一个堆中,最小 c o s t i j cost_{ij} costij对位于顶部

    一般使用小根堆进行排序。

  • 移除最小 c o s t i j cost_{ij} costij对应的点对,收缩 ( v i , v j ) → v o p t (v_i,v_j)\rightarrow{v_{opt}} (vi,vj)vopt,更新所有包含了 v i v_i vi v j v_j vj的合法点对的 c o s t cost cost

    这一步是迭代进行的,结束的标志为达到了设定的简化率或者堆空了 [ 5 ] ^{[5]} [5]

3 Python代码实现

代码实现方面,推荐直接学习该项目:Mesh_simplification_python: An implementation of mesh simplification algorithm using python,其中代码注释很全,条理清晰,值得学习。

3.1 测试结果

输入模型网格(9397 vertices, 18794 faces):

image-20230802000140688

t = 0 ,   r a t i o = 0.5 t=0,\space ratio=0.5 t=0, ratio=0.5(4698 vertices, 9396 faces):

image-20230802000230337

t = 0 ,   r a t i o = 0.1 t=0,\space ratio=0.1 t=0, ratio=0.1(939 vertices, 1878 faces):

image-20230802000546218

4 总结

  • 代码功能优化

    在原论文中还提到了如下两个细节:

    • 保留边界

      对于一些在简化过程中需要保持边界的模型网格,我们在点对收缩时判断点对是否为边界边,如果是,我们可以给该点对cost加权一个较大的惩罚因子,阻止收缩。

    • 防止面片翻转

      直接使用QEM算法进行网格简化,可能会导致一些面片翻转。所以我们需要在计算点对收缩cost时,同时判断点对的每一个相邻面片是否发生了翻转。可采用收缩前后面片法向量的夹角大小进行判断。同时,我们也对其代价进行惩罚。

参考

[1] GAMES102:几何建模与处理
[2] https://zhuanlan.zhihu.com/p/411865616
[3] Michael Garland and Paul S. Heckbert. 1997. Surface simplification using quadric error metrics. In Proceedings of the 24th annual conference on Computer graphics and interactive techniques (SIGGRAPH '97). ACM Press/Addison-Wesley Publishing Co., USA, 209–216. https://doi.org/10.1145/258734.258849
[4] https://www.jianshu.com/p/2bf615c38165
[5] https://github.com/AntonotnaWang/Mesh_simplification_python

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java版工程行业管理系统源码-专业的工程管理软件- 工程项目各模块及其功能点清单

&#xfeff; 工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据…

021 - STM32学习笔记 - Fatfs文件系统(三) - 细化与总结

021 - STM32学习笔记 - Fatfs文件系统&#xff08;三&#xff09; - 细化与总结 上节内容中&#xff0c;初步实现了FatFs文件系统的移植&#xff0c;并且实现了设备的挂载、文件打开/关闭与读写功能&#xff0c;这里对上节遗留的一些问题进行总结&#xff0c;并且继续完善文件…

Mybatis插件

文章目录 1. 如何自定义插件1.1 创建接口Interceptor的实现类1.2 配置拦截器1.3 运行程序 2. 插件原理2.1 解析过程2.2 创建代理对象2.2.1 Executor2.2.2 StatementHandler2.2. 3ParameterHandler2.2.4 ResultSetHandler 2.3 执行流程2.4 多拦截器的执行顺序 3. 1. 如何自定义插…

【Redis】内存数据库Redis进阶(Redis持久化)

目录 分布式缓存 Redis 四大问题Redis 持久化RDB (Redis DataBase)RDB执行时机RDB启动方式——save指令save指令相关配置save指令工作原理save配置自动执行 RDB启动方式——bgsave指令bgsave指令相关配置bgsave指令工作原理 RDB三种启动方式对比RDB特殊启动形式RDB优点与缺点 A…

Git全栈体系(三)

第六章 GitHub 操作 一、创建远程仓库 二、远程仓库操作 命令名称作用git remote -v查看当前所有远程地址别名git remote add 别名 远程地址起别名git push 别名 分支推送本地分支上的内容到远程仓库git clone 远程地址将远程仓库的内容克隆到本地git pull 远程库地址别名 远…

基于SpringCloud+Vue的分布式架构网上商城系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

Spring入门-技术简介、IOC技术、Bean、DI

前言 Spring是一个开源的项目&#xff0c;并不是单单的一个技术&#xff0c;发展至今已形成一种开发生态圈。也就是说我们可以完全使用Spring技术完成整个项目的构建、设计与开发。Spring是一个基于IOC和AOP的架构多层j2ee系统的架构。 SpringFramework&#xff1a;Spring框架…

06-向量的更多术语和表示法

向量 引入的概念&#xff1a;向量就是一组有序的数字, 我们在理解它的时候&#xff0c; 可以把它理解成是一个有效的线段&#xff0c;也可以把它理解成是空间中的一个点&#xff0c;那么与之相对应的一个数字&#xff0c;也就是我们在初等数学中学的一个一个数&#xff0c;我们…

GRNN神经网络原理与matlab实现

1案例背景 1.1GRNN神经网络概述 广义回归神经网络(GRNN Generalized Regression Neural Network&#xff09;是美国学者 Don-ald F. Specht在1991年提出的,它是径向基神经网络的一种。GRNN具有很强的非线性映射能力和柔性网络结构以及高度的容错性和鲁棒性,适用于解决非线性问…

关于综合能源智慧管理系统的架构及模式规划的研究

安科瑞 华楠 摘 要&#xff1a;探讨了国内外能源互联网的研究发展&#xff0c;分析了有关综合智慧能源管理系统的定位&#xff0c;以及系统的主要特点&#xff0c;研究了综合智慧能源管理系统的构架以及模式规划。 关键词&#xff1a;综合能源&#xff1b;智慧管理系统&#…

如何在不使用脚本和插件的情况下手动删除 3Ds Max 中的病毒?

如何加快3D项目的渲染速度&#xff1f; 3D项目渲染慢、渲染卡顿、渲染崩溃&#xff0c;本地硬件配置不够&#xff0c;想要加速渲染&#xff0c;在不增加额外的硬件成本投入的情况下&#xff0c;最好的解决方式是使用渲云云渲染&#xff0c;在云端批量渲染&#xff0c;批量出结…

【PHP代码审计】ctfshow web入门 php特性 93-104

ctfshow web入门 php特性 93-104 web 93web 94web 95web 96web 97web 98web 99web 100web 101web 102web 103web 104 web 93 这段PHP代码是一个简单的源码审计例子&#xff0c;让我们逐步分析它&#xff1a; include("flag.php");: 这行代码将flag.php文件包含进来。…

从零开始学python(十二)如何成为一名优秀的爬虫工程师

前言 回顾之前讲述了python语法编程 必修入门基础和网络编程&#xff0c;多线程/多进程/协程等方面的内容&#xff0c;后续讲到了数据库编程篇MySQL&#xff0c;Redis&#xff0c;MongoDB篇&#xff0c;和机器学习&#xff0c;全栈开发&#xff0c;数据分析前面没看的也不用往…

SSL原理详解

SSL协议结构&#xff1a; SSL协议分为两层&#xff0c;下层为SSL记录协议&#xff0c;上层为SSL握手协议、SSL密码变化协议和SSL警告协议。 1.下层为SSL记录协议&#xff0c;主要作用是为高层协议提供基本的安全服务 建立在可靠的传输之上&#xff0c;负责对上层的数据进行分块…

DeepVO 论文阅读

论文信息 题目&#xff1a;DeepVO Towards End-to-End Visual Odometry with Deep Recurrent Convolutional Neural Networks 作者&#xff1a;Sen Wang, Ronald Clark, Hongkai Wen and Niki Trigoni 代码地址&#xff1a;http://senwang.gitlab.io/DeepVO/ (原作者并没有开源…

【C++】从0到1讲继承|复杂的菱形继承

个人主页&#xff1a;&#x1f35d;在肯德基吃麻辣烫 我的gitee&#xff1a;gitee仓库 分享一句喜欢的话&#xff1a;热烈的火焰&#xff0c;冰封在最沉默的火山深处。 前言 本文主要讲述的是继承的概念&#xff0c;以及基类和派生类和衍生出的各种东西&#xff0c;还有多继承…

前端代码注释率

nodejs差代码注释率 /*** author duan* source https://editor.csdn.net/md/?not_checkout1&spm1011.2124.3001.6192* date 2023-7-7* * 统计指定目录下代码行数及注释率* * 用法: node count.js <路径> [后缀名]...* 后缀名不填的话默认为统计 .js 和 .ts 文件* *…

Jenkins通过OpenSSH发布WinServer2016

上一篇文章> Jenkins集成SonarQube代码质量检测 一、实验环境 jenkins环境 jenkins入门与安装 容器为docker 主机IP系统版本jenkins10.10.10.10rhel7.5 二、OpenSSH安装 1、下载 官网地址&#xff1a;https://learn.microsoft.com/zh-cn/windows-server/administration/op…

MaxPatrol SIEM 增加了一套检测供应链攻击的专业技术

我们为 MaxPatrol SIEM 信息安全事件监控系统增加了一套新的专业技术。 该产品可帮助企业防范与供应链攻击相关的威胁。 此类攻击正成为攻击者的首要目标&#xff1a;它们以软件开发商和供应商为目标&#xff0c;网络犯罪分子通过他们的产品进入最终目标的基础设施。 因此&a…

Android Studio 启用设备远程调试配置完整步聚

启用手机设置->开发者选项-无线调试,然后选择允许 已启用后无线调试变成绿色 ,点击无线调试进入详情页面 点击Android Studio的Device Manager 下的WIFI图标 会弹出下图窗口 打开手机的开发者选项中的WIFI调试(无线调试)下的使用二维码配对设备进行扫描. 设备配对成功后手机…
最新文章