网格简化(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.rhkb.cn/news/75229.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring Cloud】Gateway的配置与使用

文章目录 前言第一步&#xff0c;创建一个springboot工程第二步&#xff0c;添加依赖第三步&#xff0c;编写yml文件第四步&#xff0c;启动主启动类总结 前言 Gateway其实是springcloud 原生的东西&#xff0c;但是我还是想放在这里讲&#xff0c;因为我们使用nacos时&#x…

odoo16 上传/下载 文件接口的实现

突然有个需求说需要编写一个上传pdf 接口 首先需要准备如下 xx.xx模型 module 部分 如下&#xff1a; attachment_count fields.Integer(compute_compute_attachment_count, string附件数量, requiredTrue)def _compute_attachment_count(self):# 附件数量计算attachment_dat…

HCIP中期实验

1、该拓扑为公司网络&#xff0c;其中包括公司总部、公司分部以及公司骨干网&#xff0c;不包含运营商公网部分。 2、设备名称均使用拓扑上名称改名&#xff0c;并且区分大小写。 3、整张拓扑均使用私网地址进行配置。 4、整张网络中&#xff0c;运行OSPF协议或者BGP协议的设备…

常见的数据结构(顺序表、顺序表、链表、栈、队列、二叉树)

线性表&#xff08;Linear List&#xff09;  1.什么是线性表 2.线性表的特点 3.线性表的基本运算 顺序表 1.什么是顺序表 2.时间复杂度&#xff1a; 链表 1.什么是链表 2.单向链表 3. 双向链表 4.ArrayList和LinkedList的使用 栈Stack  1.什么是栈  2.栈的基本方法 队列…

AlexNet卷积神经网络-笔记

AlexNet卷积神经网络-笔记 AlexNet卷积神经网络2012年提出 测试结果为&#xff1a; 通过运行结果可以发现&#xff0c; 在眼疾筛查数据集iChallenge-PM上使用AlexNet&#xff0c;loss能有效下降&#xff0c; 经过5个epoch的训练&#xff0c;在验证集上的准确率可以达到94%左右…

Excel 超牛的格式调整汇总——你还在担心你做出来的表不好看吗

Excel格式调整技巧 绘图逆序绘制条形图设置条形图宽度 条件格式透视表上的条件格式 数字格式千分位逗号数字同时显示 K M 数据分列非重复计数区域透视图新增计算列隐藏行列快捷键其他小技巧 绘图 逆序绘制条形图 设置条形图宽度 条件格式 透视表上的条件格式 条件格式随切片…

vue、uniapp直传阿里云文档

前端实现文件上传到oss&#xff08;阿里云&#xff09;适用于vue、react、uni-app&#xff0c;获取视频第一帧图片 用户获取oss配置信息将文件上传到阿里云&#xff0c;保证了安全性和减轻服务器负担。一般文件资源很多直接上传到服务器会加重服务器负担此时可以选择上传到oss&…

Typescript 枚举类型

枚举是用来表示一组明确的可选值列表 // enum是枚举类型的关键字 //枚举如果不设置值&#xff0c;默认从0开始 enum Direction {Up, // 0 Down, // 1 Left, // 2Right // 3} //如果给第一个值赋值为100&#xff0c;则第二、第三第四个都会在第一个的基础上1 分别是101,102…

MySQL数据备份与还原

一、数据备份 1、使用mysqldump命令备份 mysqldump命令将数据库中的数据备份成一个文本文件。表的结构和表中的数据将存储在生成的文本文件中。 mysqldump命令的工作原理很简单。它先查出需要备份的表的结构&#xff0c;再在文本文件中生成一个CREATE语句。然后&#xff0c;将表…

用友和金蝶:管理软件巨头引领企业转型潮流,新技术开始崭露头角

打造企业帝国的管理软件 在当今企业界&#xff0c;管理软件已经成为提高工作效率、优化业务流程的重要工具。 在众多管理软件中&#xff0c;用友和金蝶凭借其卓越的功能和全面的解决方案成为了众多企业的首选。 用友和金蝶的管理软件是国内知名企业管理软件&#xff0c;广泛应…

为什么大多数团队推行自动化测试最后却不了了之?

随着软件行业的快速发展&#xff0c;接口测试用例在软件开发中扮演着越来越重要的角色。自动化测试作为软件测试的一个重要分支&#xff0c;一般可以提高测试效率和质量&#xff0c;节约测试成本和时间&#xff0c;但是在实际推行过程中&#xff0c;大多数团队最终却难以持续实…

vue3+uniapp自定义tabbar

首先把tabbar中的元素写在一个list中用v-for进行渲染 用一个interface进行定义接口&#xff0c;这样别人在review你的代码就可以清晰知道你的tabbar包含什么元素。 利用typescript特性进行类型定义&#xff0c;可以省去很多麻烦 import { reactive } from "vue" imp…

CentOS 项目发出一篇奇怪的博文

导读最近&#xff0c;在红帽限制其 RHEL 源代码的访问之后&#xff0c;整个社区围绕这件事发生了很多事情。 CentOS 项目发出一篇奇怪的博文 周五&#xff0c;CentOS 项目董事会发出了一篇模糊不清的简短博文&#xff0c;文中称&#xff0c;“发展社区并让人们更容易做出贡献…

SpringBoot搭建WebSocket初始化

1.java后端的maven添加websocket依赖 <!-- websocket依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>2.实例化ServerEndpointExport…

【C语言】初阶结构体

&#x1f388;个人主页&#xff1a;库库的里昂 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;C语言初阶 ✨其他专栏&#xff1a;代码小游戏 &#x1f91d;希望作者的文章能对你有所帮助&#xff0c;有不足的地方请在评论…

敷尔佳IPO首日,仅8名研发人员,“医用面膜第一股“是智商税?

“医美面膜第一股“来了。 今日(8月1日)&#xff0c;哈尔滨敷尔佳科技发展有限公司(下称“敷尔佳”&#xff0c;301371SZ)正式在深交所挂牌上市。 敷尔佳此次IPO募资净额为18.97亿元&#xff0c;开盘价为80.00元/股&#xff0c;发行价55.68元/股&#xff1b;开盘即涨43.67%。…

caj文件怎么转换成pdf?了解一下这种方法

caj文件怎么转换成pdf&#xff1f;如果你曾经遇到过需要将CAJ文件转换成PDF格式的情况&#xff0c;那么你一定知道这是一件麻烦的事情。幸运的是&#xff0c;现在有许多软件和工具可以帮助你完成这项任务。下面就给大家介绍一款使用工具。 【迅捷PDF转换器】是一款功能强大的工…

⛳ String 字符串的存储原理及常用方法

目录 ⛳ String 字符串的存储原理及常用方法&#x1f3ed; 一&#xff0c;String 对象介绍&#x1f69c;二&#xff0c;String 的内存结构&#x1f4e2; 2.1&#xff0c;创建字符串&#x1f389; 创建字符串的情况&#xff1a;空值创建&#xff1a;非空值创建&#xff1a; Stri…

SpringBoot + Docker 实现一次构建到处运行

一、容器化部署的好处 Docker 作为一种新兴的虚拟化方式&#xff0c;它可以更高效的利用系统资源&#xff0c;不需要进行硬件虚拟以及运行完整操作系统等额外开销。 传统的虚拟机技术启动应用服务往往需要数分钟&#xff0c;而 Docker 容器应用&#xff0c;由于直接运行宿主内…

Linux系统jenkins+newman+postman持续集成环境搭建

1、首先安装nodejs 下载nodejs压缩包&#xff0c;下载地址&#xff1a;nodejs官网下载 建议不用下载最新的&#xff0c;我这里用的是推荐的v12.18版本 下载和解压命令 wget https://nodejs.org/dist/v12.18.3/node-v12.18.3-linux-x64.tar.xz解压安装包&#xff08;记得没有z&…