图像处理之频域滤波DFT

news2024/12/26 22:25:27

  摘要:傅里叶变换可以将任何满足相应数学条件的信号转换为不同系数的简单正弦和余弦函数的和。图像信号也是一种信号,只不过是二维离散信号,通过傅里叶变换对图像进行变换可以图像存空域转换为频域进行更多的处理。本文主要简要描述傅里叶变换以及其在图像处理中的简单应用,并进行一些简单的实验来描述其相关性质。
  关键字:傅里叶变换,二维傅里叶变换,二维离散傅里叶变换

  傅里叶变换是对傅里叶级数进行研究得到的结论,傅里叶发现满足一定数学条件的复杂周期函数可以用一系列简单的正弦和余弦函数之和表示。分解后的表示形式的每个分量都是一个频率的分量,也就将复杂信号转换成简单信号,而简单信号更容易进行数学描述和分析。

1 复数域

  由于傅里叶变换中涉及到了复数,首先简单了解下复数。
  复数的定义如下:
C = R + j I C=R+jI C=R+jI
  其中 R R R I I I都为实数分别为复数的实部和虚部,而 j j j是-1的平方根,即 j 2 = − 1 j^2=-1 j2=1。实数集就是我们一般谈的数集,其实复数的子集(当 I = 0 I=0 I=0时)。如果需要在平面坐标中表述复数,其实和普通的笛卡尔坐标系表示相同,只是横坐标换成实数,纵坐标换成虚数即可(即复数是复平面坐标中的点 ( R , I ) (R,I) (R,I))。
  复数的共轭:
C ∗ = R − j I C^{*}=R-jI C=RjI
  复数在极坐标下的表示为:
C = ∣ C ∣ ( c o s θ + j s i n θ ) ∣ C ∣ = R 2 + I 2 θ = a r c t a n ( I R ) \begin{equation} \begin{aligned} C&=|C|(cos\theta+jsin\theta)\\ |C|&=\sqrt{R^2+I^2}\\ \theta&=arctan(\frac{I}{R}) \end{aligned} \end{equation} CCθ=C(cosθ+jsinθ)=R2+I2 =arctan(RI)
  另外如果用欧拉公式转( e j θ = c o s θ + j s i n θ e^{j\theta=cos\theta+jsin\theta} ejθ=cosθ+jsinθ)换则可以转换为:
C = ∣ C ∣ e j θ C=|C|e^{j\theta} C=Cejθ

2 傅里叶变换

2.1 傅里叶级数

  傅里叶级数:即具有周期 T T T的连续变换 t t t的周期函数 f ( t ) f(t) f(t)可以被描述为乘以适合的系数的正弦和余弦的和,这个和就是傅里叶级数。
f ( t ) = ∑ n = − ∞ ∞ c n e j 2 π n T t c n = 1 T ∫ − T 2 T 2 f ( t ) e − j 2 π n T t d t , n = 0 , ± 1 , ± 2 , . . . \begin{equation} \begin{aligned} f(t)&=\sum_{n=-\infty}^{\infty}{c_{n}e^{j\frac{2\pi n}{T}t}}\\ cn&=\frac{1}{T}\int_{-\frac{T}{2}}^{\frac{T}{2}}{f(t)e^{-j\frac{2\pi n}{T}t}}dt,n=0,\pm1,\pm2,... \end{aligned} \end{equation} f(t)cn=n=cnejT2πnt=T12T2Tf(t)ejT2πntdt,n=0,±1,±2,...
  使用欧拉公式转换即可得到正弦和余弦和的标识:
f ( t ) = ∑ n = − ∞ ∞ c n [ c o s ( 2 π n T t ) + j s i n ( 2 π n T t ) ] f(t)=\sum_{n=-\infty}^{\infty}{c_{n}[cos(\frac{2\pi n}{T}t)+jsin(\frac{2\pi n}{T}t)]} f(t)=n=cn[cos(T2πnt)+jsin(T2πnt)]
  假设原始波形的为 f ( t ) = f ( t + T ) f(t)=f(t+T) f(t)=f(t+T),则对于傅里叶级数而言,其n次谐波(当 n = 1 n=1 n=1时的分量为一次谐波, n = 2 n=2 n=2时的分量为二次谐波)的幅度为 c n c_n cn,周期为 T n \frac{T}{n} nT,频率为 n T \frac{n}{T} Tn
在这里插入图片描述

2.2 连续傅里叶变换

  一维连续傅里叶变换
  满足狄利克雷条件的函数 f ( t ) f(t) f(t)的傅里叶变换为:

  狄利克雷条件:

  • 在一周期内,连续或只有有限个第一类间断点;
  • 在一周期内,极大值和极小值的数目应是有限个;
  • 在一周期内,信号是绝对可积的。

F ( μ ) = ∫ − ∞ + ∞ f ( t ) e − j 2 π μ t d t F ( μ ) = ∫ − ∞ + ∞ f ( t ) [ c o s ( 2 π μ t ) − j s i n ( 2 π μ t ) ] d t μ = n T \begin{equation} \begin{aligned} F(\mu)&=\int_{-\infty}^{+\infty}{f(t)e^{-j2\pi \mu t}dt}\\ F(\mu)&=\int_{-\infty}^{+\infty}{f(t)[cos(2\pi \mu t) - jsin(2\pi \mu t)]dt}\\ \mu&=\frac{n}{T} \end{aligned} \end{equation} F(μ)F(μ)μ=+f(t)ej2πμtdt=+f(t)[cos(2πμt)jsin(2πμt)]dt=Tn
   F ( t ) F(t) F(t)傅里叶变换对应的傅里叶逆变换 F − 1 ( t ) F^{-1}(t) F1(t)为:
f ( t ) = ∫ − ∞ + ∞ F ( μ ) e j 2 π μ t d μ f ( t ) = ∫ − ∞ + ∞ F ( μ ) [ c o s ( 2 π μ t ) + j s i n ( 2 π μ t ) ] d μ μ = n T \begin{equation} \begin{aligned} f(t)&=\int_{-\infty}^{+\infty}{F(\mu)e^{j2\pi \mu t}d\mu}\\ f(t)&=\int_{-\infty}^{+\infty}{F(\mu)[cos(2\pi \mu t) + jsin(2\pi \mu t)]d\mu}\\ \mu&=\frac{n}{T} \end{aligned} \end{equation} f(t)f(t)μ=+F(μ)ej2πμtdμ=+F(μ)[cos(2πμt)+jsin(2πμt)]dμ=Tn

  傅里叶变换 F ( t ) F(t) F(t)可以将连续函数 f ( t ) f(t) f(t)从时域转换到频域空间,而逆变换 F − 1 ( t ) F^{-1}(t) F1(t)可以将其傅里叶变换 F ( t ) F(t) F(t)还原到时域得到 f ( t ) f(t) f(t)。傅里叶变换和傅里叶逆变换构成傅里叶变换对。通常的信号处理,如果在时域不好处理时,我们可以利用傅里叶变换先将信号转换到频域,在频域空间进行处理之后再用逆变换将信号转换到时域空间。

  二维连续傅里叶变换
  二维傅里叶变换和一维傅里叶变换类似,只是将一维扩展到二维:
F ( μ , v ) = ∫ − ∞ + ∞ ∫ − ∞ + ∞ f ( t , z ) e − j 2 π ( μ t + v z ) d t d z f ( t , z ) = ∫ − ∞ + ∞ ∫ − ∞ + ∞ F ( μ , v ) e j 2 π ( μ t + v z ) d μ d v μ = n T μ , v = n T v \begin{equation} \begin{aligned} F(\mu,v)&=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty}{f(t,z)e^{-j2\pi(\mu t + vz)}dt dz}\\ f(t,z)&=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty}{F(\mu,v)e^{j2\pi(\mu t + vz)}d\mu dv}\\ \mu&=\frac{n}{T_{\mu}},v=\frac{n}{T_{v}} \end{aligned} \end{equation} F(μ,v)f(t,z)μ=++f(t,z)ej2π(μt+vz)dtdz=++F(μ,v)ej2π(μt+vz)dμdv=Tμn,v=Tvn

  傅里叶变换后是在复数空间,即 F ( u ) = R ( μ ) + j I ( μ ) = ∣ F ( μ ) ∣ e j ϕ ( u ) F(u)=R(\mu)+jI(\mu)=|F(\mu)|e^{j\phi(u)} F(u)=R(μ)+jI(μ)=F(μ)ejϕ(u)
  傅里叶谱 ∣ F ( μ ) ∣ = ∣ R ( μ ) 2 + I ( μ ) 2 ∣ 1 2 |F(\mu)|=|R(\mu)^2+I(\mu)^2|^{\frac{1}{2}} F(μ)=R(μ)2+I(μ)221
  相角 ϕ ( μ ) = a r c t h a n ( I ( μ ) R ( μ ) ) \phi(\mu)=arcthan(\frac{I(\mu)}{R(\mu)}) ϕ(μ)=arcthan(R(μ)I(μ))
  能量谱 P ( u ) = ∣ F ( μ ) ∣ 2 = R ( μ ) 2 + I ( μ ) 2 P(u)=|F(\mu)|^2=R(\mu)^2+I(\mu)^2 P(u)=F(μ)2=R(μ)2+I(μ)2

2.3 离散傅里叶变换

  实际使用时由于硬件设备的原因,我们只能对离散数据进行处理,而离散数据是通过采样得到的。

2.3.1 卷积

  在了解如何对连续信号进行取样的傅里叶变换之前先了解下卷积能够方面我们进行后续的处理。
  卷积本质就是将两个信号相乘做积分,但是如果只是简单相乘则得到的输出值当 f ( t ) f(t) f(t)为冲激函数时,输出值和相乘的函数 h ( t ) h(t) h(t)相反。因此需要将 h ( t ) h(t) h(t)关于原点做反转。于是卷积的定义为:
f ( t ) ∗ h ( t ) = ∫ − ∞ + ∞ f ( τ ) h ( t − τ ) d τ f(t)\ast h(t)=\int_{-\infty}^{+\infty}f(\tau)h(t-\tau)d\tau f(t)h(t)=+f(τ)h(tτ)dτ
  而卷积对应的傅里叶变换为( F ( μ ) F(\mu) F(μ) H ( μ ) H(\mu) H(μ)分别为两个函数的傅里叶变换):
F ( f ( t ) ∗ h ( t ) ) = ∫ − ∞ + ∞ [ ∫ − ∞ + ∞ f ( τ ) h ( t − τ ) d τ ] e e − j 2 π τ d t = H ( μ ) F ( μ ) F(f(t)\ast h(t))=\int_{-\infty}^{+\infty}[\int_{-\infty}^{+\infty}f(\tau)h(t-\tau)d\tau]e^{e^{-j2\pi \tau}}dt=H(\mu)F(\mu) F(f(t)h(t))=+[+f(τ)h(tτ)dτ]eej2πτdt=H(μ)F(μ)

2.3.2 取样

  假设对于连续函数 f ( t ) f(t) f(t),对独立变量 t t t Δ T \Delta T ΔT的间隔进行取样,并记采样得到的离散信号为 f ^ ( t ) \hat{f}(t) f^(t),则
在这里插入图片描述

f ^ ( t ) = f ( t ) s Δ T ( t ) = ∑ n = − ∞ + ∞ f ( t ) δ ( t − n Δ T ) \hat{f}(t)=f(t)s_{\Delta T}(t)=\sum_{n=-\infty}^{+\infty}f(t)\delta(t - n\Delta T) f^(t)=f(t)sΔT(t)=n=+f(t)δ(tnΔT)
  其中 s Δ T ( t ) s_{\Delta T}(t) sΔT(t)为冲激串:
在这里插入图片描述

  而取样冲激串的傅里叶变换为:
S ( μ ) = S ( δ ( t − n Δ T ) ) = 1 Δ T ∑ n = − ∞ + ∞ δ ( μ − n Δ T ) \begin{equation} \begin{aligned} S(\mu)&=S(\delta(t - n\Delta T))=\frac{1}{\Delta T}\sum_{n=-\infty}^{+\infty}\delta(\mu - \frac{n}{\Delta T}) \end{aligned} \end{equation} S(μ)=S(δ(tnΔT))=ΔT1n=+δ(μΔTn)
  则采样后的离散序列的傅里叶变换为:
F ( f ^ ( t ) ) = F [ f ( t ) s Δ T ( t ) ] = F ( μ ) ∗ S ( μ ) = 1 Δ T ∑ n = − ∞ + ∞ F ( μ − n Δ T ) F(\hat{f}(t))=F[f(t)s_{\Delta T}(t)]=F(\mu)\ast S(\mu)=\frac{1}{\Delta T}\sum_{n=-\infty}^{+\infty}F(\mu - \frac{n}{\Delta T}) F(f^(t))=F[f(t)sΔT(t)]=F(μ)S(μ)=ΔT1n=+F(μΔTn)
  从上面的式子中我们能够看到采样后的离散信号的傅里叶变换就是原始信号的傅里叶变换的无穷拷贝,而每个拷贝之间的间隔为采样频率,即 1 Δ T \frac{1}{\Delta T} ΔT1。如果采样频率过低,则采样信号的相邻两个傅里叶变换就会重叠,发生混叠无法区分,采样得到的信号就会失真。因此采样频率的下限为 1 2 Δ T \frac{1}{2\Delta T} T1,即奈奎斯特采样频率,如果低于这个频率采样就会失真,高于这个频率采样基本能还原出原始信号。
在这里插入图片描述

  下图的虚线就是使用低采样频率采样失真的效果:
在这里插入图片描述

2.3.3 离散傅里叶变换

  一维离散傅里叶变换
  经过采样的离散函数 f ^ ( t ) 的 \hat{f}(t)的 f^(t)离散傅里叶变换的表示为:
F ^ ( μ ) = ∫ − ∞ + ∞ f ^ ( t ) e − j 2 π μ t d t = ∫ − ∞ + ∞ ∑ n = − ∞ + ∞ f ( t ) δ ( t − n Δ T ) e − j 2 π μ t d t = ∑ n = − ∞ + ∞ ∫ − ∞ + ∞ f ( t ) δ ( t − n Δ T ) e − j 2 π μ t d t = ∑ n = − ∞ + ∞ f n e − j 2 π μ Δ T \begin{equation} \begin{aligned} \hat{F}(\mu)&=\int_{-\infty}^{+\infty}{\hat{f}(t)e^{-j2\pi \mu t}dt}\\ &=\int_{-\infty}^{+\infty}{ \sum_{n=-\infty}^{+\infty}f(t)\delta(t - n\Delta T) e^{-j2\pi \mu t} }dt\\ &=\sum_{n=-\infty}^{+\infty} \int_{-\infty}^{+\infty}{f(t)\delta(t - n\Delta T) e^{-j2\pi \mu t} }dt\\ &=\sum_{n=-\infty}^{+\infty} f_{n}e^{-j2\pi \mu \Delta T} \end{aligned} \end{equation} F^(μ)=+f^(t)ej2πμtdt=+n=+f(t)δ(tnΔT)ej2πμtdt=n=++f(t)δ(tnΔT)ej2πμtdt=n=+fnej2πμΔT
  由于 F ^ ( t ) \hat{F}(t) F^(t)是周期为 1 Δ T \frac{1}{\Delta T} ΔT1的无线周期连续函数,因此我们只需要关心一个周期内的FT状态即可。假设我们在一个周期内得到 F ^ ( t ) \hat{F}(t) F^(t) M M M个等距采样的样本,那么 μ = m M Δ T , m = 0 , 1 , . . . , M − 1 \mu=\frac{m}{M\Delta T},m=0,1,...,M-1 μ=MΔTm,m=0,1,...,M1,即
F ^ ( m ) = ∑ m = 0 M − 1 f n e − j 2 π m n / M , m = 0 , 1 , 2 , . . . , M − 1 \hat{F}(m)=\sum_{m=0}^{M-1}f_ne^{-j2\pi mn/M},m=0,1,2,...,M-1 F^(m)=m=0M1fnej2πmn/M,m=0,1,2,...,M1
  相对的,当我们知道傅里叶变换为 F ^ ( t ) \hat{F}(t) F^(t)时,即可通过逆变换得到对应的离散信号:
f ^ ( n ) = 1 M ∑ m = 0 M − 1 F m e j 2 π m n / M , m = 0 , 1 , 2 , . . . , M − 1 \hat{f}(n)=\frac{1}{M}\sum_{m=0}^{M-1}F_me^{j2\pi mn/M},m=0,1,2,...,M-1 f^(n)=M1m=0M1Fmej2πmn/M,m=0,1,2,...,M1
  二维离散傅里叶变换
    首先我们将上面提到的一维离散傅里叶变换扩展到二维空间:
F ^ ( u , v ) = ∑ x = 0 M − 1 ∑ y = 0 N − 1 f ( x , y ) e − j 2 π ( u x M + v y N ) f ^ ( x , y ) = 1 M N ∑ x = 0 M − 1 ∑ y = 0 N − 1 F ( u , v ) e j 2 π ( u x M + v y N ) \begin{equation} \begin{aligned} \hat{F}(u,v)&=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)e^{-j2\pi(\frac{ux}{M} + \frac{vy}{N})}\\ \hat{f}(x,y)&=\frac{1}{MN}\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}F(u,v)e^{j2\pi(\frac{ux}{M} + \frac{vy}{N})} \end{aligned} \end{equation} F^(u,v)f^(x,y)=x=0M1y=0N1f(x,y)ej2π(Mux+Nvy)=MN1x=0M1y=0N1F(u,v)ej2π(Mux+Nvy)
  二维离散信号是由二维连续函数采样得到,即数字图像是从真实世界采集光信号转换成电信号,由于硬件器件的原因肯定存在精度问题。数字图像是有限时间信号,而有限时间信号包含无限频率,所以无法从采样函数的傅里叶变换中分离出一个完整的原函数的傅里叶变换。因此数字图像总是存在混淆的问题,只是不同精度问题严重程度不同。当采样率足够高时该问题人眼几乎不可察觉。

  混叠是指取样讯号被还原成连续讯号时产生彼此交叠而失真的现象。

3 傅里叶变换的实现

3.1 DCT

  傅里叶变换的实现比较简单,暴力时间复杂度为 O ( n 4 ) \Omicron(n^4) O(n4)。代码中的Matrix是自己实现的矩阵类基本操作就是一般矩阵的操作。#pragma omp parallel for是打开了OMP加速。

template<int, class T>
static Matrix<double> dft(const Matrix<T> &m){
    GASSERT(m.channels() == 1, "the matrix channle must be 1");
    std::size_t hei = m.rows(), wid = m.cols();
    Matrix<double> dftm(m.cols(), m.rows(), 2);
#pragma omp parallel for
    for(std::size_t u = 0; u < hei; u ++){
        for(std::size_t v = 0; v < wid; v ++){
            double rv = 0.0, vv = 0.0;
            for(std::size_t y = 0; y < hei; y ++){
                for(std::size_t x = 0; x < wid; x ++){
                    double xv = 2.0 * M_PI * (u * y * 1.0/ wid + v * x * 1.0/ hei);
                    rv += cos(xv) * m(x, y, 0);
                    vv += -sin(xv) * m(x, y, 0);
                }
            }

            dftm(v, u, 0) = rv;
            dftm(v, u, 1) = vv;
        }
    }

    return dftm;
}

  经过DCT的图像的频域的值不在[0,255]先要autoscale得到下图:
在这里插入图片描述

  依然不方便观察需要将四个顶点的值向中心移动:
在这里插入图片描述

3.2 IDCT

  逆变换同理:

template<class T>
static Matrix<T> idft(const Matrix<double> &m){
    GASSERT(m.channels() == 2, "the matrix channle must be 2");
    std::size_t hei = m.rows(), wid = m.cols();
    Matrix<double> dftm(m.cols(), m.rows(), 1);
    double mn = 1.0 / (hei * wid);
    for(std::size_t y = 0; y < hei; y ++){
        for(std::size_t x = 0; x < wid; x ++) {
            double rval = 0.0, ival = 0.0;
            for(std::size_t v = 0; v < hei; v ++){
                for(std::size_t u = 0; u < wid; u ++) {
                    double vv = 2 * M_PI * (u * x * 1.0/ wid + v * y * 1.0 / hei);
                    double r = m(u, v, 0);
                    double i = m(u, v, 1);
                    rval += r * cos(vv) - i * sin(vv);
                    ival += i * cos(vv) + r * sin(vv);
                }
            }

            double vv = sqrt(rval * rval + ival * ival) * mn;
            dftm(x, y, 0) = vv;
        }
    }

    return dftm.as<T>();
}

  IDCT得到的图像:
在这里插入图片描述

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

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

相关文章

Heap及其应用

目录 堆的相关知识 什么是堆&#xff1f; 堆的性质&#xff1a; 堆的实现&#xff1a; 堆的结构&#xff1a; &#xff08;一&#xff09;堆的插入 向上调整法&#xff1a; 寻找父节点 循环结束条件 代码&#xff1a; &#xff08;二&#xff09;堆的删除 删除根节点…

Huggingface:免费开源AI人工智能API工具平台

| 【产品介绍】 • 名称 Huggingface • 成立/上线时间 2016年 • 具体描述 HuggingFace是一个开源的自然语言处理AI工具平台&#xff0c;它为NLP的开发者和研究者提供了一个简单、快速、高效、可靠的解决方案&#xff0c;让NLP变得更加简…

R绘制箱线图

代码大部分来自boxplot()函数的帮助文件&#xff0c;可以通过阅读帮助文件&#xff0c;调整代码中相应参数看下效果&#xff0c;进而可以理解相应的作用&#xff0c;帮助快速掌握barplot()函数的用法。 语法 Usage(来自帮助文件) barplot(height, ...)## Default S3 method: …

lua环境搭建数据类型

lua作为一门计算机语言&#xff0c;从语法角度个人感觉还是挺简洁的接下来我们从0开始学习lua语言。 1.首先我们需要下载lua开发工具包 在这里我们使用的工具是luadist 下载链接为&#xff1a;https://luadist.org/repository/下载后的压缩包解压后就能用。 2.接下来就是老生…

听GPT 讲Istio源代码--istioctl

在 Istio 项目的 istioctl 目录中&#xff0c;有一些子目录&#xff0c;每个目录都有不同的作用和功能。以下是这些子目录的详细介绍&#xff1a; /pkg: pkg 目录包含了 istioctl 工具的核心代码和库。这些代码和库提供了与 Istio 控制平面交互的功能&#xff0c;例如获取和修改…

postgresql 内核源码分析 btree索引插入分析,索引页面分裂流程,多举措进行并发优化,对异常进行保护处理

Btree索引插入流程分析 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程 ​开源贡献&#xff1a; toadb开源库 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&a…

Swing程序设计详解(一)

【今日】 “若你决定灿烂&#xff0c;山无遮&#xff0c;海无拦” 目录 初识Swing 一 Swing简述 二 Swing常用窗体 2.1 JFrame窗体 2.2 JDialog对话框 2.3JOptionPane小型对话框 (1)通知框 (2)确认框 (3)输入框 (4)自定义对话框 三 常用布局管理器 3.1 绝…

JWT生成与解析/JWT令牌前端存储

第一步&#xff1a;创建项目 添加Maven依赖&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version> </dependency> <dependency><groupId>org.s…

【C++】深拷贝和浅拷贝 ② ( 默认拷贝构造函数是浅拷贝 | 代码示例 - 浅拷贝造成的问题 )

文章目录 一、默认拷贝构造函数是浅拷贝1、默认拷贝构造函数2、默认拷贝构造函数是浅拷贝机制 二、代码示例 - 浅拷贝造成的问题 一、默认拷贝构造函数是浅拷贝 1、默认拷贝构造函数 如果 C 类中 没有定义拷贝构造函数 , C 编译器会自动为该类提供一个 " 默认的拷贝构造函…

GeoJSON转STL:地形3D打印

我们通过将 GeoJSON 形状坐标提取到点云中并使用 Open3d 应用泊松重建&#xff0c;从 GeoJSON 数据重建 STL 网格。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我对打印 GeoJSON 山丘的第一次尝试深感不满&#xff0c;因此想出了一个三步流程&#xff0c;仅使用开源…

Acwing 828. 模拟栈

Acwing 828. 模拟栈 题目要求思路讲解代码展示 题目要求 思路讲解 栈&#xff1a;先进后出 队列&#xff1a;先进先出 代码展示 #include <iostream>using namespace std;const int N 100010;int m; int stk[N], tt;int main() {cin >> m;while (m -- ){string o…

【JVM】经典垃圾收集器

文章目录 说明新生代收集器Serial收集器ParNew收集器Parallel Scavenge收集器 老年代收集器Serial Old收集器Parallel Old收集器CMS收集器 Garbage First收集器需要解决的问题运作过程CMS和G1的区别 说明 Java中有许多垃圾收集器&#xff08;Garbage Collector&#xff0c;GC&…

Spring Cloud Alibaba系列之nacos:(5)源码本地环境搭建

传送门 Spring Cloud Alibaba系列之nacos&#xff1a;(1)安装 Spring Cloud Alibaba系列之nacos&#xff1a;(2)单机模式支持mysql Spring Cloud Alibaba系列之nacos&#xff1a;(3)服务注册发现 Spring Cloud Alibaba系列之nacos&#xff1a;(4)配置管理 为什么要搭建本地…

范文展示,如何三步写出一篇满意的论文

第一步&#xff1a;输入文章关键信息 文章标题&#xff0c;写论文的话即为拟定的论文标题&#xff0c;例如这篇范文中的题目为“阳明心学研究” 关键词&#xff0c;可以写出多个论文主题相关的关键词&#xff0c;用逗号分开&#xff0c;例如这篇范文中只写了一个关键词“王阳…

CentOS 7.6使用mysql-8.0.31-1.el7.x86_64.rpm-bundle.tar安装Mysql 8.0

https://downloads.mysql.com/archives/community/是社区版的官网&#xff0c;可以选择版本下载。 cat /etc/redhat-release可以看到系统版本是CentOS Linux release 7.6.1810 (Core)&#xff0c;uname -r可以看到版本是3.10.0-957.el7.x86_64。 yum remove -y mysql-libs把…

计算机硬件基本组成和各硬件工作原理

计算机硬件基本组成和各硬件工作原理 计算机硬件基本组成早期冯若依曼机的结构冯若依曼机的特点 现代计算机的结构思维导图 各硬件工作原理主存储器运算器控制器I/O 计算机硬件基本组成 计算机硬件基本组成可分两大类 1.早期冯若依曼机的结构 2.现代计算机的结构 早期冯若依曼机…

类与对象的创建

package com.mypackage.oop.later;//学生类 //类里面只存在属性和方法 public class Student {//属性&#xff1a;字段//在类里面方法外面定义一个属性&#xff08;或者说是变量&#xff09;&#xff0c;然后在方法里面对他进行不同的实例化String name; //会有一个默认值&…

在word文档中找不到endnote的选项卡

本人由于在下载endnote之后才下载的office&#xff0c;所以导致在word文档中找不到endnote的选项卡&#xff0c;自己摸索到了解决方法。 首先确保已经拥有word与endnote之后&#xff0c;右键endnote打开所在文件夹&#xff1a; 在文件夹中找到这个Configure endnote.exe运行 之…

three.js简单3D图形的使用

npm init vitelatest //创建一个vite的脚手架 选择 Vanilla 之后自己处理一下 在main.js中写入 // 导入three.js import * as THREE from three// 创建场景 const scene new THREE.Scene();// 创建相机 const camera new THREE.PerspectiveCamera(45, //视角window.inner…

【Unity程序技巧】Unity中的单例模式的运用

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…