【深度学习】图像风格混合——StyleGAN原理解析

news2024/11/26 22:37:20

1、前言

上一篇,我们讲了PGGAN的模型原理,本章我们就来讲解一下StyleGAN,这个模型能够自由控制图像的风格,细节变化等等,生成用户想要的图像,甚至从某种程度上说,其可以实现AI换脸。

PS:这篇文章其实我做了很多功课,本来不想写的。因为对于我这种水平的人来说,论文太难理解,不仅翻译过来语句不顺(本人英语不好,只能看机翻的版本),里面的原理部分也感觉相当抽象。本来想在网上搜一些文章来看一下,结果很多文章都是跟机器翻译直接复制过来的一样,完全不作解释,晦涩难懂。当燃了,也许是我资质驽钝,无法理解里面的那些浅显的概念。为了防止有人和我一样,看论文看的云里雾里,难以理解其中的意思,我还是下决心以通俗的语言去讲解其中的一些概念,不敢说一定正确理解了论文所讲,只希望能帮助到屏幕前对StyleGAN懵逼的你。

原论文:A Style-Based Generator Architecture for Generative Adversarial Networks

参考代码:Pytorch版本,非官方

视频:图像风格混合——StyleGAN原理解析-哔哩哔哩

效果图:

在这里插入图片描述

2、引入

首先,为什么要有StyleGAN。在上一篇的PGGAN中,我们已经能够生成高清大图了,并且质量相当不错。可是,我们仍有一个问题——当我们生成图像的时候,我们对这个图像的一些细节不满意,那能不能对这个图像进行一些修改,比如头型,头发等等进行一些变化。在传统的GAN模型系列中,几乎是做不到的。

为什么呢?因为你不知道那些数据代表头发,哪些数据代表头型。此时的你可能会想,那我们一点点的修改其中的量,看图像的变化,不就能试出来哪些变量代表什么了吗?

想法是美好的,但是现实是骨感的。你就是做不到,因为图像的特征之间存在极大的耦合(相关性),一个变量的修改会影响其他变量的更改。比如你修改了其中一个值,很有可能会让整张图像直接毁掉,因为在本来的框架中,那个值的变动要引起其他值的变动(相关性),才能形成图像。而你只修改了其中一个,很大可能会造成图像崩溃。

于是,人们就想,能不能充分的分离出这些特征,减小特征之间的耦合,让特征之间相互独立,互不影响。这样就可以单独修改图像的某一部分了。而StyleGAN正是解决了这个问题。

2、StyleGAN结构图

StyleGAN模型主要是通过修改生成网络,达到上面的目的

2.1、流程

生成网络的结构图是这篇论文最简单的部分了,我们来看这张图

在这里插入图片描述

其分为a,b两部分,左边是我们传统模型GAN的生成网络,而右边则是修改后的,StyleGAN的生成网络结构。

StyleGAN由两部分构成——Mapping network and Synthesis network ,其中Mapping network就是用来控制图像的风格信息的。Synthesis network用来生成图像。流程如下

首先,由Mapping network从标准正态分布中(也可以是其他简单概率分布)采样出一个z latent Code(512维的向量),然后归一化,依次经过8个全连接层映射,得到的值记作w latent Code(512维的向量)。我们把z latent Code的概率分布空间记作Z latent Space,w latent Code的概率分布空间记作W latent Space。如图

在这里插入图片描述

接着,我们初始化一个可学习的常数(Const),记为x,然后,x加上一个B(B是一个随机噪声经过了仿射变化后的值,也就是 B = w × n o i s e B=w\times noise B=w×noise,其中 w w w是一个可学习的参数,为了对噪声进行一些变化),再经过一个AdaIN(Adaptive Instance Normalization),这里的AdaIN实际上就是上一层的输出进行实例归一化,然后再加上缩放和偏置项,输出公式如下
o u t p u t = y s , i x i − μ ( x i ) σ ( x i ) + y b , i output = y_{s,i}\frac{x_i-\mu{(x_i)}}{\sigma(x_i)}+y_{b,i} output=ys,iσ(xi)xiμ(xi)+yb,i
x i − μ ( x i ) σ ( x i ) \frac{x_i-\mu{(x_i)}}{\sigma(x_i)} σ(xi)xiμ(xi)就是实例归一化了,然后通过 y s , i , y b , i y_{s,i},y_{b,i} ys,i,yb,i就是对其进行缩放和偏置项。这两个y哪来的呢,实际上就是左边的w latent Code 经过一个仿射变化(全连接层)转化为512x2的向量,记为A,然后A拆分为两个512向量,分别对应 y s , i , y b , i y_{s,i},y_{b,i} ys,i,yb,i

经过AdaIN后再经过一个卷积层Conv 3x3,然后再重复一个过程,接着上采样分辨率,又重复这个过程。

所以这就是StyleGAN的生成网络结构图了。

看起来没啥特殊的是不是?从哪里分离特征了?我们知道,synthesis network在生成图像的时候,在每个分辨率都是会将左边的w latent Code注入进去。作者经过实验,**发现在低分辨率注入w latent Code,能够控制图像的姿势、发型、脸型等,中分辨率注入w latent Code,则控制面部特征等,当高分辨率注入w latent Code,会带来颜色和微观结构的调整,比如说肤色。 **作者怎么做实验呢?当模型训练好了之后,作者生成两张图像A,B,他们对应的w latent Code为w0,w1,在低分辨率的时候,我们注入w0,在高分辨率的时候,我们注入w1,就可以观察到变化。如图所示

在这里插入图片描述

​ 这个实验的成功,已经充分说明了图片的特征之间已经充分解耦(线性无关)。

​ 除此之外,我们在结构图中,还看到了在不同分辨率中,都有随机噪声的注入。通过实验,作者发现这些噪声能够用来增加图像某些细节的随机性,比如头发、胡茬、雀斑或皮肤毛孔的准确位置。这个随机噪声的注入,在不同分辨率的影响也不同,具体我们来看这张图

在这里插入图片描述

(a)代表全局输入噪声的生成图。(b)代表无噪声的生成图。(c)代表在高分辨率使用噪声的生成图。

(d)代表在低分辨率使用噪声的生成图。

不难看到,当没有噪声的时候,图片几乎没啥细节、特色,其外观平平;而当加入噪声时,整张图像变得更加细腻。在高分辨率使用噪声时,生成图像的皮肤、头发卷曲、背景,都变得更加细致;在低分辨率使用噪声时,会让头发等变得卷曲或出现背景特征。

2.2、问题①:z latent Code 到 w latent Code

讲到这里,我不知道你是否会有疑惑,但是论文里面雀食讲到了,那就是为什么要多此一举把z latent Code 映射到w latent Code 才注入到synthesis network中,而不是直接把z注入到synthesis network中?

前面我们提到,在不同位置把w latent Code注入,会影响图像的风格(姿态、发型等等),说明w latent Code 是风格信息的代表。而如果我们直接用z latent Code去注入,那么z latent Code就是风格信息的代表。

可是,你想过没,z latent Code是从标准正态分布里面采样出来的,里面的值在一开始都是随机的,从某种意义上来说,这些数值还没有实质意义。什么意思呢?举个不太恰当的例子,假如你把从标准正太采样出来的值赋予意义,第一个值代表性别,第二个值代表头发长度,第三个值代表…,这些赋予的实际意义的值合理吗?

不合理!非常不合理!如果我们的数据集不存在男性且长发的数据,可这两个值是完全随机从标准正太分布中采样的,那么采样出男性且长发的概率就相当大。把这些信息注入到synthesis network中,如果这些信息仍然代表风格信息,那么判别网络肯定会判别为假图像,因为真图像根本没有这种图像。

而对于生成网络而言,既然它避免不了随机采样出代表男性且长发的值,那唯一的办法就是,在后面的数值传播中,将这个组合信息抹去。这种操作会造成什么呢?论文里面的意思会造成特征的扭曲(可简单理解为特征耦合)。

以下为个人看法

换句话说,此时的z latent Code代表的不再是真正意义上的风格信息,因为真正的风格信息不会有男性且长发的组合。如果我们把此时的z latent Code仍然当作是风格信息,那么在后续的前向传播中削去这个组合之后,图像的性别和头发信息又该从哪来?这些都不得而知

在后面的数值传播中,比如在模型图中,经过一个Conv 3x3 的卷积层的变化后,或许就消去了那个组合。那么此时我是否可以认为,此时得到的值,才是真正代表风格信息的呢?但是,你如何确保在经过一个3x3之后就会消除这个组合呢?万一它到了后面输出图像的前一刻才消除呢?那个时刻的信息才真正代表风格信息呢?那个时候的信息已经充分耦合了,你怎么办?这些你是没办法控制的**(也许此时你会疑惑为什么w latent Code就一定能充分解耦,后面会讲到,别急)**

以上为个人看法

而如果先把z latent Code映射到w latent Code,就可以在映射的过程中,直接消去男性且长发的组合。并且,由于经过的是非线性变化,此时的概率分布,理论上可以接近风格信息所对应的概率分布。(当燃了,前提假设是生成网络对于充分解耦的特征能够生成更好的图像,而耦合的则更难)

论文里面用了一张非常形象的图来表示

在这里插入图片描述

(a)是数据集特征空间,左上角缺失的那一部分代表男性且长发的数据。

(b)代表从Z latent Space映射到图像的特征空间,可以看到空间扭曲。这张图的意思更像是Z latent Space本身包含了数据男性且长发的组合,所以其形状是一个圆,如果不扭曲空间,就会包含有那个组合,后续的数值传播中,神经网络不得不扭曲空间,而从达到消去该组合的目的。

(c)代表从W latent Space映射到图像的特征空间,其和数据集的特征空间形状很接近,可以看到特征之间相当平整,有序,更加线性。

作者还进行了消融实验,发现w雀食能够充分解耦,而z却不行。

2.3、 Style mixing(风格混合)

之所以在w latent Code这个位置注入到synthesis network 能够充分解耦,我个人认为很大原因就是因为Style mixing。

风格混合其实就是在训练的时候,我们随机采样出两个z latent Code——z0,z1,然后经过全连接层变成w0,w1。接着,就到了风格的混合。选定一个分辨率位置,低于这个分辨率的层把w0注入进去,高于这个分辨率的层,把w1注入进去。从而达到风格混合。

想法也很简单,如果w代表的是风格信息且没有充分解耦,那么我们随意的对两个w latent Code进行混合,必然会造成文章前面所说到的图像崩溃,从而判别器会一眼判断出真假。而生成网络为了避免这种情况,会让w所代表的风格信息充分解耦起来。

2.4、问题②:W latent Space or Noise ?

前面实验的结果已经很明显了,w latent Code 代表风格信息,控制着图像的全局信息。而噪声则代表一些局部的随机变化。

你是否会有一个疑问,为什么风格是由w latent Code来控制的?就是因为它在不同分辨率注入进去了?噪声也在不同分辨率都注入进去了呀。 凭什么就是你w latent Code代表全局?噪声代表局部?

论文里面提到的如果噪声尝试控制全局信息,会导致空间不一致的情况,从而被判别网络惩罚。

空间不一致?什么意思呢?假如,我们要生成的是一张复古风格的图像,那么在低分辨率的姿态,面部等会带有一些复古的元素;在高分辨率的时候,人面部的肤色以及背景,肯定也是服从复古风格。而这些风格的来源,皆来自同一个w latent Code。

可如果是要噪声来控制,每次都会随机采样一个噪声注入进去,也许在低分辨率的时候,采样出来的风格是复古风格,但是在高分辨率,由于随机性,可能会生成一张清新风格的背景和肤色。这会造成在不同分斌率的风格不一样,这就是空间不一致性。这种不一致性大大提高了判别器判别假图片的成功率。所以,生成网络必然会学习使用w latent Code来代表风格信息,噪声代表局部随机变化。

2.5、 Truncation trick in W(截断技巧)

这个小技巧并不是这篇论文提出来的,其方法是对W latent Code 进行一些约束。首先,计算w latent Code的数学期望
w ˉ = E z ∼ P ( z ) [ f ( z ) ] \bar w = \mathbb{E}_{z \sim P(z)}[f(z)] wˉ=EzP(z)[f(z)]
然后新的w latent Code就等于
w ′ = w ˉ + ϕ ( w − w ˉ ) w^{'}=\bar w + \phi(w-\bar w) w=wˉ+ϕ(wwˉ)
w ′ w^{'} w代表输出的新的w latent Code , ϕ \phi ϕ是我们设定的超参数,其中 ϕ < 1 \phi<1 ϕ<1

这个公式怎么理解呢?在我们进行训练的时候,或许我们存在某种类型的数据较为稀少(低密度区域),那么这种数据肯定没有得到很好的学习。为了提高后面图像的生成质量,采用截断技巧收缩风格空间,减少生成低密度区域图像的可能。

所以我们先对风格信息求出数学期望,得到平均风格,然后用 d = w − w ˉ d =w-\bar w d=wwˉ代表每张图片的风格信息与平均风格的距离。再乘以一个 ϕ \phi ϕ,就代表对这个距离进行缩放。比如 ϕ = 0.5 , d = 0.1 \phi = 0.5,d=0.1 ϕ=0.5d=0.1,那么最终得到0.05,可如果 d = 100 d = 100 d=100,那么最终得到50。不难看到,当这个距离很小的时候,对其进行缩放的程度就越小。而当距离很大时(低密度区域),其缩放程度就越大。

3、Perceptual path length(感知路径长度)

前面我们只是感性地认识了W latent Space可以充分解耦,那么我们如何去衡量解耦的程度呢?

那就通过感知路径长度,首先,我们随机从标准正态中采用出 z 1 , z 2 z_1,z_2 z1,z2,然后利用生成网络,生成左上角和右下角的图像。当特征充分解耦,那么从 z 1 z_1 z1图像的狗变到 z 2 z_2 z2图像的狗的过程中,理应就是改变一些肤色等等。比如我们在点t的位置,仍然是只狗,然后再往前走一步 t + ϵ 1 t+\epsilon_1 t+ϵ1改变一些值,如果充分解耦,那么理应得到的也是一只狗。但是,当特征耦合程度很高的时候,你随意改变其中一个值而其他值没有得到修改,会让图像崩掉,也许就变成了左下角那张床的图像。对于这种情况,你所要修改的值会更多,路径也会更加长(对应图中绿色的线)

图像来自参考【1】

Ps:图像来自参考【1】

所以,当把z latent Code直接注入到synthesis network,我们使用下面的公式求出他的感知路径长度
L Z = E [ 1 ϵ 2 d ( G ( s l e r p ( z 1 , z 2 ; t ) ) , G ( s l e r p ( z 1 , z 2 : t + ϵ ) ) ) ] \mathbb{L}_Z = \mathbb{E}\left[\frac{1}{\epsilon^2}d\left(G(slerp(z_1,z_2;t)),G(slerp(z_1,z_2:t+\epsilon))\right)\right] LZ=E[ϵ21d(G(slerp(z1,z2;t)),G(slerp(z1,z2:t+ϵ)))]
其中 z 1 , z 2 ∼ P ( z ) z_1,z_2 \sim P(z) z1,z2P(z) t ∼ U ( 0 , 1 ) t ∼ U(0,1) tU(0,1), G是生成器,d代表的是感知距离, ϵ = 10 −4,slerp表示球面插值,插值其实就是求出两点之间某个点的所对应的值,比如图中, z 1 , z 2 z_1,z_2 z1,z2之中t所对应的值,不懂的话参考线性插值

而对于将z latent Code映射为w latent Code再注入,其感知距离为
L W = E [ 1 ϵ 2 d ( G ( l e r p ( f ( z 1 ) , f ( z 2 ) ; t ) ) , G ( l e r p ( f ( z 1 ) , f ( z 2 ) : t + ϵ ) ) ) ] \mathbb{L}_W = \mathbb{E}\left[\frac{1}{\epsilon^2}d\left(G(lerp(f(z_1),f(z_2);t)),G(lerp(f(z_1),f(z_2):t+\epsilon))\right)\right] LW=E[ϵ21d(G(lerp(f(z1),f(z2);t)),G(lerp(f(z1),f(z2):t+ϵ)))]
其中lerp表示线性插值

下面我们来看一下流程w latent Code计算感知路径长度的流程

①随机从标准正太采样出 z 1 , z 2 z_1,z_2 z1,z2,映射成 w 1 , w 2 w_1,w_2 w1,w2

②从0~1分布中随机采样一个t,计算 w 1 , w 2 w_1,w_2 w1,w2在t这个位置的线性插值,得到的值记作wt0。再计算t+ ϵ \epsilon ϵ时刻的线性插值,得到的值记作wt1。然后把wt0,wt1注入给synthesis network生成图像 i m g 1 , i m g 2 img_1,img_2 img1img2,对这两张图片进行剪裁,只留下人脸的部分(消去背景)。

③用原始训练数据训练好一个VGG16模型。

④将 i m g 1 , i m g 2 img_1,img_2 img1img2喂给VGG16,VGG16输出他们的特征向量分别记为feature1,feature2

⑤求平方,然后在通道维度求和 d = ∑ c h a n n e l ( f e a t u r e 1 − f e a t u r e 2 ) 2 d = \sum\limits_{channel}(feature1-feature2)^2 d=channel(feature1feature2)2

L w = 1 ϵ 2 d \mathbb{L}_w=\frac{1}{\epsilon^2}d Lw=ϵ21d

最后实验发现,z latent Code的路径长度远远高于w latent Code,这说明w latent Code的解耦程度比z高很多。

4、结束

以上,就是StyleGAN的全部内容了,其中还有一些细节,比如线性可分性我没讲到,因为我觉得无关紧要。如有问题,还望指出,阿里嘎多

在这里插入图片描述

5、参考

【1】图像生成典中典:StyleGAN & StyleGAN2 论文&代码精读 - 知乎 (zhihu.com)

【2】StyleGAN 架构解读(重读StyleGAN)精【1】-CSDN博客

【3】Python PyTorch lerp用法及代码示例 - 纯净天空 (vimsky.com)

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

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

相关文章

[StartingPoint][Tier1]Pennyworth

Important Jenkins是一个用于自动化构建、测试和部署软件项目的开源持续集成和持续部署&#xff08;CI/CD&#xff09;工具。它允许开发团队自动执行和监控在软件开发过程中的重复性任务&#xff0c;例如构建代码、运行测试、部署应用程序等。Jenkins提供了一个易于使用的Web界…

ST表的解释

介绍 ST表&#xff1a;一种用于高效处理区间查询的数据结构。它可以在O(1)的时间复杂度内回答某一区间的最值查询&#xff08;最小值、最大值等&#xff09;。ST表使用动态规划的思想&#xff0c;通过预处理的方式来快速计算出各个区间的最值。 st算法的主要思想就是将所求的…

为什么 MySQL 采用 B+ 树作为索引?

资料来源 : 小林coding 小林官方网站 : 小林coding (xiaolincoding.com) 「为什么 MySQL 采用 B 树作为索引&#xff1f;」这句话&#xff0c;是不是在面试时经常出现。 要解释这个问题&#xff0c;其实不单单要从数据结构的角度出发&#xff0c;还要考虑磁盘 I/O 操作次数&am…

【操作系统】python实现银行家算法

银行家算法是最具有代表性的避免死锁的算法。 1、算法原理 银行家算法&#xff1a;当一个新进程进入系统时&#xff0c;该进程必须申明在运行过程中所需要的每种资源的最大数目&#xff0c;且该数目不能超过系统拥有的资源总量。当进程请求某组资源时&#xff0c;系统必须先确…

Enzo Life Sciences--17β-Estradiol high sensitivity ELISA kit

高灵敏ELISA试剂盒&#xff0c;可检测到低至14 pg/ml的17β-雌二醇 雌二醇(estradiol) 是由卵巢内卵泡的颗粒细胞分泌的类固醇激素&#xff0c;是主要的雌激素&#xff0c;负责调节女性特征、附属性器官的成熟和月经-排卵周期&#xff0c;促进乳腺导管系统的产生&#xff0c;有…

机器人客户端如何配置同步消息至多个群中

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 前言 由于微信群的人数&#xff0c;最多是500人&#xff0c;如果有人的业务做的大&#xff0c;可能会同步创建好多个群&#xff0c;但是资料的不想多个群一起发&#xff0c;发给某个群&a…

产品经理和项目经理的区别

1. 前言 本文深入探讨了产品经理与项目经理在职责、关注点以及所需技能方面的显著区别。产品经理主要负责产品的规划、设计和市场定位,强调对用户需求的深刻理解和产品创新的推动;而项目经理则侧重于项目的执行、进度控制和资源管理,确保项目按时、按质、按预算完成。两者在…

[大模型]大语言模型量化方法对比:GPTQ、GGUF、AWQ

在过去的一年里&#xff0c;大型语言模型(llm)有了飞速的发展&#xff0c;在本文中&#xff0c;我们将探讨几种(量化)的方式&#xff0c;除此以外&#xff0c;还会介绍分片及不同的保存和压缩策略。 说明&#xff1a;每次加载LLM示例后&#xff0c;建议清除缓存&#xff0c;以…

[BT]BUUCTF刷题第13天(4.1)

第13天 Upload-Labs-Linux (Basic) Pass-01 根据题目提示&#xff0c;该题为绕过js验证。 一句话木马&#xff1a; <?php eval(system($_POST["cmd"]));?> // 符号 表示后面的语句即使执行错误&#xff0c;也不报错。 // eval() 把括号内的字符串全部…

「每日跟读」英语常用句型公式 第6篇

「每日跟读」英语常用句型公式 第6篇 1. As ___ as possible 越 ___ 越好 As soon as possible (ASAP)(越快越好) As happy as possible (越快乐越好) As prepared as possible (越有准备越好) As much/many as possible (越多越好 *不可数/可数) As early as possible …

一款轻量、干净的 Laravel 后台管理框架

系统简介 ModStart 是一个基于 Laravel 的模块化快速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 系统特性 …

Chatgpt掘金之旅—有爱AI商业实战篇|内容策展业务|(八)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、AI技术创业内容策展业务有哪些机会&#xff1f; 人工智能&#xff08;AI&#xff09;技术作为当今科技创新的前沿领域&#xff0c;为创业者提供了广阔的机会和挑战。随着…

017——DS18B20驱动开发(基于I.MX6uLL)

目录 一、 模块介绍 1.1 简介 1.2 主要特点 1.3 存储器介绍 1.4 时序 1.5 命令 1.5.1 命令大全 1.5.2 命令使用 1.5.3 使用示例 1.6 原理图 二、 驱动程序 三、 应用程序 四、 测试 一、 模块介绍 1.1 简介 DS18B20 温度传感器具有线路简单、体积小的特点&…

HarmonyOS 应用开发-边缓存边播放案例

介绍 OhosVideoCache是一个支持边播放边缓存的库&#xff0c;只需要将音视频的url传递给OhosVideoCache处理之后再设置给播放器&#xff0c; OhosVideoCache就可以一边下载音视频数据并保存在本地&#xff0c;一边读取本地缓存返回给播放器&#xff0c;使用者无需进行其他操作…

window环境运行nacos源码

为了研究一下nacos,所以从git上下载了nacos源码并且启动。 1.首先下载源码 git地址&#xff1a;https://github.com/alibaba/nacos.git 2.使用ideal打开源码 nacos的启动通过nacos-console模块执行。 3.修改为单机启动模式 Nacos默认启动是集群模式&#xff0c;单机模式需…

微服务面试题二

1.什么是雪崩 微服务之间相互调用&#xff0c;因为调用链中的一个服务故障&#xff0c;引起整个链路都无法访问的情况。 如何解决雪崩&#xff1f; 超时处理&#xff1a;请求超时就返回错误信息&#xff0c;不会无休止等待仓壁模式&#xff1a;限定每个业务能使用的线程数&a…

【三维重建工具】NeRFStudio、3D GaussianSplatting、Colmap安装与使用指南(更新中)

目录 一、NeRFStudio安装1.安装&#xff08;ubuntu系统&#xff09;2.安装&#xff08;windows系统&#xff09; 二、安装tinycudann三、Colmap安装与使用1. 安装依赖2. 安装colmap3.使用colmap3.1 可视化界面使用3.2 Nerfstudio命令行调用Colmap 四、使用NeRFStudio进行三维重…

鸿蒙Native输出so动态库,并提供给第三方导入使用

前言&#xff1a; DevEco Studio版本&#xff1a;4.0.0.600 API:9 最近在学习鸿蒙的Native输出so动态库&#xff0c;下面就给大家分享下我的学习心得及在实现过程中遇到的问题。 实现需求&#xff1a;通过so库输出文本内容 “你好&#xff0c;鸿蒙&#xff01;” 参考资料…

2.SpringBoot利用Thymeleaf实现页面的展示

什么是Thymeleaf&#xff1f; Thymeleaf是一个现代服务器端Java模板引擎&#xff0c;适用于Web和独立环境&#xff0c;能够处理HTML&#xff0c;XML&#xff0c;JavaScript&#xff0c;CSS甚至纯文本。 Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。为实现这…

HarmonyOS4.0模拟器安装

我们也可以利用设备模拟器来查看更真实的效果。不过需要先配置模拟器。 首先&#xff0c;选择主菜单中的Tools&#xff0c;找到其中的Device Manager&#xff0c;即设备管理&#xff1a; 安装设备 设备可以是远端设备&#xff0c;也可以是本地设备&#xff0c;我们可以先安装…