嘎嘎详细的三维变换详细讲解,包括视图变换、投影变换等,超级通俗易懂!

news2024/9/27 12:09:40

前置二维空间的各种变换笔记:二维变换

三维空间中的齐次坐标

  • 从二维变换开始引申,可得到三维中的一个点的表达方式为 ( x , y , z , 1 ) ⊤ (\mathbf{x}, \mathbf{y}, \mathbf{z}, 1)^{\top} (x,y,z,1),也就是w=1,而三维的向量则表达为 ( x , y , z , 0 ) ⊤ (\mathbf{x}, \mathbf{y}, \mathbf{z}, 0)^{\top} (x,y,z,0),也就是w=0
  • 由于三维空间的一个点是上述格式的,若其中的w由于两点相加或者其他原因超过了1,则我们令这个点的xyz都除以w,那么w就会变成1了,也就是xyz所表达的位置坐标为 ( x / w , y / w , z / w ) (x / w, y / w, z / w) (x/w,y/w,z/w)
  • 而在三维空间中的齐次变换矩阵则如 ( x ′ y ′ z ′ 1 ) = ( a b c t x d e f t y g h i t z 0 0 0 1 ) ⋅ ( x y z 1 ) \left(\begin{array}{l} x^{\prime} \\ y^{\prime} \\ z^{\prime} \\ 1 \end{array}\right)=\left(\begin{array}{lllc} a & b & c & t_x \\ d & e & f & t_y \\ g & h & i & t_z \\ 0 & 0 & 0 & 1 \end{array}\right) \cdot\left(\begin{array}{l} x \\ y \\ z \\ 1 \end{array}\right) xyz1 = adg0beh0cfi0txtytz1 xyz1 所示
  • 其中矩阵的abcdefghi表达为线性变换,tx、ty、tz表达为平移变换,总体表达为一种仿射变换。
  • 同样,矩阵的最后一行也是(0, 0, 0, 1)
  • 其中线性变换和平移变换的执行顺序是先执行线性变换,再执行平移变换,具体可以从我们二维仿射变换公式看 ( x ′ y ′ ) = ( a b c d ) ⋅ ( x y ) + ( t x t y ) \binom{x^{\prime}}{y^{\prime}}=\left(\begin{array}{ll} a & b \\ c & d \end{array}\right) \cdot\binom{x}{y}+\binom{t_x}{t_y} (yx)=(acbd)(yx)+(tytx),先乘线性变换矩阵,再加平移变换。

三维齐次变换

  • 由二维向外引申,便可得到三维的各种变换矩阵形式
  • 缩放变换: S ( s x , s y , s z ) = ( s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ) \mathbf{S}\left(s_x, s_y, s_z\right)=\left(\begin{array}{cccc} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) S(sx,sy,sz)= sx0000sy0000sz00001
  • 平移变换: T ( t x , t y , t z ) = ( 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ) \mathbf{T}\left(t_x, t_y, t_z\right)=\left(\begin{array}{cccc} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{array}\right) T(tx,ty,tz)= 100001000010txtytz1
  • 旋转变换:
    • 绕x轴旋转: R x ( α ) = ( 1 0 0 0 0 cos ⁡ α − sin ⁡ α 0 0 sin ⁡ α cos ⁡ α 0 0 0 0 1 ) \mathbf{R}_x(\alpha)=\left(\begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & \cos \alpha & -\sin \alpha & 0 \\ 0 & \sin \alpha & \cos \alpha & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) Rx(α)= 10000cosαsinα00sinαcosα00001
    • 绕y轴旋转: R y ( α ) = ( cos ⁡ α 0 sin ⁡ α 0 0 1 0 0 − sin ⁡ α 0 cos ⁡ α 0 0 0 0 1 ) \mathbf{R}_y(\alpha)=\left(\begin{array}{cccc} \cos \alpha & 0 & \sin \alpha & 0 \\ 0 & 1 & 0 & 0 \\ -\sin \alpha & 0 & \cos \alpha & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) Ry(α)= cosα0sinα00100sinα0cosα00001
    • 绕z轴旋转: R z ( α ) = ( cos ⁡ α − sin ⁡ α 0 0 sin ⁡ α cos ⁡ α 0 0 0 0 1 0 0 0 0 1 ) \mathbf{R}_z(\alpha)=\left(\begin{array}{cccc} \cos \alpha & -\sin \alpha & 0 & 0 \\ \sin \alpha & \cos \alpha & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) Rz(α)= cosαsinα00sinαcosα0000100001
    • 上述旋转都是简单的绕轴旋转,但是如果是一般性的旋转又该怎么处理呢?
    • 图形学有一个大佬,就写了一个矩阵,可以把任意一个轴的旋转写成一个矩阵,这个旋转公式就是著名的Rodrigues旋转公式,公式为 R ( n , α ) = cos ⁡ ( α ) I + ( 1 − cos ⁡ ( α ) ) n n T + sin ⁡ ( α ) ( 0 − n z n y n z 0 − n x − n y n x 0 ) ⏟ N \mathbf{R}(\mathbf{n}, \alpha)=\cos (\alpha) \mathbf{I}+(1-\cos (\alpha)) \mathbf{n} \mathbf{n}^T+\sin (\alpha) \underbrace{\left(\begin{array}{ccc} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \end{array}\right)}_{\mathbf{N}} R(n,α)=cos(α)I+(1cos(α))nnT+sin(α)N 0nznynz0nxnynx0
    • 其中n代表要绕着的旋转轴向量

图形变换

  • 模型变换:类比于在一个场景中,模型的摆放,也就是拍照时所拍的物体放在哪

  • 视图变换:类比于,找到一个相机的角度,也就是相机在哪里拍照

  • 投影变换: 从模型和视图变换之后做一个3d到2d的投影,类似与相机和拍摄物体都确定好了,拍照的这么个过程

视图变换如何做?

  • 也就是怎么定义一个相机视角

  • 首先需要相机的位置 e ⃗ \vec{e} e ,其次还需要相机的朝向 g ^ \hat{g} g^,也就是往哪看,最后需要一个向上方向 t ^ \hat{t} t^来定义相机是往上看还是往下看。至此,即可确定一个相机的视角了。

  • 由于只要能保住相机和其所拍摄的物体所有的相对位置都是固定的,那么无论相机和这个物体被怎样移动,那么最后拍摄下来的照片应该都是一样的才对,所以为了方便运算,有一个约定俗成的规定,就是将相机永远摆放至原点

  • 假设当前相机视角如图所示,应该怎样将其变换到原点出呢

    image-20240710090850635

    image-20240710091101643

    • 首先做一个平移变换将相机移动到原点
    • 再将相机朝向 g ^ \hat{g} g^做旋转变换移动到-Z上
    • 最后将向上朝向 t ⃗ \vec{t} t 移动到Y上,那么 g × t g \times t g×t也就自动朝向X了
    • 我们可以定义整个变换矩阵为M,也就是用M来表达刚刚的所有操作,那么就有 M view  = R view  T view  M_{\text {view }}=R_{\text {view }} T_{\text {view }} Mview =Rview Tview 
    • 也就是先乘平移变换再乘旋转变换即可得到总的M变换矩阵,而这个变换矩阵T很好写,为 T view  = [ 1 0 0 − x e 0 1 0 − y e 0 0 1 − z e 0 0 0 1 ] T_{\text {view }}=\left[\begin{array}{cccc} 1 & 0 & 0 & -x_e \\ 0 & 1 & 0 & -y_e \\ 0 & 0 & 1 & -z_e \\ 0 & 0 & 0 & 1 \end{array}\right] Tview = 100001000010xeyeze1 ,也就是将自己的所在点各减去自己点离原点的距离即可
    • 而旋转R矩阵则相对较难,很难直观的知道怎样从一个轴变换到X、Y、-Z轴上,但是我们如果反过来思考,如果要把X、Y、-Z轴变换到某一个轴上,就很简单了,这就是前文提到的逆变换,而我们知道,逆变换矩阵是一个正交矩阵,而正交矩阵有一个性质就是他的逆是他自己的转置 R − θ = R θ T \mathbf{R}_{-\theta}=\mathbf{R}_{\theta}^T Rθ=RθT,于是我们只需要求出X、Y、Z如何变换到 g × t g\times t g×t t t t − g -g g上,再对该矩阵转置一下,就能得到从 g × t g\times t g×t t t t g g g变换到X、Y、-Z的变换矩阵了。
    • 比如要将X轴 [ 1 0 0 0 ] \begin{bmatrix} 1\\ 0\\ 0\\ 0 \end{bmatrix} 1000 旋转到 g × t g \times t g×t [ x g ^ × t ^ y g ^ × t ^ z g ^ × t ^ 0 ] \begin{bmatrix} x_{\hat{g} \times \hat{t} }\\ y_{\hat{g} \times \hat{t} }\\ z_{\hat{g} \times \hat{t} }\\ 0 \end{bmatrix} xg^×t^yg^×t^zg^×t^0 上,则旋转矩阵为 [ x g ^ × t ^ 0 0 0 y g ^ × t ^ 0 0 0 z g ^ × t ^ 0 0 0 0 0 0 1 ] \left[\begin{array}{cccc} x_{\hat{g} \times \hat{t}} & 0 & 0 & 0 \\ y_{\hat{g} \times \hat{t}} & 0 & 0 & 0 \\ z_{\hat{g} \times \hat{t}} & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] xg^×t^yg^×t^zg^×t^0000000000001 ,同理可得Y、Z轴,将其合并一下,即可得到总的逆旋转矩阵 R v i e w − 1 = [ x g ^ × t ^ x t x − g 0 y g ^ × t ^ y t y − g 0 z g ^ × t ^ z t z − g 0 0 0 0 1 ] R_{view}^{-1}=\left[\begin{array}{cccc} x_{\hat{g} \times \hat{t}} & x_t & x_{-g} & 0 \\ y_{\hat{g} \times \hat{t}} & y_t & y_{-g} & 0 \\ z_{\hat{g} \times \hat{t}} & z_t & z_{-g} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] Rview1= xg^×t^yg^×t^zg^×t^0xtytzt0xgygzg00001 ,则转置后的旋转矩阵为 R v i e w = [ x g ^ × t ^ y g ^ × t ^ z g ^ × t ^ 0 x t y t z t 0 x − g y − g z − g 0 0 0 0 1 ] R_{view}=\left[\begin{array}{cccc} x_{\hat{g} \times \hat{t}} & y_{\hat{g} \times \hat{t}} & z_{\hat{g} \times \hat{t}} & 0 \\ x_t & y_t & z_t & 0 \\ x_{-g} & y_{-g} & z_{-g} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] Rview= xg^×t^xtxg0yg^×t^ytyg0zg^×t^ztzg00001 ,这便得到了从任意轴旋转到原点X、Y、-Z轴的旋转矩阵了,再和前面的平移矩阵T相乘,即可得到最终的变换矩阵M。
  • 也就是,只要相机和所拍摄关联到的物体都按照这个M矩阵进行变换,那么在变换前和变换后所拍摄到的内容应该都是一样的。

投影变换如何做?

  • 正交投影:投影前后无透视扭曲,即无近大远小的特性

    image-20240710101540574

    • 而想要将三维物体在无透视变化的情况下投影到二维平面上其实很简单,只需要去除这个物体的z轴就行了

      image-20240710133905868

    • 假设我们要投影的物体如上所示,可以发现,只要将他俩的z轴去掉,那么剩下的x,y自然就是他在二维平面上的投影。

    • 但是一般情况下,需要先将这个物体通过变换矩阵转移到原点xy轴的-1到1之间的矩形之中,这样做的目的是为了简化后续操作,也就是大家都遵守这套规范,后续api啊各方面的开发就会很简便。

    • 但是这样做就会出现一个问题,就是物体的前后信息丢失了,你无法显示出物体的深度信息,为了解决这个问题,通常会保留下这个z轴,也就是说先将物体通过各种变换转移到原点处xyz都在-1到1的一个立方体中,这个立方体也叫做标准化空间,这样的话物体之间的深度信息就会保留下来,也就是x和y坐标会被用来确定物体在屏幕上的位置,而z坐标则用于深度测试等目的。而最终的三维到二维的投影呢则是对这个标准化空间里做一个切片,z坐标被用来进行深度测试和裁剪,而x和y坐标则被用来确定最终在屏幕上的位置。也就是如下图所示。

      image-20240710135747981

    • 其中l、r为物体的左右(left、right),b、t为下上(bottom、top),f、n为远近(far,near)。

    • 而将被拍摄物体通过变换矩阵到原点的-1到1的空间内也就很简单了,先平移变换,再缩放变换即可(对应着上图的二图和三图)。

    • 平移变换可以直接将物体的中心处移动到原点处即可,而物体的中心计算方法就很简单,x轴的中心就是 r + l 2 \frac{r+l}{2} 2r+l,yz轴同理,那么将物体最终移动到中心就是自身每个轴减去这个值即可,于是平移变换矩阵为 [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] \left[\begin{array}{cccc} 1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{array}\right] 1000010000102r+l2t+b2n+f1

    • 而缩放变换呢就是要将物体规范化到-1到1的空间内,-1到1的长度为2,那么x轴的缩放就是用2除以物体的宽度,也就是 2 r − l \frac{2}{r-l} rl2(具体数学推理就是求一个线性变换y=ax+b,将x等于l和r代入即可得到a和b的值,其中a就是缩放因子,b就是平移因子,最后解的a就是这个2/(r-l)),其他轴同理,于是缩放矩阵为 [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] \left[\begin{array}{cccc} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] rl20000tb20000nf200001

    • 而最终的正交投影变换矩阵为他俩相乘 M ortho  = [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] = [ 2 r − l 0 0 − r + l 2 0 2 t − b 0 − t + b 2 0 0 2 n − f − n + f 2 0 0 0 1 ] M_{\text {ortho }}=\left[\begin{array}{cccc} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right]\left[\begin{array}{cccc} 1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{array}\right]=\left[\begin{array}{cccc} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{2} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{2} \\ 0 & 0 & \frac{2}{n-f} & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{array}\right] Mortho = rl20000tb20000nf200001 1000010000102r+l2t+b2n+f1 = rl20000tb20000nf202r+l2t+b2n+f1

    • 最后通过这个矩阵M就可以将任意物体规范化到原点处-1到1的标准空间中啦~

  • 透视投影:有近大远小的特性

    image-20240710101525589

    • 将三维物体通过透视投影到二维平面上有一个办法,由于透视投影他可以理解成沿着一个点,向外延申出四条线,如上图,那么所包裹住的物体就是一个四棱台,而我们知道,正交投影所包裹住的是一个长方体,那我们就可以先将这个四棱台压成长方体,再按照正交投影的办法去变换即可。

      image-20240710144540819

    • 也就是将上面左图的远平面在xy轴处压成近平面的矩形,最终呈现右图的样子。显然,在这个变化当中,近平面的x、y、z都不会发生改变,而远平面的z和远平面中心点也不会发生改变。

      image-20240710150424063

    • 如上图所示((x’,y’,z’)是近平面的点,(x,y,z)是远平面的点),根据相似三角形原则,若点(x,y,z)想变换到点(x’,y’,z’)上,y和y’的比值一定等于n和z的比值,于是可得 y ′ = n z y y^{\prime}=\frac{n}{z} y y=zny,同理可得 x ′ = n x y x^{\prime}=\frac{n}{x} y x=xny

    • 也就是说原本(x,y,z,1)和一个矩阵相乘后,会得到(nx/z,ny/z,不知道,1)这样的向量,而我们知道,在齐次坐标中,一个点同乘任何非0常数,所表达的矩阵依然一致,也就是(nx/z,ny/z,不知道,1)和(nx,ny,不知道,z)他俩所表达的点都是(x,y,z),也就是 M persp  →  ortho  ( 4 × 4 ) ( x y z 1 ) = ( n x n y  unknown  z ) M_{\text {persp } \rightarrow \text { ortho }}^{(4 \times 4)}\left(\begin{array}{l} x \\ y \\ z \\ 1 \end{array}\right)=\left(\begin{array}{c} n x \\ n y \\ \text { unknown } \\ z \end{array}\right) Mpersp  ortho (4×4) xyz1 = nxny unknown z

    • 很容易就能得到这个M矩阵为 M persp ortho  = ( n 0 0 0 0 n 0 0 ? ? ? ? 0 0 1 0 ) M_{\text {persp ortho }}=\left(\begin{array}{cccc} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ ? & ? & ? & ? \\ 0 & 0 & 1 & 0 \end{array}\right) Mpersp ortho = n0?00n?000?100?0

    • 而上述矩阵中的第三行的值可以通过前面所说的两个条件来计算,就是“近平面的x、y、z都不会发生改变,而远平面的z和远平面中心点也不会发生改变。”

    • 设近平面的z轴值为n,也就是上面的M矩阵乘上近平面的(x,y,n,1)后仍然是(x,y,n,1),然后在这个齐次坐标同乘一个n,也就是 M persp  →  ortho  ( 4 × 4 ) = ( x y n 1 ) = = ( n x n y n 2 n ) M_{\text {persp } \rightarrow \text { ortho }}^{(4 \times 4)}=\left(\begin{array}{l} x \\ y \\ n \\ 1 \end{array}\right)==\left(\begin{array}{c} n x \\ n y \\ n^2 \\ n \end{array}\right) Mpersp  ortho (4×4)= xyn1 == nxnyn2n

    • 那么此时我们将M矩阵的第三行当个向量提取出来,也就是 ( 0 0 A B ) ( x y n 1 ) = n 2 \left(\begin{array}{llll} 0 & 0 & A & B \end{array}\right)\left(\begin{array}{l} x \\ y \\ n \\ 1 \end{array}\right)=n^2 (00AB) xyn1 =n2,前面两个数之所以为0是因为很明显最后的这个 n 2 n^2 n2肯定和xy无关,相乘后也就是 A n + B = n 2 A n+B=n^2 An+B=n2

    • 而远平面的中心点在变换中不会发生改变,设远平面的z轴值为f,而远平面中心点则表示为 ( 0 0 f 1 ) \left(\begin{array}{l} 0 \\ 0 \\ f \\ 1 \end{array}\right) 00f1 ,同时乘个f,则为 ( 0 0 f 2 f ) \left(\begin{array}{c} 0 \\ 0 \\ f^2 \\ f \end{array}\right) 00f2f ,和前面的 ( 0 0 A B ) \left(\begin{array}{llll} 0 & 0 & A & B \end{array}\right) (00AB)相乘后也就是 A f + B = f 2 A f+B=f^2 Af+B=f2,解两式可得 A = n + f B = − n f \begin{aligned} & A=n+f \\ & B=-n f \end{aligned} A=n+fB=nf

    • 这样就得到了最终的变换矩阵 M persp ortho  = ( n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ) M_{\text {persp ortho }}=\left(\begin{array}{cccc} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & 1 & 0 \end{array}\right) Mpersp ortho = n0000n0000n+f100nf0 ,这个矩阵可以将任意物体从透视投影的四棱台挤压成正交投影的正方形

    • 最后再按照正交投影的方法来完成后续步骤即可完成透视投影 M persp  = M ortho  M persp  →  ortho  M_{\text {persp }}=M_{\text {ortho }} M_{\text {persp } \rightarrow \text { ortho }} Mpersp =Mortho Mpersp  ortho 

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

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

相关文章

插入排序算法(C语言版)

直接插入排序 插入排序(insert sort)是一种简单的排序算法,它的工作原理与手动整理一副牌的过程非常相似。 具体来说,我们在未排序区间选择一个基准元素,将该元素与其左侧已排序区间的元素逐一比较大小,并…

了解劳动准备差距:人力资源专业人员的战略

劳动准备差距是一个紧迫的问题,在全球人事部门回应,谈论未开发的潜力和错过的机会。想象一下,人才和需求之间的悬崖之间有一座桥,这促使雇主思考:我们是否为员工提供了足够的设备来应对未来的考验? 这种不…

认识R155法规(UN Regulation No. 155)-MUNIK

背景 Background 随着汽车新四化(电动化、智能化、网联化、共享化)政策的提出,大数据和人工智能等技术的发展,以及软件驱动汽车、舱驾一体、行泊一体等新型架构概念的提出,车内外智能传感器采集的大量数据&#xff08…

桌面悬浮备忘录哪个好?能在桌面悬浮使用的备忘app

备忘录是我们日常工作和生活中的常用工具,它帮助我们记录重要信息,提醒我们完成各项任务。而将备忘录悬浮在桌面上使用,无疑能进一步提高我们的工作效率。想象一下,在处理复杂的工作任务时,你能够随时在桌面上查看提醒…

求函数最小值-torch版

目标:torch实现下面链接中的梯度下降法 先计算 的导函数 ,然后计算导函数 在处的梯度 (导数) 让 沿着 梯度的负方向移动, 自变量 的更新过程如下 torch代码实现如下 import torchx torch.tensor([7.5],requires_gradTrue) # print(x.gr…

【xinference】(15):在compshare上,使用docker-compose运行xinference和chatgpt-web项目,配置成功!!!

视频演示 【xinference】(15):在compshare上,使用docker-compose运行xinference和chatgpt-web项目,配置成功!!! 1,安装docker方法: #!/bin/shdistribution$(…

【SVN-CornerStone客户端使用SVN-多人开发-解决冲突 Objective-C语言】

一、接下来,我们来说第三方的图形化界面啊, 1.Corner Stone:图形化界面,使用SVN, Corner Stone的界面,大概就是这样的, 1)左下角:是我们远程的一个仓库, 2)右上角:是我们本地的一些东西, 首先,在我的服务器上,再开一个仓库,叫做wechat, 我在这个里边,新建…

红队常用命令速查大全(非常详细)零基础入门到精通,收藏这一篇就够了

这里我整合并且整理成了一份【282G】的网络安全/红客技术从零基础入门到进阶资料包,需要的小伙伴文末免费领取哦,无偿分享!!! 对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以…

开放式耳机什么品牌好?四款音质好的开放式耳机推荐

长时间佩戴耳机,舒适度成为了不可忽视的因素。开放式耳机通常采用轻量化材料和透气耳垫,减轻耳朵的负担,即使长时间聆听,也能保持耳朵的舒适与干爽。 然而,众多品牌的开放式耳机琳琅满目,究竟哪个品牌的开…

从重庆元宇宙国风秀看未来元宇宙发展趋势

2024年2月24日,为纪念梅兰芳先生诞辰130周年,以“新国风东方美”为主题的【承华灵境】元宇宙国风秀在重庆市人民大礼堂发布。这场活动将中国经典艺术与数字化技术融合,呈现了一场新国风东方美学的跨越时空人文科技之旅,其中的重点…

【Linux】数据流重定向

数据流重定向(redirect)由字面上的意思来看,好像就是将【数据给它定向到其他地方去】的样子? 没错,数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据,给它传输到其他的地方,例如文件或…

前端发布项目后,解决缓存的老版本文件问题

最近碰到如题目所说的问题,用了思路一的解决方法,结束之后又上网看技术大牛们的解决方法,总结得出下面的文章。 方式一:纯前端 每次打包发版时都使用webpack构建一个version.json文件,文件里的内容是一个随机的字符串…

递归(五)—— 初识暴力递归之“如何利用递归实现栈逆序”

题目:要求不使用额外的数据结构,仅利用递归函数实现栈的逆序。 题目分析: 利用实例来理解题意,栈内元素从栈底到栈顶一次是3,2,1 ,要求经过处理后,栈底到栈顶依次是1,2…

FastAPI 学习之路(三十五)项目结构优化

之前我们创建的文件都是在一个目录中,但是在我们的实际开发中,肯定不能这样设计,那么我们去创建一个目录,叫models,大致如下。 主要目录是: __init__.py 是一个空文件,说明models是一个package…

前端面试39(关于git)

针对前端开发者的Git面试题可以覆盖Git的基础概念、常用命令、工作流程、团队协作、以及解决冲突等方面。以下是一些具体的Git面试 Git基础知识 什么是Git? Git是一个分布式版本控制系统,用于跟踪计算机文件的更改,并协调多个人共同在一个项…

最简单详细的jwt用户登录校验教程(新手必看)

首先简单建张用户表。 DROP TABLE IF EXISTS user; CREATE TABLE user (id bigint NOT NULL AUTO_INCREMENT,name varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,username varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL…

C++ 编译体系入门指北

前言 之从入坑C之后,项目中的编译构建就经常跟CMake打交道,但对它缺乏系统的了解,遇到问题又陷入盲人摸象。对C的编译体系是如何发展的,为什么要用CMake,它的运作原理是如何的比较感兴趣,所以就想系统学习…

迁移至 AI-Ready 基础架构:日立内容平台至 MinIO

借助我们的 HCP-to-MinIO 工具,从 Hitachi Content Platform (HCP) 过渡到 MinIO 从未如此简单。该工具旨在支持客户不断变化的存储需求,可在 GitHub 上免费获得,大大简化了迁移过程。许多组织正在转型,以利…

台灯怎么选对眼睛好?六大重点教你台灯怎么选不踩雷

根据2024年国家卫健委最新公布的数据,我国儿童青少年总体近视率为52.7%,其中,小学生为42%,初中生为80.7%,高中生为85.7%。儿童的学习环境对学习效果和视力健康都有很大影响。面对日益严峻的近视形势,家长和…

基因检测3 - 遗传性耳聋

1. 耳聋简介 在每1000个新生儿中有1-3个耳聋患儿,绝大部分为遗传学耳聋。遗传性耳聋疾病的遗传方式包括常染色体隐性遗传、常染色体显性遗传、线粒体遗传以及伴性遗传。 根据遗传性耳聋除听力损失外是否存在其他表型,将耳聋分为综合征型耳聋 &#xff…