论文阅读《GlueStick: Robust Image Matching by Sticking Points and Lines Together》

news2024/10/6 0:28:17

论文地址:https://arxiv.org/abs/2304.02008
源码地址:https://github.com/cvg/GlueStick


概述

  针对视角变化时在闭塞、无纹理、重复纹理区域的线段匹配难的问题,本文提出一种新的匹配范式(GlueStick),该方法基于深度图神经网络将点、线的描述符统一到一个框架中,利用点之间的信息将来自匹配图像之间的线进行粘合,提高了模型的联合匹配效率,表明了在单一框架中使用两种特征的互补性能大幅度提升性能。
本文的主要贡献如下:

  • 使用数据驱动的方法代替启发式几何策略进行线匹配,在统一的框架中联合表征点与线。
  • 提供了一种新的架构,充分挖掘图像内特征之间的局部关联信息。
  • 实验结果表明,所提出的方法比之前最先进的方法有较大提升。

模型架构

在这里插入图片描述
  受启发于:在匹配过程中,每个特征都可以利用其周围的特征信息来提高匹配性能,如线段可以利用周围的点来增强自己的表征能力,或者反之亦然。此外,网络在训练的过程中可以自动学习到对匹配任务有用的周围的点或者线。模型的主要框架如图2所示,主要包含三个部分:

  1. Front-End:使用常用的特征检测器来提取点、线与它们的描述符,然后将其编码成一个统一的线框。
  2. GNN:使用图神经网络来对输入特征的外观与空间信息进行编码,充分挖掘特征点之间的内部关联,输入为增强后带有更多信息的匹配特征描述符。
  3. Dual-Softmax:使用两个独立的softmax层来分别对点和线进行匹配,确定最后的匹配对应关系。

From Points and Lines to Wireframes

   GNN的输入为特征点的位置与描述符、表示线段链接关系的连接矩阵。第一步是建立这些连接关系并构建线框图。使用SuperPoint来预测关键点与稠密的描述符图,并通过LSD检测器检测线段,并将线段两端附近的关键点删除,避免特征冗余。
  LSD检测的线段的为断开的独立线段,为了给模型更多结构化信息,并鼓励网络按照线段的连接性进行推理,使用阈值 d d d 来将相邻端点进行合并,此过程将非结构化的线转换成了互联的线框,将每个关键点与线段端点表示为线框中的一个节点,每个节点有不同的连接性:0表示孤立节点,2表示角点。继而在节点周围使用SP生成的特征点插入,用来增强线段的表征能力,这种方式会改变线段端点的位置,而不会改变线段的数量,对于有高精度要求的下游任务,使用端点的原始位置来保证原始检测器的亚像素精度。

Attention-based Graph Neural Network (GNN)

  模型的关键部分是GNN,该模块可以将视觉和空间信息编码为一组表征能力丰富的特征描述符,通过特征描述符的相似性来建立最后的匹配关系。在网络内部,每个节点(关键点、线段端点)都与一个基于视觉外观和位置信息的描述符相关联。
在这里插入图片描述

  不妨设 A 与 B 为一对图像,对于每幅图像,网络的输入为:特征点集合 p \mathbf{p} p 的坐标 ( x p , y p ) (x_p, y_p) (xp,yp),置信度 s p s_p sp 和视觉特征描述符 d v i s ∈ R D \mathbf{d}^{vis}\in \mathbb{R}^D dvisRD; 线集合 l \mathbf{l} l 的端点 ( x p , y p ) , ( x p ′ , y p ′ ) (x_p, y_p), (x_p^\prime, y_p^\prime) (xp,yp),(xp,yp) 与线段分数 s l s_l sl。线段分数可以为先检测器返回的任何值,也可以用线段的长度来表示。节点置信度 s p s_p sp 由关键点检测器计算而来,如果是线段端点则等于 s l s_l sl
Positional and Directional Encoding.
  首先对每个特征点的空间信息进行编码,使用MLP来学习位置编码 P E p PE^p PEp P E e PE^e PEe, 对于每个点生成空间描述符 d p \mathbf{d}^p dp,并未每个从该节点发出的线段生成描述符 d e \mathbf{d}^e de。如具有3个连接点的节点将被分配一个 d p \mathbf{d}^p dp 与 3 个 d e \mathbf{d}^e de。边位置编码还需要额外的信息,即到线段另一端的偏移量,从而能够范围线段的角度与长度。

d p = PE ⁡ p ( [ x p , y p , s p ] ⊤ ) d e = PE ⁡ e ( [ x p , y p , x p ′ − x p , y p ′ − y p , s l ] ⊤ ) (1) \begin{aligned} \mathbf{d}^{p} & =\operatorname{PE}^{p}\left(\left[x_{p}, y_{p}, s_{p}\right]^{\top}\right) \\ \mathbf{d}^{e} & =\operatorname{PE}^{e}\left(\left[x_{p}, y_{p}, x_{p}^{\prime}-x_{p}, y_{p}^{\prime}-y_{p}, s_{l}\right]^{\top}\right) \end{aligned} \tag{1} dpde=PEp([xp,yp,sp])=PEe([xp,yp,xpxp,ypyp,sl])(1)
其中 d p \mathbf{d}^p dp 用于初始化节点信息,而 d e \mathbf{d}^e de 用于线消息传递。
Network Architecture.
   GNN 包含三种无向边:self-attention edges( ε s e l f \varepsilon_{self} εself) 连接同一副图像之间的节点; line edges( ε l i n e \varepsilon_{line} εline) 将同一条线的端点连接; cross attention edges ( ε c r o s s \varepsilon_{cross} εcross) 连接不同图像之间的节点;
  每个节点 i i i 的特征向量使用空间与视觉信息来初始化: 0 x i = d i p + d i v i s {}^0x_i = \mathbf{d}^p_i + \mathbf{d}^{vis}_i 0xi=dip+divis,然后通过 L L L 次 Self,Line与 Cross layers的更新迭代,节点的描述符被不断丰富与精细化,最后将每个节点的特征进行线性投影得到输出层特征。

Self and Cross Layers.
   ε s e l f \varepsilon_{self} εself ε c r o s s \varepsilon_{cross} εcross 的定义是类似的。第 m m m 层的特征更新过程如下:
( m + 1 ) x i = ( m ) x i + ψ m ( [ ( m ) x i ∥ a m ( ( m ) x i ; E ) ] ) , (2) { }^{(m+1)} \mathbf{x}_{i}={ }^{(m)} \mathbf{x}_{i}+\psi_{m}\left(\left[{ }^{(m)} \mathbf{x}_{i} \| a_{m}\left({ }^{(m)} \mathbf{x}_{i} ; \mathcal{E}\right)\right]\right),\tag{2} (m+1)xi=(m)xi+ψm([(m)xiam((m)xi;E)]),(2)
其中 ∣ ∣ || ∣∣ 代表拼接, 函数 ψ m \psi_{m} ψm 使用 MLP来拟合。 a m ( ( m ) x i E ) a_{m}\left({ }^{(m)} \mathbf{x}_{i}\mathcal{E}\right) am((m)xiE) 为多头注意力机制,其中:
a m ( x i ; E ) = ∑ j : ( i , j ) ∈ E softmax ⁡ j ( q i ⊤ k j D ) v j , (3) a_{m}\left(\mathbf{x}_{i} ; \mathcal{E}\right)=\sum_{j:(i, j) \in \mathcal{E}} \operatorname{softmax}_{j}\left(\frac{\mathbf{q}_{i}^{\top} \mathbf{k}_{j}}{\sqrt{D}}\right) \mathbf{v}_{j},\tag{3} am(xi;E)=j:(i,j)Esoftmaxj(D qikj)vj,(3)
其中 q i \mathbf{q}_{i} qi k j \mathbf{k}_{j} kj 是由节点特征 x i x_i xi x j x_j xj 生成的,在自注意力层中, k j k_j kj v j v_j vj 来自同一图像,而在交叉注意力中来自不同图像。自注意力允许网络利用整个图像的上下文,并解决重复结构下的模糊匹配问题。交叉注意力将相应特征在描述符空间中的距离拉近,并可以在另一幅图像中搜索类似的节点结构,以充分利用空间信息。

Line Message Passing.
  本文提出一种新的 Line Message Passing(LMP) 的方法在线 ε l i n e \varepsilon_{line} εline 之间传播信息,通过在 wireframe 结构中连接 line segments,利用第 i i i 个节点与邻域节点 N i N_i Ni 的连接关系在匹配图像中寻找类似的连接关系。基于 m m m 层LMP来不断更新聚合来自 两个端点{ }^{(m)} \mathbf{x}_{i} 与 ( m ) x j { }^{(m)} \mathbf{x}_{j} (m)xj本身的信息与相应的位置编码信息 d j e \mathbf{d}^e_j dje
( m + 1 ) x i = ( m ) x i + ∑ j ∈ N i ϕ m ( [ ( m ) x i ∥ ∣ ( m ) x j ∥ d j e ] ) ∣ N i ∣ , (2) { }^{(m+1)} \mathbf{x}_{i}={ }^{(m)} \mathbf{x}_{i}+\sum_{j \in \mathcal{N}_{i}} \frac{\phi_{m}\left(\left[{ }^{(m)} \mathbf{x}_{i}\left\|\left.\right|^{(m)} \mathbf{x}_{j}\right\| \mathbf{d}_{j}^{e}\right]\right)}{\left|\mathcal{N}_{i}\right|},\tag{2} (m+1)xi=(m)xi+jNiNiϕm([(m)xi (m)xj dje]),(2)
其中 ϕ m \phi_{m} ϕm 由MLP来实现, ∣ N i ∣ |\mathcal{N}_{i}| Ni 为节点 i i i 的邻域节点之和,此处使用邻域节点的信息的均值来更新当前节点信息,也可以对邻域节点增加注意力机制,从经验数据上看书这样会增加模型的计算量,而对性能的提升不大。

Dual-Softmax for Points and Lines

  最近一些工作表明,dual-softmax相较于Sinkhorm 算法有更好的性能,为此本文采用独立的dual-softmax处理点与线的匹配。此外,再一次使用GNN来对所有的节点(点与线)进行一次匹配:对于A图中的所有节点 f i A ∈ R D \mathbf{f}_i^A\in \mathbb{R}^D fiARD f j B ∈ R D \mathbf{f}_j^B\in \mathbb{R}^D fjBRD,每个节点的分配矩阵 S p \mathbf{S}^p Sp
S i j p = ( f i A ) ⊤ f j B . (5) \mathbf{S}_{i j}^{p}=\left(\mathbf{f}_{i}^{A}\right)^{\top} \mathbf{f}_{j}^{B} .\tag{5} Sijp=(fiA)fjB.(5)
使用可学习的参数来对分配矩阵增加 dustbin 的行与列(参考super glue)来表示非匹配点,然后对所有行和所有列进行softmax:
S final  p = softmax ⁡ r o w ( S p ) ⊙ softmax ⁡ c o l ( S p ) . (6) \mathbf{S}_{\text {final }}^{p}=\sqrt{\operatorname{softmax}_{\mathrm{row}}\left(\mathbf{S}^{p}\right) \odot \operatorname{softmax}_{\mathrm{col}}\left(\mathbf{S}^{p}\right)} .\tag{6} Sfinal p=softmaxrow(Sp)softmaxcol(Sp) .(6)
其中 ⊙ \odot 为逐元素相乘, 选择两个节点之间的匹配分数高于阈值 η \eta η 的视为匹配点。线的匹配过程是类似的,使用两个端点来表示一条线段 f s ∈ R D \mathbf{f}_{s}\in\mathbb{R}^D fsRD f e ∈ R D \mathbf{f}_{e}\in\mathbb{R}^D feRD, 为了消除端点顺序对匹配的影响,选择分配矩阵中得分比较大的一项作为最后的选择值,如图4所示:
在这里插入图片描述
S i j l = max ⁡ ( ( f s A ) ⊤ f s B + ( f e A ) ⊤ f e B , ( f s A ) ⊤ f e B + ( f e A ) ⊤ f s B ) . (7) \begin{array}{r} \mathbf{S}_{i j}^{l}=\max \left(\left(\mathbf{f}_{s}^{A}\right)^{\top} \mathbf{f}_{s}^{B}+\left(\mathbf{f}_{e}^{A}\right)^{\top} \mathbf{f}_{e}^{B},\right. \left.\left(\mathbf{f}_{s}^{A}\right)^{\top} \mathbf{f}_{e}^{B}+\left(\mathbf{f}_{e}^{A}\right)^{\top} \mathbf{f}_{s}^{B}\right) . \end{array}\tag{7} Sijl=max((fsA)fsB+(feA)feB,(fsA)feB+(feA)fsB).(7)
最后通过公式6的dual-softmax来得到最后的分配矩阵。

Ground Truth Generation

  为了得到点的 Ground True(GT) 值 M p \mathcal{M}^p Mp,利用相机参数与深度图,将关键点从一幅图像中warp到另外一幅图像中,如果重投影点落在现有关键点的一个小邻域内,则认为两个关键点在空间中是接近的,则认为他们是匹配的。

  线段匹配的一大挑战就是对一些碎片化、和部分遮挡的的线段生成高质量的标签数据。不妨设图像 A A A B B B 分别包含 M M M N N N 条线段,表示为 A : = { 1 , . . . , M } \mathcal{A}:=\{1, ...,M\} A:={1,...,M} B : = { 1 , . . . , N } \mathcal{B}:=\{1, ...,N\} B:={1,...,N}, 则匹配线段表示为 M l = { ( i , j ) ⊂ A × B } \mathcal{M}^l=\{(i, j)\subset\mathcal{A}\times \mathcal{B}\} Ml={(i,j)A×B},对于图 A A A 中的每条线段 I i A \mathbf{I}_i^A IiA,从线段中采样 K K K 个点 [ x i , 1 A , . . . , x i , K A ] [\mathbf{x}_{i,1}^A, ..., \mathbf{x}_{i,K}^A] [xi,1A,...,xi,KA]。如果这个点没有深度值或者重投影到B图时没有深度值,则将该点剔除。同时,这些点应该不属于遮挡区域,使用图 A 中的点warp到图B,然后计算深度值偏差度,如果大于阈值则认为该点是遮挡点:
 Occluded  = ∣ d ( X i ) − d B ∣ d B > T occlusion  , (8) \text { Occluded }=\frac{\left|d\left(\mathbf{X}_{i}\right)-d^{B}\right|}{d^{B}}>T_{\text {occlusion }},\tag{8}  Occluded =dB d(Xi)dB >Tocclusion ,(8)
  然后生成一个邻近矩阵来统计A图中,第 i i i 条线段有多少个点能成功warp到B图中 j j j 条线段附近:
C i , j B = ∑ k = 1 K 1 ( valid ⁡ ( x i , k B ) ∧ d ⊥ ( x i , k B , l j B ) < T d i s t ) (9) \mathbf{C}_{i, j}^{B}=\sum_{k=1}^{K} \mathbb{1}\left(\operatorname{valid}\left(\mathbf{x}_{i, k}^{B}\right) \wedge d_{\perp}\left(\mathbf{x}_{i, k}^{B}, \mathbf{l}_{j}^{B}\right)<T_{\mathrm{dist}}\right)\tag{9} Ci,jB=k=1K1(valid(xi,kB)d(xi,kB,ljB)<Tdist)(9)

其中 1 ( ⋅ ) 1(\cdot) 1() 为指示函数, d ⊥ ( ⋅ , ⋅ ) d_{\perp}(\cdot,\cdot) d(,) 为垂直与点线距离。 T d i s t T_{\mathrm{dist}} Tdist 为像素为单位的距离阈值,用于控制 GT 的严格程度, C A C^A CA 的定义与 C B C^B CB 类似,为此定义一个具有最小重叠阈值 T o v e r l T_{overl} Toverl 的成本矩阵:
C i , j = { ∞ ,  if  C i , j A < T overl  ∨ C j , i B < T overl  − C i , j A C j , i B ,  otherwise.  (10) \mathbf{C}_{i, j}=\left\{\begin{array}{ll} \infty, & \text { if } \mathbf{C}_{i, j}^{A}<T_{\text {overl }} \vee \mathbf{C}_{j, i}^{B}<T_{\text {overl }} \\ -\mathbf{C}_{i, j}^{A} \mathbf{C}_{j, i}^{B},& \text { otherwise. } \end{array}\right.\tag{10} Ci,j={,Ci,jACj,iB, if Ci,jA<Toverl Cj,iB<Toverl  otherwise. (10)
最后使用匈牙利算法来求解该分配问题,分配结果 ( i , j ) ∈ M l (i, j)\in \mathbb{M}^l (i,j)Ml 为匹配特征,未被匹配的特征都被标记为未匹配状态。


损失函数

一般使用带有 hard negative mining 的 triplet-ranking-loss作为损失函数,而线段经常出现重复结构,这会导致不稳定的 hard negative,因此使用点与线的分配的负对数似然来作为损失函数:
L = NLL ⁡ ( S final  p , M p ) + NLL ⁡ ( S final  l , M l ) 2 (11) \mathcal{L}=\frac{\operatorname{NLL}\left(\mathbf{S}_{\text {final }}^{p}, \mathcal{M}^{p}\right)+\operatorname{NLL}\left(\mathbf{S}_{\text {final }}^{l}, \mathcal{M}^{l}\right)}{2} \tag{11} L=2NLL(Sfinal p,Mp)+NLL(Sfinal l,Ml)(11)

NLL ⁡ ( A , M ) = − ∑ ( i , j ) ∈ M log ⁡ A i , j − ∑ i ∈ I log ⁡ A i , N + 1 − ∑ j ∈ J log ⁡ A M + 1 , j (12) \begin{aligned} \operatorname{NLL}(\mathbf{A}, \mathcal{M})= & -\sum_{(i, j) \in \mathcal{M}} \log \mathbf{A}_{i, j} -\sum_{i \in \mathcal{I}} \log \mathbf{A}_{i, N+1}-\sum_{j \in \mathcal{J}} \log \mathbf{A}_{M+1, j} \end{aligned}\tag{12} NLL(A,M)=(i,j)MlogAi,jiIlogAi,N+1jJlogAM+1,j(12)


实验结果

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL性能优化(三)事务与锁详解

文章目录什么是数据库事务&#xff1f;事务的四大特性&#xff1a;ACID事务的开启与结束案例表结构与数据案例事务并发的三大问题&#xff1a;脏读&#xff08;一个事务读取到了其他事务未提交的数据&#xff09;不可重复读&#xff08;一个事务读取到其他事务已提交的数据造成…

Qt在安卓手机输出‘hello,world‘

我也想实现这样的功能。 最开始的参考文章&#xff1a; (2条消息) Qt android 开发环境搭建_逝水流年丶轻染尘的博客-CSDN博客 方案1&#xff1a;(失败) 我之前已经下载过 Qt5.14.2了&#xff0c;所以我想直接添加组件 中间过程参考&#xff1a; (2条消息) Qt更新组件出现&…

敏捷开发模式下如何用 PingCode 这类工具迭代管理

迭代&#xff08;Sprint&#xff09;是 Scrum 敏捷开发框架的核心&#xff0c;正确的迭代可以帮助敏捷团队提高工作交付速度。Scrum 团队以完成迭代待办列表为工作目标&#xff0c;并在迭代结束时交付一定的产品增量。PingCode 以产品待办列表作为迭代管理的核心&#xff0c;因…

java并发编程之美第二章读书笔记

并发编程的其他基础知识 什么是多线程的并发编程 并发: 同一时间段内多个任务同时都在执行,且执行都没有执行结束,强调的是在一个时间段内同时执行,而一个时间段由多个时间积累而成的,所以并发的多个任务在单位时间内并不一定同时执行 并行: 单位时间内多个任务同时在执行…

基于GPT-4免费生成代码的工具!小游戏,管理系统都能生成!

Cursor支持Python、Java、C、JavaScript、C#等等&#xff0c;可AI生成代码&#xff0c;功能非常强大&#xff01;这篇教程将教你如何下载安装&#xff0c;带你玩转Cursor 目录 话不多说&#xff0c;先看能力&#xff1a; 只需要三步&#xff0c;就可以AI出你想要的代码&#x…

测试基础知识

开发模型和测试模型 软件的生命周期 软件的生命周期指的是产品从设想开始到软件不再使用的时间。 软件的生命周期可以分为6个阶段&#xff1a;需求分析&#xff0c;计划&#xff0c;设计&#xff0c;编码&#xff0c;测试&#xff0c;运行维护。 瀑布模型 适用项目&#xf…

[考研数据结构]第3章之栈的基本知识与操作

文章目录 栈的基本概念 栈的实现 顺序栈 共享栈 链栈 栈的基本概念 栈的定义 栈&#xff08;Stack&#xff09;是只允许在一端进行插入或删除操作的线性表 相关术语 栈顶&#xff08;Top&#xff09;线性表允许进行插入或删除的那一端称之为栈顶栈底&#xff08;Bottom&…

JAVASE基础(二)

这里写目录标题JAVASE基础11.科学计数法12.编码和字符集12.编译格式问题13.类型转换类型级别自动类型转换强制类型转换特殊情况14.final修饰符a.修饰变量b.修饰方法c.修饰类15.scanner使用16.两个数交换引入中间变量位运算数学数方法一数学计数方法二17.扩展赋值运算符&#xf…

递归算法_字符串反转_20230412

递归算法-字符串反转 前言 递归算法对解决重复的子问题非常有效&#xff0c;字符串反转也可以用递归算法加以解决&#xff0c;递归算法设计的关键是建立子问题和原问题之间的相关性&#xff0c;同时需要确立递归退出的条件&#xff1b;如果递归退出的条件无法确定&#xff0c…

【LeetCode: 面试题 17.13. 恢复空格 | 暴力递归=>记忆化搜索=>动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Redis安装和配置

目录本章重点Redis安装Redis启动和停止配置后台启动连接前的配置本章重点 主要掌握安装和启动了解redis的配置文件进行配置掌握Redis几种启动方式 Redis安装 下载 Redis官网 点击下载 解压 然后将下载好的压缩包上传到服务器,进行解压! tar zxvf 进行解压 编译 我们要进行编…

4.12每日一练

题目&#xff1a;给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外&#xff0c;这两个数…

学生信息管理系统【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 本系统源码地址&#xff1a;https://download.csdn.net/download/qq_50954361/87673902 更多系统资源库…

安全运营场景下的机器学习算法应用

观测到一个有意思的现象&#xff1a; 假设把安全划分为 基础安全 和 业务安全&#xff0c;PR类的议题中&#xff0c;会出现分级&#xff1a;基础安全领域&#xff0c;喜欢讲纵深防御&#xff0c;给出一个炫酷的架构图&#xff0c;然后各种技术关键字往上标&#xff1b;业务安全…

Doris集群的安装部署

目录 安装与部署 软硬件配置​ 1、机器选择 2、软件选择 3、环境信息修改和部署架构 4、安装部署Doris 5、启动FE 6、在FE节点启动MySQL客户端 7、在BE节点启动be 8、查看BE状态 8、查看FE状态是否正常 WEBUI 官方建议 安装与部署 该文档主要介绍了部署 Doris 所…

如何压缩Outlook数据文件大小

由于 Outlook 需要管理大量的电子邮件&#xff0c;Outlook 偶尔会出现问题是很正常的。 但是&#xff0c;如果你注意到 Outlook 打开或加载的时间过长&#xff0c;这可能是一个严重的问题。此外&#xff0c;你还可能面临其他问题&#xff0c;比如收件箱加载时间过长&#xff0…

WebWorker、ThreeJs的渲染和控制

在 ios16.4 版本中已经开始支持了 OffscreenCanvas &#xff0c;那看样子&#xff0c;是时候再把Three做一波优化了 背景介绍 在之前的项目经验中&#xff0c;如果使用threejs加载比较大的3d场景&#xff0c;那么在创建 threejs 的对象和绘制的时候&#xff0c;会占用浏览器线…

认识C++《共、枚、指1》

目录 前言: 1.共用体的基本知识 2.匿名共用体 3.枚举 3.1设置枚举值 3.2枚举的应用场景 3.3枚举变量的取值范围 4.地址和自由存储空间 5.指针的思想 6.指针的声明和初始化 前言: 指针内容比较多&#xff0c;还需要再出一篇。久等了&#xff01;&#xff01;我看了我的…

数据库中的视图及三级模式结构

文章目录一、视图二、数据库三级模式结构一、视图 简单地说&#xff0c;视图可以看成是一个窗口&#xff0c;它所反映的是一个表或若干表的局部数据&#xff0c;可以简化查询语句。视图一经定义&#xff0c;用户就可以把它当作表一样来查询数据。 但视图和基本表不同&#xf…

Python算法设计 - Karatsuba乘法

版权声明&#xff1a;原创不易&#xff0c;本文禁止抄袭、转载&#xff0c;侵权必究&#xff01; 目录一、Karatsuba 乘法二、算法思路三、Python算法实现四、作者Info一、Karatsuba 乘法 当你在纸上做两个数字的乘法时&#xff0c;一般我们都是用小时候学到的方法&#xff1a…