【用文本生成歌声】Learn2Sing 2.0——歌声转换算法及梅尔频谱详解

一. 频谱图与梅尔谱图的介绍

频谱图:频谱图可以理解为一堆垂直堆叠在一起的快速傅里叶变换结果。

1.1 信号

在进入频谱图模块之前,首先我们需要了解信号是什么。
信号就是某一特定量随时间变化,对于音频来说,这个特定的变化量就是气压。我们采集到的信号叫做波形,他可以通过计算机来描述出来(如下图):
横轴为时间,纵轴为振幅
在这里插入图片描述
现在我们得到了一个可以处理的语音信号数字表示,我们需要使用傅立叶变换来对这个波形做进一步处理。

1.2 傅立叶变换

傅立叶变换双语讲解链接
傅立叶变换是将信号从时域转为频域的强大利器。对于我们上面得到的波形信号,该信号由多个单频声波组成,当我们随着时间对信号进行采样时,我们仅仅能够捕获到最终叠加后的振幅(amplitude)。但是傅立叶变换可以帮助我们将其分解为多个频率和频率对应的振幅。最终得到的数据称为频谱。具体变化如下图所示:
在这里插入图片描述

1.3 快速傅立叶变换与频谱图

在得知什么是傅立叶变换后,我们引入了快速傅立叶变换(FFT),它们在数学上达到的效果是相同的,但是快速傅立叶变换将时间复杂度降低为nlogn。所以我们在实际操作中一般使用FFT(注意FFT一般要求输入数据的长度是2的幂次方)。
我们对1.1中得到的波形做快速傅立叶变换,得到下面的频谱图
在这里插入图片描述
可以看到频谱的横坐标为频率,纵坐标为振幅

But,我们忽略了一个很重要的点,那就是在上面的分析过程中,我们假设信号只是由多个单一的周期性信号组成的,但是在实际生活中,应该还掺杂着大量的非周期信号!这种信号在时间-振幅图上,显示为无规律的波形图案。

我们用简单的加法就可以得知,规则信号+不规则信号=不规则信号,因此我们实际处理的大部分音频是不规则信号
好消息是我们仍然可以使用快速傅立叶变换来处理这些不规则信号。
怎么处理呢?好问题!

1.3.1 整体机理简单解释

首先我们要明确的是,傅立叶变换适合处理周期性的规则数据,那么我们如何将不规则的数据转换为规则数据呢?答案可能在你学微积分的时候就可以得到——那就是切分。我们将不规则的数据按照特定大小(也就是窗口)进行切分,得到较小的片段,这样的小片段更适合进行傅立叶变换。最后我们将得到每个小片段的频谱图。

整体流程如下图所示:
在这里插入图片描述

1.3.2 窗函数的应用

上图展示了“Window Length”(窗长)和“Hop Length”(跳跃长度),以及窗函数的形状。窗长定义了每次FFT分析所考虑的信号长度,而跳跃长度是指每次窗口移动的时间间隔。通常,窗口之间会有一定的重叠,称为“Overlap Length”(重叠长度)。

可以看到,两个窗口会有重叠的部分,这称为窗口重叠,窗口重叠可以减少频谱的泄露,原因如下:

  • 窗口效应:在对音频信号进行窗函数处理时,窗函数的边缘通常会对信号进行衰减。这会导致窗口两端的信号部分丢失信息,尤其是当信号的频率成分在窗口的边界处变化较大时。
  • 连续性保持:通过使窗口之间重叠,可以保证每个信号的部分至少在两个或多个窗口中被分析,从而减少由于窗口效应导致的信息丢失和频谱泄露。

通过使用窗口函数,我们成功地将原始信号分割成多个重叠的段落,并对每个段落应用窗函数,得到多个窗口化的信号段。

1.3.3 快速傅立叶变换(FFT)分析

即对每个窗口化的信号段进行FFT分析。FFT将这些时域信号转换成频域信号,输出频率成分和它们的幅度。我们上述在做的(多个窗口进行傅立叶变换),也被称为短时傅里叶变换(short-time Fourier transform,STFT)。

我们将得到的小的窗口,通过梅尔滤波器组,这些滤波器按照梅尔尺度均匀分布,并且每个滤波器覆盖特定的频率范围。

1.3.4 后续计算

计算每个滤波器的能量:
对于每个梅尔滤波器,计算它覆盖的频率带内所有频率成分的能量总和。这通常是通过将滤波器的响应与每个窗口的频谱进行点乘并求和来完成的。

取对数:
为了更贴合人耳对声音强度的感知,在计算出每个滤波器的能量后,通常会对这些能量值取对数。这一步增强了动态范围,并且使得频谱的表示更适合后续的音频处理和分析任务。

完成上述操作后,只需要绘制出梅尔频谱图即可

1.3.5 梅尔频谱完整代码示例

#创建一个由两个正弦波组成的简单合成信号,一个频率为 300 Hz,另一个频率为 600 Hz。
fs = 8000  # Sampling frequency
duration = 1.0  # seconds
t = np.linspace(0, duration, int(fs * duration), endpoint=False)
signal = 0.5 * np.sin(2 * np.pi * 300 * t) + 0.5 * np.sin(2 * np.pi * 600 * t)

#执行短时傅立叶变换(STFT)
frequencies, times, Zxx = stft(signal, fs=fs, window='hann', nperseg=256, noverlap=128)

#创建梅尔过滤器并应用,即使用 librosa 创建梅尔滤波器组并将其应用于从 STFT 获得的幅度谱。
n_mels = 64 #梅尔带数
mel_filters = librosa.filters.mel(sr=fs, n_fft=256, n_mels=n_mels)
mel_spectrogram = np.dot(mel_filters, np.abs(Zxx)) # Apply Mel filterbank

#取对数得到 log-Mel 频谱图
log_mel_spectrogram = np.log(mel_spectrogram + 1e-9)  # Add a small number to avoid log(0)

#绘制信号和 Log-Mel 频谱图
plt.figure(figsize=(12, 8))
# 绘制原本信号
plt.subplot(2, 1, 1)
plt.title("Original Signal")
plt.plot(t * 1000, signal)  # Ensure t is correctly sized
plt.xlabel("Time (ms)")
plt.ylabel("Amplitude")

# 绘制梅尔谱图
plt.subplot(2, 1, 2)
plt.title("Log-Mel Spectrogram")
plt.imshow(log_mel_spectrogram, aspect='auto', origin='lower', extent=[0, duration, 0, n_mels])
plt.xlabel("Time (s)")
plt.ylabel("Mel filter index")
plt.colorbar(label="Log-Magnitude")

plt.tight_layout()
plt.show()

最终生成的梅尔频谱如下所示:
在这里插入图片描述

二. Learn2Sing 2.0歌声转换算法详解

2.1 引入

AIGC席卷下, 语音合成, 语音转换一直是音频技术的关键核心技术。 语音合成的关键是学会目标人的音色, 并迁移到源目标上。 随着元宇宙的爆火, 虚拟人逐渐走到了荧幕前, 语音合成也从音色转换升级至目标人的音色克隆。 **即给定足够时长的目标人语音, 即可通过文本的方式生成用户需要的音频片段。**然而仅仅让虚拟人说话是不够的, 歌声是一个很好表现自己的方式, 歌声转唱就是典型的应用案例。 随着“ AI孙燕姿” 的成功出圈, 让用户可以链接粉丝和偶像产生互动感, 具有很强娱乐性, 除此之外, 歌声转唱可以为每个人提供个性化的音乐体验, 用户通过录制简单的一段说话音频, 就可以定制属于自己独特音色的歌手, 让不擅长唱歌的用户完成歌曲的演唱。 这就是:Singing Voice Conversion。

歌声转换( Singing voice conversion) 旨在保证歌唱内容的同时, 将音色从source speaker转换到 target speaker, 这将为音乐行业带来革命性的变化。 歌声转唱具有很强的娱乐性, 可以使目标歌手无需重新录制歌曲, 不仅能够节省大量的时间和金钱, 还能为艺术创作开辟新的艺术道路, 同时可以让每一个用户都能实现自己独特的音色唱歌, 商业前景和市场巨大。

2.2 过去研究的不足

2.2.1 依赖大量标识数据

最早的歌声生成模型是依靠大量已经标记的声音数据,即由专业歌手录制并标记的歌唱语料库,这需要使用 MusicXML 或 MIDI 文件来训练模型SVS 任务。**But,要知道我们最终的目的是在没有相关歌声数据的情况下也能为每个用户创建自己的歌声。**所以我们不应依靠大量标记好的数据。

2.2.2 Learn2Sing 1.0中出现的问题

Learn2Sing 1.0是作者之前尝试过的一个版本,是一种歌声合成模型。虽然Learn2Sing 1.0一定程度上减少了对参考音频的依赖,但是仍然存在诸多问题:

  • 音高预测的不准确:独立的基频(F0)预测模型由于训练数据有限,可能导致音高曲线不准确,从而影响最终声音的自然度和表现力。
  • 推理效率低:基于自回归解码器的方法需要逐帧预测梅尔频谱图,这使得推理过程变得缓慢。
  • 依赖参考音频:尽管进行了一些优化,但系统在一定程度上仍然需要参考音频,这限制了其在没有足够参考数据时的应用,尤其是在尝试合成新歌或高度表现力的歌声时。

2.3 Learn2Sing 2.0的破冰

长话短说,我们直接看Learn2Sing 2.0的整体机理:
在这里插入图片描述

Learn2Sing 2.0的工作原理是通过两个主要阶段来合成歌声,分别是生成中间表示和基于这些表示的最终梅尔频谱图的恢复
生成中间表示:

  1. 输入:该阶段接收的输入包括音素序列(phone sequence)、音高(pitch)和发言人信息(speaker information)。音素序列表示了语音的基本语音单位,音高提供了每个音素的音高信息,而发言人信息则允许模型捕捉到特定发言人的声音特征。
  2. 处理:首先,根据输入数据生成一个梅尔频谱图的平均值。这个平均化的过程发生在音素级别,即将与每个音素相关联的梅尔频谱图区域求平均,以形成一个更稳定和典型的表示形式。
  3. 上采样:生成的特征需要与原始音频的时间分辨率对齐。因此,这些特征将被上采样,以与平均梅尔频谱图对齐,为下一阶段的处理做准备。

最终梅尔频谱图的恢复:

  • 输入:这一阶段的输入是上一步生成的中间表示,加上额外的风格信息。这些风格信息可以是关于发言人是在说话还是在唱歌的信息,有助于调整最终输出以更好地符合目标风格。
  • 处理:使用基于扩散概率模型(DPM)的解码器来处理这些输入,逐步恢复和细化最终的梅尔频谱图。扩散概率模型(如GradTTS)是一种生成模型,能够处理含噪声的数据,并逐步去除噪声,恢复出清晰的数据表示。

2.3.1 使用到的扩散模型DPM

DPM是一种强大的建模工具,已被应用于语音合成和歌声合成(SVS)任务。
需要明确的是,DPM包含两个过程:前向扩散和逆向扩散(其实大多数扩散模型都有这两个过程)。前向扩散通过逐渐增加噪声来从真实数据获得一个可追踪的先验分布;逆向扩散则尝试还原出真实数据,通过去除噪声。
Song等人提出了一个统一的基于分数的DPM框架,然后将其应用于Grad-TTS的语音合成领域。也就是说,DPMGrad-TTS框架的核心所在。

  • 在Grad-TTS系统中,DPM的两个扩散过程被具体化为满足特定随机微分方程(SDE)的形式。
  • Grad-TTS不直接解逆向时间的SDE,而是使用一个普通微分方程(ODE)来进行逆过程的计算。
  • 通过估计梅尔频谱图的对数密度的梯度,Grad-TTS能够从文本预测出梅尔频谱图,然后逐步重建目标梅尔频谱图。

具体公式如下:
首先是前向扩散的过程:

d X t = 1 2 Σ − 1 ( μ − X t ) β t d t + β t d W t , t ∈ [ 0 , 1 ] d X_{t}=\frac{1}{2} \Sigma^{-1}\left(\mu-X_{t}\right) \beta_{t} d t+\sqrt{\beta_{t}} d W_{t}, t \in[0,1] dXt=21Σ1(μXt)βtdt+βt dWt,t[0,1]

  • Xt是时间t的数据状态。
  • μ 是数据的均值(通常是数据的起始状态或期望状态)。
  • βt是噪声程度,随时间变化的调度参数。
  • dWt是标准布朗运动(白噪声源)。
  • 此方程逐渐增加数据的噪声水平,使数据从初始状态X0随时间演变到更加随机的状态。

然后是逆向扩散过程:
d X t = ( 1 2 Σ − 1 ( μ − X t ) − ∇ log ⁡ p t ( X t ∣ X 0 ) ) β t d t + β t d W ~ t , t ∈ [ 0 , 1 ] \begin{array}{l}d X_{t}=\left(\frac{1}{2} \Sigma^{-1}\left(\mu-X_{t}\right)-\nabla \log p_{t}\left(X_{t} \mid X_{0}\right)\right) \beta_{t} d t +\sqrt{\beta_{t}} d \widetilde{W}_{t}, \quad t \in[0,1]\end{array} dXt=(21Σ1(μXt)logpt(XtX0))βtdt+βt dW t,t[0,1]

  • 最后一项 β t d W ~ t \sqrt{\beta_{t}} d \widetilde{W}_{t} βt dW t表示在逆向过程中,噪声被逐渐移除

利用常微分方程(ODE)来代替直接解决逆向时间的 SDE:
d X t = 1 2 ( μ − X t − s θ ( X t , μ , t ) ) β t d t d X_{t}=\frac{1}{2}\left(\mu-X_{t}-s_{\theta}\left(X_{t}, \mu, t\right)\right) \beta_{t} d t dXt=21(μXtsθ(Xt,μ,t))βtdt

  • s θ ( X t , μ , t ) s_{\theta}\left(X_{t}, \mu, t\right) sθ(Xt,μ,t)是一个评分函数,用于估计对数概率密度的梯度。这个函数是可学习的,它在推断阶段帮助逐步修正噪声数据 Xt ,使之逼近目标数据 μ。
  • βt控制着噪声的减少速度。
  • 通过调整评分函数和噪声调度,Grad-TTS 在推断阶段能够逐步从噪声状态重构目标梅尔频谱图。

我们有必要在这里梳理清楚模型的两个关键时期——训练阶段推断阶段
还是看上面那张图,在训练阶段,被更新参数的模块包括:

  1. 编码器Encoder:
    输入包括Speaker ID、Phoneme(音素)、和Pitch(音高)。
    这些输入通过编码器处理,得到声音的中间表示。这一步涉及到学习如何根据不 同的发音和音调来调整声音的特性。
  2. 长度调节器(Length Regulator):
    使用预测的持续时间(Predicted Duration)调整音节的长度,以符合真实的持续时间(Real Duration),另外要注意的是,Length Regulator起到了上采样的作用。
  3. 预测的梅尔频谱μ:
    从编码器输出得到预测的梅尔频谱图μ,并与真实的梅尔频谱图(Ground Truth μ)比较,计算均方误差(MSE Loss)。
  4. 扩散解码器(Diffusion Decoder):
    使用噪声时间t和扩散过程来从预测的梅尔频谱图μ生成噪声梅尔频谱Xt,再反向通过扩散过程逼近真实的梅尔频谱图X0,同样使用MSE Loss作为训练损失。


而在推断阶段,使用到的模块有(此时各模块参数冻结):

  • 使用预训练的评分模型 SDM:
    在推断阶段,预训练的评分模型(SDM)(这是在训练阶段训练好的)用于帮助精确调节生成的梅尔频谱,尽可能逼近真实的梅尔频谱图。
  • 最小化互信息(MI minimization):
    这通常在推断阶段进行,旨在减少不同模式间的相互信息,帮助模型更好地泛化,提高输出的多样性和自然性。
  • 样式嵌入(Style Embedding)和样式ID(Style ID):
    这些在推断过程中被用来调整输出以符合特定的声音风格和特性。
  • 生成预测的歌声X0:
    最终输出是预测的歌声梅尔频谱图 X0,这是通过逐步从带噪声的梅尔频谱Xt进行细化得到的。

总之,训练部分涉及构建和优化模型,使其能够从给定的输入生成准确的输出。推断部分则是实际应用训练好的模型,以生成符合用户期望的高质量声音输出。

2.3.2 Proposed Learn2Sing 2.0 Model

OK,我们知道了整体的流程,现在我们来把细节整理清楚。以下是几个比价关键的细节:

  • Encoder生成的是一个中间状态的梅尔谱图,即音素级平均梅尔频谱图μ。它不参与生成speaker音高即pitch特征!
  • speaker的音高特征是在扩散模型中主键恢复的。
  • 在同一音素内不存在不同的发音或唱歌风格,比如过载、颤音、准备期或音调波动,因为所有帧内的μ都是相同的。
  • 在文本到语音(TTS)系统中,经常会出现系统混淆speaker embedding和style embedding的情况。说话者嵌入(speaker embedding)旨在捕捉与特定说话者相关的特征,如音色和发音习惯;而风格嵌入(style embedding)则捕捉发音的风格,如情感表达、语调变化和语速。Learn2Sing 2.0 使用了vCLUB来解决这个问题(也就是互信息模块),其损失函数如下所示:
    L m i = 1 N 2 ∑ i = 1 N ∑ j = 1 N [ log ⁡ q θ ( s t y i ∣ s p k i ) − log ⁡ q θ ( s t y j ∣ s p k i ) ] \mathcal{L}_{\mathrm{mi}}=\frac{1}{N^{2}} \sum_{i=1}^{N} \sum_{j=1}^{N}\left[\log q_{\theta}\left(\boldsymbol{s t} \boldsymbol{y}_{i} \mid \boldsymbol{s p} \boldsymbol{k}_{i}\right)-\log q_{\theta}\left(\boldsymbol{s t} \boldsymbol{y}_{j} \mid \boldsymbol{s p} \boldsymbol{k}_{i}\right)\right] Lmi=N21i=1Nj=1N[logqθ(styispki)logqθ(styjspki)]
  • 第一项 log ⁡ q θ ( s t y i ∣ s p k i ) \log q_{\theta}\left(\boldsymbol{s t y}_{i} \mid \boldsymbol{s p k}_{i}\right) logqθ(styispki)是在给定第i个人的spk嵌入下,预测为i的风格的概率。
  • 第二项 log ⁡ q θ ( s t y j ∣ s p k i ) \log q_{\theta}\left(\boldsymbol{s t y}_{j} \mid \boldsymbol{s p k}_{i}\right) logqθ(styjspki)是在给定第i个人的spk嵌入下,预测为j的风格的概率。
    这两项的差值如果越大,意味着qθ误判的概率越大(即将spki误判为styi的概率较大),这显然不是我们所期待的,所以我们选择最小化这个损失。

其中qθ成为可学习的参数,它的更新方式是对数似然更新(如下所示,其实和上面这个损失函数就是照应的):
L ( θ ) = 1 N ∑ i = 1 N log ⁡ q θ ( s t y i ∣ s p k i ) \mathcal{L}(\theta)=\frac{1}{N} \sum_{i=1}^{N} \log q_{\theta}\left(\boldsymbol{s t y}_{i} \mid \boldsymbol{s p \boldsymbol { k } _ { i }}\right) L(θ)=N1i=1Nlogqθ(styispki)

总损失为:
L total  = L μ + L diff  + λ L m i \mathcal{L}_{\text {total }}=\mathcal{L}_{\mu}+\mathcal{L}_{\text {diff }}+\lambda \mathcal{L}_{m i} Ltotal =Lμ+Ldiff +λLmi
L μ \mathcal{L}_{\mu} Lμ是是预测的μ 和实际μ之间的均方误差损失, L diff  \mathcal{L}_{\text {diff }} Ldiff 是扩散误差, λ L m i \lambda \mathcal{L}_{m i} λLmi就是刚才所说的互信息损失,λ是一个超参系数。

2.3.3 Fast Maximum Likelihood Sampling Scheme

在采样也就是解码阶段,该模型使用的是固定步长一阶逆SDE求解器(目的是加速采样的速度,在保证速度的同时保证质量),旨在最大化前向扩散离散采样路径的似然性。具体来说,快速采样方案首先定义了以下值:
γ s , t = exp ⁡ ( − 1 2 ∫ s t β u d u ) , ϕ s , t = γ s , t 1 − γ 0 , s 2 1 − γ 0 , t 2 , ν s , t = γ 0 , s 1 − γ s , t 2 1 − γ 0 , t 2 , σ s , t 2 = ( 1 − γ 0 , s 2 ) ( 1 − γ s , t 2 ) 1 − γ 0 , t 2 , κ t , h = ν t − h , t ( 1 − γ 0 , t 2 ) γ 0 , t β t h − 1 ω t , h = ϕ t − h , t − 1 β t h + 1 + κ t , h 1 − γ 0 , t 2 − 1 2 , ( σ t , h ) 2 = σ t − h , t 2 \begin{array}{c}\gamma_{s, t}=\exp \left(-\frac{1}{2} \int_{s}^{t} \beta_{u} d u\right), \phi_{s, t}=\gamma_{s, t} \frac{1-\gamma_{0, s}^{2}}{1-\gamma_{0, t}^{2}}, \\\nu_{s, t}=\gamma_{0, s} \frac{1-\gamma_{s, t}^{2}}{1-\gamma_{0, t}^{2}}, \sigma_{s, t}^{2}=\frac{\left(1-\gamma_{0, s}^{2}\right)\left(1-\gamma_{s, t}^{2}\right)}{1-\gamma_{0, t}^{2}}, \\\kappa_{t, h}=\frac{\nu_{t-h, t}\left(1-\gamma_{0, t}^{2}\right)}{\gamma_{0, t} \beta_{t} h}-1 \\\omega_{t, h}=\frac{\phi_{t-h, t}-1}{\beta_{t} h}+\frac{1+\kappa_{t, h}}{1-\gamma_{0, t}^{2}}-\frac{1}{2},\left(\sigma_{t, h}\right)^{2}=\sigma_{t-h, t}^{2}\end{array} γs,t=exp(21stβudu),ϕs,t=γs,t1γ0,t21γ0,s2,νs,t=γ0,s1γ0,t21γs,t2,σs,t2=1γ0,t2(1γ0,s2)(1γs,t2),κt,h=γ0,tβthνth,t(1γ0,t2)1ωt,h=βthϕth,t1+1γ0,t21+κt,h21,(σt,h)2=σth,t2
这部分定义了一系列参数和方程,这些都是在执行扩散过程的逆过程中用来计算每一步中所需的具体数值。这些数值和方程是为了最大化在正向扩散过程中离散样本路径的似然概率。
在这里插入图片描述
并采用以下类反向SDE求解:
X t − h = X t + β t h ( ( 1 2 + ω t , h ) ( X t − μ ) + ( 1 + κ t , h ) s θ ( X t , μ , s t y , t ) ) + σ t , h ξ t \begin{array}{r}X_{t-h}=X_{t}+\beta_{t} h\left(\left(\frac{1}{2}+\omega_{t, h}\right)\left(X_{t}-\mu\right)\right. \\\left.+\left(1+\kappa_{t, h}\right) s_{\theta}(X t, \mu, \boldsymbol{s t y}, t)\right)+\sigma_{t, h} \xi_{t}\end{array} Xth=Xt+βth((21+ωt,h)(Xtμ)+(1+κt,h)sθ(Xt,μ,sty,t))+σt,hξt
在这里插入图片描述

2.4 效果展示

Teacher声音
Student原始声音
Student经Teacher指导后合成后的声音

好了,希望以上内容可以帮到大家,未来一起进步!码字不易,还请点赞收藏支持一下叭

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

韩顺平0基础学Java——第8天

p155-168 数组(第六章) 数组可以存放多个同一类型的数据,数组也是一种数据类型(引用类型)。 即,数组就是一组数据~ 例:double [] hens {1,2,3,4,5,6}; 新建了一组鸡,里面有6个。…

代码随想录算法训练营第36期DAY18

DAY18 二叉树的层序遍历 102二叉树的层序遍历 “队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。” 二叉树层序遍历模版: /** * Definition for a binary tree node. * struct TreeNode { *…

PostgreSQL的学习心得和知识总结(一百四十二)|深入理解PostgreSQL数据库数据库之 Continuous Integration

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…

办公技巧之合集文档 拆分_word

问题 如何将文档合集拆分为单独文档。 操作步骤 软件 word 365 原理简述: 在 word 大纲视图下,通过一级标题确定子文档范围,然后导出即可。 文档结构 从下图可见,文档结构为已建立大纲级别的文档,如果没有建立&a…

每日一题——力扣27. 移除元素(举一反三)

题目链接:https://leetcode.cn/problems/remove-element/description/ 菜鸡写法: // 函数定义,移除数组nums中所有值为val的元素,并返回新的数组长度 int removeElement(int* nums, int numsSize, int val) {// 如果数组长度为…

Steam游戏搬砖,不说破万,月入5K没问题

steam游戏搬砖项目的玩法就是打汇率差,在steam平台购买道具,挂在网易buff上出售,通过汇率差盈利。一天交易几百美金的道具,大概能搞到200块左右的利润,而且平台是支持这样交易的,还很稳定。目前最主流的游戏…

设计模式1——初步认识篇

设计模式1——初步认识篇 一、先让我们浅聊一下面向对象和设计模式。 说起设计模式,我第一次听到它,是在学习面向对象的时候。那么什么是面向对象,什么是设计模式,而且设计模式和面向对象又有什么关系呢? 1、什么是面…

im8mm 网络卡死 Rx packets:1037578 errors:66 dropped:0 overruns:66 frame:0

1:网络接收数据包异常 2:问题复现 问题在进行网络数据包同吞吐量测试的时候出现的。同时发现,在使用iperf2测试时,是不会出现网络中断卡死的情况,使用 iperf3时才会出现此问题 指令(下面的指令运行在PC2上面&#xff…

十二种网络威胁防护方案

一、SQL注入 SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任…

kali linux更新卡在libc6:amd64 (2.37-15)

适配于linux的windows子系统,wsl2,安装kali linux,运行 sudo apt update 卡在:Setting up libc6:amd64 (2.37-15) … 关机重启、重新修复执行也不行 解决办法:kill当前apt进程或者关机重启kali-linux,然后执行: ssudo mv /usr/sbin/telinit /usr/sbin/telinit.baksu…

安装docker镜像nginx1.26.0版本,与删除docker容器【灵异事件】

为了http3 的这个模块,所以需要升级nginx的版本,需要nginx1.26.0才有 –with-http_v3_module 这个模块 为什么记录一下?因为觉得奇怪 1:删除nginx镜像,显示镜像还被某个容器在使用 luichunluichun:~$ docker rmi ng…

数电——集成计数器

分析 (1)74161 4位同步(cp相同)二进制,模16(2的4次方) 逻辑符号 端口 D0,D1,D2,D3为输入信号 Q0,Q1,Q2,Q3为输出信号 RCO输出进位标志:记满16个数后,输出1 P,T 控…

番外篇 | 利用PyQt5+YOLOv5来搭建目标检测系统(附可视化界面+功能介绍+源代码)

前言:Hello大家好,我是小哥谈。PyQt5是一个Python绑定的Qt库,是用于创建图形用户界面(GUI)和其他应用程序组件的工具包。PyQt5提供了许多GUI元素,如按钮、文本框、标签等,也提供了许多Qt的功能,如网络、数据库、XML等。通过PyQt5可以在Python中使用Qt的丰富功能和强大的工…

远程桌面连接不上怎么连服务器,原因是什么?如何解决?

远程桌面连接不上怎么连服务器,原因是什么?如何解决? 面对远程桌面连接不上的困境,我们有办法! 当你尝试通过远程桌面连接服务器,但遭遇连接失败的挫折时,不要慌张。这种情况可能由多种原因引起…

Python运维之协程

目录 一、定义协程 二、并发 三、异步请求 协程是一种轻量级的线程,它通过保存和恢复寄存器上下文和栈来实现调度切换,从而保留函数执行的状态。 这种机制使得协程在处理I/O密集型任务时效率较高,因为它们可以在I/O操作期间让出CPU&#…

【触摸案例-手势解锁案例-错误的样式 Objective-C语言】

一、然后呢,我们再来说一下这个错误的样式 1.首先,在我们的示例程序里边,我现在来连一条线,一撒手的时候, 它先出来一个,红色的按钮的样式,那么这个时候呢,实际上,是在设置另外一种状态,给按钮的另外一种状态,再去设置另外一张红色的图片,然后呢,再去切换成那一种…

C++青少年简明教程:C++中的常量、变量、表达式和语句

C青少年简明教程:C中的常量、变量、表达式和语句 在C编程中,常量、变量、表达式和语句是基本的编程概念。 常量(Constants):在程序中具有固定值的数据称为常量。常量可以是字面值,如整数、浮点数、字符或…

信息系统项目管理基础

目录 一、项目管理概论 1、定义 2、项目管理的十二原则 3、SMART原则 4、项目经理 5、项目的生命周期 二、项目立项管理 1、项目启动过程 三、项目整合管理 1、管理基础 2、项目整合管理过程 ①制定项目章程 ②制定项目管理计划 ③指导与管理项目工作 ④管理项目…

河南大学大礼堂火灾事故引发安防监控对智能分析技术应用的思考

一、方案背景 2024年5月2日,在修缮施工期间的河南大学河南留学欧美预备学校旧址大礼堂发生火情。现场航拍画面显示,大礼堂经过火灾,房顶已经基本坍塌,被火烧过的建筑呈焦黑状。 公开资料显示,大礼堂属河南留学欧美预…

【栈】Leetcode 比较含退格的字符串

题目讲解 844. 比较含退格的字符串 算法讲解 使用栈模拟,但遇到#字符就让栈顶元素出栈,但是在写的过程中有两点需要注意:当#出现在第一个位置,需要特殊处理一下;当栈为空的时候,还出现#字符需要特殊处理…