当前位置: 首页 > news >正文

离散傅里叶变换(Discrete Fourier Transform, DFT)及其在图像处理中的应用

离散傅里叶变换(DFT)及其在图像处理中的应用

什么是离散傅里叶变换?

离散傅里叶变换(Discrete Fourier Transform, DFT)是一种强大的数学工具,用于将离散信号从时域(或空间域)转换到频域。它可以将一个有限长度的信号分解成一系列正弦和余弦波的组合,每个波都有特定的频率、幅度和相位。DFT 的核心思想来源于傅里叶分析,但它适用于离散信号,是数字信号处理和图像处理的基础。

DFT 的数学定义如下:对于长度为 ( N N N) 的一维信号 ( x [ n ] x[n] x[n]),其离散傅里叶变换为:

X [ k ] = ∑ n = 0 N − 1 x [ n ] e − j 2 π N n k , k = 0 , 1 , . . . , N − 1 X[k] = \sum_{n=0}^{N-1} x[n] e^{-j \frac{2\pi}{N} nk}, \quad k = 0, 1, ..., N-1 X[k]=n=0N1x[n]ejN2πnk,k=0,1,...,N1

其中:

  • ( X [ k ] X[k] X[k]) 是频域中的复数系数,表示频率分量;
  • ( x [ n ] x[n] x[n]) 是时域或空间域的输入信号;
  • ( e − j 2 π N n k e^{-j \frac{2\pi}{N} nk} ejN2πnk) 是复指数函数,包含正弦和余弦成分;
  • ( j j j) 是虚数单位。

反变换(IDFT)可以将频域信号转换回时域:

x [ n ] = 1 N ∑ k = 0 N − 1 X [ k ] e j 2 π N n k x[n] = \frac{1}{N} \sum_{k=0}^{N-1} X[k] e^{j \frac{2\pi}{N} nk} x[n]=N1k=0N1X[k]ejN2πnk

DFT 有什么用?

DFT 的用途非常广泛,尤其是在信号处理和图像处理领域。以下是一些主要应用:

  1. 频谱分析:分析信号的频率成分,例如音频信号中的音调或图像中的纹理。
  2. 滤波:通过修改频域系数实现低通、高通或带通滤波,去除噪声或增强特定特征。
  3. 图像压缩:提取主要频率成分,丢弃次要信息(如 JPEG 中的 DCT)。
  4. 卷积加速:利用快速傅里叶变换(FFT)实现高效卷积运算,广泛应用于图像处理和深度学习。

在图像处理中,二维 DFT 特别重要,因为图像本质上是一个二维信号。通过分析图像的频域特性,我们可以进行去噪、边缘检测、纹理分析等操作。

二维 DFT 在图像处理中的应用

对于一张二维图像 ( f ( x , y ) f(x, y) f(x,y))(大小为 ( M × N M \times N M×N)),二维 DFT 的公式为:

F ( u , v ) = ∑ x = 0 M − 1 ∑ y = 0 N − 1 f ( x , y ) e − j 2 π ( u x M + v y N ) F(u, v) = \sum_{x=0}^{M-1} \sum_{y=0}^{N-1} f(x, y) e^{-j 2\pi \left( \frac{ux}{M} + \frac{vy}{N} \right)} F(u,v)=x=0M1y=0N1f(x,y)ej2π(Mux+Nvy)

其中:

  • ( F ( u , v ) F(u, v) F(u,v)) 是频域系数,( u u u) 和 ( v v v) 分别表示水平和垂直方向的频率;
  • ( f ( x , y ) f(x, y) f(x,y)) 是图像像素值。

反变换为:

f ( x , y ) = 1 M N ∑ u = 0 M − 1 ∑ v = 0 N − 1 F ( u , v ) e j 2 π ( u x M + v y N ) f(x, y) = \frac{1}{MN} \sum_{u=0}^{M-1} \sum_{v=0}^{N-1} F(u, v) e^{j 2\pi \left( \frac{ux}{M} + \frac{vy}{N} \right)} f(x,y)=MN1u=0M1v=0N1F(u,v)ej2π(Mux+Nvy)

在图像处理中,二维 DFT 的结果是一个复数矩阵,其幅度谱(Magnitude Spectrum)通常用于可视化:

∣ F ( u , v ) ∣ = Re ( F ( u , v ) ) 2 + Im ( F ( u , v ) ) 2 |F(u, v)| = \sqrt{\text{Re}(F(u, v))^2 + \text{Im}(F(u, v))^2} F(u,v)=Re(F(u,v))2+Im(F(u,v))2

以下是一个 Python 代码示例,展示如何对图像应用二维 DFT 并可视化频谱。


Python 代码实现(二维 DFT)

import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft2, ifft2, fftshift# Load and process an image
def load_image():# Create a simple synthetic image (grayscale)image = np.zeros((256, 256))image[100:156, 100:156] = 255  # Add a white square in the centerreturn image# Apply 2D DFT and visualize
def apply_dft(image):# Compute 2D DFTdft = fft2(image)# Shift the zero frequency component to the centerdft_shifted = fftshift(dft)# Compute magnitude spectrum (log scale for better visualization)magnitude_spectrum = np.log(1 + np.abs(dft_shifted))# Reconstruct the image using inverse DFTreconstructed_image = np.abs(ifft2(dft))return magnitude_spectrum, reconstructed_image# Main function
if __name__ == "__main__":# Load imageoriginal_image = load_image()# Apply DFTmagnitude_spectrum, reconstructed_image = apply_dft(original_image)# Visualizationplt.figure(figsize=(12, 4))plt.subplot(1, 3, 1)plt.imshow(original_image, cmap='gray')plt.title("Original Image")plt.axis('off')plt.subplot(1, 3, 2)plt.imshow(magnitude_spectrum, cmap='gray')plt.title("Magnitude Spectrum (Log Scale)")plt.axis('off')plt.subplot(1, 3, 3)plt.imshow(reconstructed_image, cmap='gray')plt.title("Reconstructed Image")plt.axis('off')plt.tight_layout()plt.show()
代码说明
  1. load_image:生成一个简单的 256x256 灰度图像,中间有一个白色方块,用于测试。
  2. apply_dft
    • 使用 scipy.fft.fft2 计算二维 DFT。
    • 使用 fftshift 将零频分量移到频谱中心,便于可视化。
    • 计算幅度谱并取对数(np.log(1 + np.abs())),增强显示效果。
    • 使用 ifft2 进行逆变换,重构图像。
  3. 可视化:展示原始图像、频谱图和重构图像。
运行结果

在这里插入图片描述

运行代码后,你会看到:

  • 原始图像:一个带有白色方块的灰度图像。
  • 幅度谱:频谱图显示低频分量集中在中心,高频分量分布在边缘,形成对称图案。
  • 重构图像:通过逆 DFT 恢复的图像,应与原始图像几乎一致。

DFT 与 DCT 的区别

关于DCT,可以参考笔者的另一篇博客:离散余弦变换(Discrete Cosine Transform, DCT):从数学到图像压缩的魔法(Python代码实现)

离散傅里叶变换(DFT)和离散余弦变换(DCT)都是频域变换工具,但在原理和应用上有显著差异:

  1. 数学基础

    • DFT:使用复指数函数 ( e − j θ e^{-j\theta} ejθ),输出是复数(包含幅度和相位),能完整表示信号的频率和相位信息。
    • DCT:仅使用实数的余弦函数,输出是实数,专注于信号的幅度信息,相位信息被简化。
  2. 边界条件

    • DFT:假设信号是周期性的,因此在边界处可能引入伪影(称为“周期性边界效应”)。
    • DCT:假设信号在边界处通过镜像对称扩展,减少边界伪影,特别适合图像处理。
  3. 能量集中

    • DCT:将信号能量更多地集中在低频系数中,这使得它在压缩(如 JPEG)中更高效。
    • DFT:能量分布较均匀,不如 DCT 集中,但在频谱分析中更全面。
  4. 计算复杂度

    • DFT:直接计算复杂度为 ( O ( N 2 ) O(N^2) O(N2)),但通过快速傅里叶变换(FFT)可降至 (O(N \log N)),适用于大尺寸信号。
    • DCT:复杂度也为 ( O ( N 2 ) O(N^2) O(N2)),但在图像压缩中通常处理小块(如 8x8),实际计算量较小。
  5. 应用场景

    • DFT:更适合需要完整频率信息和相位的场景,如信号分析、滤波、卷积运算。
    • DCT:专为数据压缩设计(如 JPEG、MPEG),因其能量集中特性在有损压缩中占优。
总结

离散傅里叶变换(DFT)是一个通用的信号分析工具,在图像处理中通过二维 DFT 可以揭示图像的频率特性,适用于滤波、去噪等任务。而 DCT 则是图像压缩的“秘密武器”,通过能量集中和实数运算优化了压缩效率。选择 DFT 还是 DCT,取决于你的具体需求:如果你需要全面的频域分析,DFT 是首选;如果目标是高效压缩,DCT 更胜一筹。

希望这篇博客和代码能让你更好地理解 DFT 及其与 DCT 的差异!如果有疑问,欢迎留言讨论。

你的疑问非常好!关于频谱图中“低频分量集中在中心且很亮”的现象,以及为什么亮的不是高频分量,这涉及到频域表示的特点和可视化时的处理方式。下面我来详细解答:


为什么频谱图中低频分量集中在中心且很亮?

1. 频谱图的中心化(fftshift 的作用)

在代码中,我们使用了 fftshift 函数对二维 DFT 的结果进行了移位处理。原始的 DFT 输出 ( F ( u , v ) F(u, v) F(u,v)) 将零频分量(即频率为 0 的分量)放在矩阵的左上角 ( ( 0 , 0 ) (0, 0) (0,0)) 位置。但在实际可视化时,为了更直观地观察频率分布,我们通常将零频分量移到频谱图的中心。这种移位操作使得:

  • 低频分量(接近零频的频率)集中在频谱图的中心。
  • 高频分量(较大的频率)分布在边缘。

因此,在你看到的频谱图中,中心区域代表低频分量,而边缘区域代表高频分量。

2. 亮度与幅度谱的关系

频谱图显示的是幅度谱 ( ∣ F ( u , v ) ∣ |F(u, v)| F(u,v)),即 DFT 复数系数的模(magnitude),计算公式为:

∣ F ( u , v ) ∣ = Re ( F ( u , v ) ) 2 + Im ( F ( u , v ) ) 2 |F(u, v)| = \sqrt{\text{Re}(F(u, v))^2 + \text{Im}(F(u, v))^2} F(u,v)=Re(F(u,v))2+Im(F(u,v))2

为了让幅度谱的可视化更清晰,代码中还对幅度取了对数:

magnitude_spectrum = log ⁡ ( 1 + ∣ F ( u , v ) ∣ ) \text{magnitude\_spectrum} = \log(1 + |F(u, v)|) magnitude_spectrum=log(1+F(u,v))

  • 低频分量为什么亮?
    在图像中,低频分量通常对应平滑区域或整体亮度变化(例如大块的白色或黑色区域)。这些区域的能量(幅度)往往很大,因为它们占据了图像的主要内容。在你的示例图像中,白色方块是一个较大的均匀区域,其能量集中在低频部分,因此中心区域的幅度值很高。取对数后,这些高幅度值在灰度图中表现为“很亮”。

  • 高频分量为什么不亮?
    高频分量对应图像中的细节、边缘或快速变化的部分(例如白色方块的边界)。这些分量的幅度通常较小,因为细节部分的能量分布较分散,且在图像中占的比例较低。即使某些高频分量的幅度可能不小,取对数后它们的值也被压缩,不如低频分量突出,因此边缘区域显得较暗。

3. 为什么亮的不是高频?

疑问:“亮的一般不是高频吗?”
这可能是因为在某些直观理解中,高频分量与“尖锐”或“显著”的边缘相关,容易让人觉得它们应该很“亮”。但在频谱图中,亮度直接反映的是幅度的大小,而不是频率的高低:

  • 图像特性决定能量分布:对于大多数自然图像或简单图像(如你的白色方块示例),低频分量包含大部分能量,因为它们描述了图像的主要结构。而高频分量的能量通常较少,除非图像充满了密集的细节或噪声。
  • 对数缩放的影响:未经对数缩放的幅度谱动态范围很大,低频分量可能比高频分量高出几个数量级。如果直接显示原始幅度谱,低频的亮度会过于强烈,其他部分几乎不可见。取对数是为了平衡这种差异,让高频分量也能被看到,但低频的高幅度仍然主导了亮度。

用代码验证亮度的来源

为了进一步说明,我们可以修改代码,观察不同图像的频谱图,验证低频和高频的亮度分布。以下是扩展代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft2, ifft2, fftshift# Create a synthetic image with a white square (low frequency dominant)
def load_low_freq_image():image = np.zeros((256, 256))image[100:156, 100:156] = 255  # White square in the centerreturn image# Create a synthetic image with high-frequency details (checkerboard pattern)
def load_high_freq_image():image = np.zeros((256, 256))for i in range(256):for j in range(256):if (i // 16 + j // 16) % 2 == 0:  # Checkerboard patternimage[i, j] = 255return image# Apply 2D DFT and visualize
def apply_dft(image):dft = fft2(image)dft_shifted = fftshift(dft)magnitude_spectrum = np.log(1 + np.abs(dft_shifted))reconstructed_image = np.abs(ifft2(dft))return magnitude_spectrum, reconstructed_image# Main function
if __name__ == "__main__":# Test two imageslow_freq_image = load_low_freq_image()  # Low frequency dominanthigh_freq_image = load_high_freq_image()  # High frequency dominant# Apply DFT to bothlow_freq_spectrum, low_freq_reconstructed = apply_dft(low_freq_image)high_freq_spectrum, high_freq_reconstructed = apply_dft(high_freq_image)# Visualizationplt.figure(figsize=(12, 8))plt.subplot(2, 3, 1)plt.imshow(low_freq_image, cmap='gray')plt.title("Low Frequency Image")plt.axis('off')plt.subplot(2, 3, 2)plt.imshow(low_freq_spectrum, cmap='gray')plt.title("Magnitude Spectrum (Low Freq)")plt.axis('off')plt.subplot(2, 3, 3)plt.imshow(low_freq_reconstructed, cmap='gray')plt.title("Reconstructed Image (Low Freq)")plt.axis('off')plt.subplot(2, 3, 4)plt.imshow(high_freq_image, cmap='gray')plt.title("High Frequency Image")plt.axis('off')plt.subplot(2, 3, 5)plt.imshow(high_freq_spectrum, cmap='gray')plt.title("Magnitude Spectrum (High Freq)")plt.axis('off')plt.subplot(2, 3, 6)plt.imshow(high_freq_reconstructed, cmap='gray')plt.title("Reconstructed Image (High Freq)")plt.axis('off')plt.tight_layout()plt.show()
运行结果分析

在这里插入图片描述

  1. 低频主导图像(白色方块)

    • 频谱图中心很亮,因为白色方块的均匀区域贡献了大量低频能量。
    • 边缘较暗,高频分量(方块边界)的能量较少。
  2. 高频主导图像(棋盘格图案)

    • 频谱图中亮度分布到远离中心的位置,形成离散的亮点,对应棋盘格的高频周期性变化。
    • 中心(低频)不再是最亮的区域,因为图像缺少大范围平滑结构。

总结

频谱图中“亮”的区域反映的是幅度的大小,而幅度的大小取决于图像的能量分布:

  • 低频分量亮:在你的原始例子中,低频分量因白色方块的平滑区域而具有高幅度,因此中心很亮。
  • 高频分量暗:高频分量的能量通常较分散,且幅度较小,在对数缩放下不突出。
  • 亮的不是高频的误解:高频分量可能在边缘或细节丰富的图像中更显著,但在典型图像中,低频分量往往占主导地位。

如果你对特定图像的频谱有疑问,可以提供图像或描述,我可以帮你进一步分析!

为什么频谱图通常只显示幅度谱 ( ∣ F ( u , v ) ∣ |F(u, v)| F(u,v)),而相位谱往往被忽略?


什么是幅度谱和相位谱?

在二维离散傅里叶变换(DFT)中,输出 ( F ( u , v ) F(u, v) F(u,v)) 是一个复数矩阵,每个元素可以表示为:

F ( u , v ) = Re ( F ( u , v ) ) + j ⋅ Im ( F ( u , v ) ) F(u, v) = \text{Re}(F(u, v)) + j \cdot \text{Im}(F(u, v)) F(u,v)=Re(F(u,v))+jIm(F(u,v))

其中:

  • ( Re ( F ( u , v ) ) \text{Re}(F(u, v)) Re(F(u,v))) 是实部;
  • ( Im ( F ( u , v ) ) \text{Im}(F(u, v)) Im(F(u,v))) 是虚部。

我们可以将其转换为极坐标形式:

F ( u , v ) = ∣ F ( u , v ) ∣ e j ϕ ( u , v ) F(u, v) = |F(u, v)| e^{j \phi(u, v)} F(u,v)=F(u,v)ejϕ(u,v)

  • 幅度谱 ( ∣ F ( u , v ) ∣ |F(u, v)| F(u,v)):
    ∣ F ( u , v ) ∣ = Re ( F ( u , v ) ) 2 + Im ( F ( u , v ) ) 2 |F(u, v)| = \sqrt{\text{Re}(F(u, v))^2 + \text{Im}(F(u, v))^2} F(u,v)=Re(F(u,v))2+Im(F(u,v))2
    表示每个频率分量的强度或能量大小。

  • 相位谱 ( ϕ ( u , v ) \phi(u, v) ϕ(u,v)):
    ϕ ( u , v ) = arctan ⁡ ( Im ( F ( u , v ) ) Re ( F ( u , v ) ) ) \phi(u, v) = \arctan\left(\frac{\text{Im}(F(u, v))}{\text{Re}(F(u, v))}\right) ϕ(u,v)=arctan(Re(F(u,v))Im(F(u,v)))
    表示每个频率分量的相位角,反映信号在时间或空间上的偏移。


为什么频谱图通常只显示幅度谱?

1. 幅度谱直接反映能量分布

幅度谱 ( ∣ F ( u , v ) ∣ |F(u, v)| F(u,v)) 表示每个频率分量的强度,直接对应于信号的能量分布。在图像处理和信号分析中,我们通常关心:

  • 哪些频率分量占主导地位(例如低频的平滑区域还是高频的边缘);
  • 信号的频率特性如何(例如是否有噪声或特定模式)。

幅度谱提供了直观的“强度图”,可以快速判断信号的主要成分。例如:

  • 在你的白色方块图像中,幅度谱中心的亮点表明低频分量占主导;
  • 在噪声图像中,高频分量可能更显著。

相比之下,相位谱 ( ϕ ( u , v ) \phi(u, v) ϕ(u,v)) 是一个角度值(通常在 ( [ − π , π ] [- \pi, \pi] [π,π]) 范围内),它的数值没有直接的物理意义(如能量或强度),可视化后往往是一片杂乱的图案,不易直观解读。

2. 可视化难度
  • 幅度谱:取对数后(如 ( log ⁡ ( 1 + ∣ F ( u , v ) ∣ ) \log(1 + |F(u, v)|) log(1+F(u,v)))),幅度谱的值被压缩到一个合理的范围,便于用灰度图或彩色图显示,人类视觉系统能轻松分辨。
  • 相位谱:相位值是周期性的角度(如 ( − π -\pi π) 到 ( π \pi π)),直接显示时会形成复杂的跳跃图案(由于相位的周期性,可能出现不连续的边界)。即使映射到灰度值,也很难看出规律,除非进行特殊处理(如解缠绕或平滑),但这增加了分析复杂性。
3. 应用场景的侧重点

在许多实际应用中,幅度谱已经足以满足需求:

  • 图像压缩:如 JPEG 使用 DCT,只关心幅度信息来量化系数,相位被忽略。
  • 滤波:设计低通或高通滤波器时,主要修改幅度谱(如削弱高频分量),相位通常保持不变。
  • 频谱分析:检查信号的频率分布时,幅度谱直接给出答案。

相位谱虽然包含信息,但在这些场景下不是首要关注的,因为它对最终结果的感知影响较小(后面会详细解释)。


相位谱的作用是什么?为什么不常关心?

相位谱的作用

相位谱 ( ϕ ( u , v ) \phi(u, v) ϕ(u,v)) 描述了每个频率分量在空间或时间上的相对位置或偏移。换句话说,它决定了信号的“形状”或“结构”,而幅度谱决定了“强度”。在图像中:

  • 幅度谱:控制每个频率分量的大小,影响图像的对比度和能量分布。
  • 相位谱:控制频率分量的排列方式,影响图像的空间结构(如边缘的位置、物体的轮廓)。

一个经典实验可以说明两者的作用:将两张图像的幅度谱和相位谱互换,然后用逆 DFT 重构:

  • 用图像 A 的幅度谱 + 图像 B 的相位谱:重构图像更像图像 B。
  • 用图像 B 的幅度谱 + 图像 A 的相位谱:重构图像更像图像 A。

这表明相位谱对图像的视觉结构(可识别性)至关重要,而幅度谱更多影响亮度和对比度。

为什么不常关心相位谱?
  1. 人类视觉对相位的敏感度较低
    人眼对图像的整体结构(由相位决定)非常敏感,但对相位的微小扰动不敏感。例如:

    • 如果幅度谱保持不变,轻微改变相位谱,图像仍可识别。
    • 如果相位谱保持不变,改变幅度谱(如滤波),图像的感知变化更明显(如变模糊或变清晰)。
      在压缩或滤波中,丢弃或修改部分相位信息对视觉影响较小,因此相位常被忽略。
  2. 相位信息难以处理和利用

    • 相位谱的周期性和跳跃性使其难以直接操作。例如,滤波时修改相位可能引入伪影(如振铃效应),而修改幅度更直观。
    • 在压缩中(如 JPEG),相位信息被 DCT 简化(DCT 是实数变换,不保留相位),但仍能重构可接受的图像。
  3. 计算和存储成本
    DFT 输出是复数,包含幅度和相位需要双倍存储空间(实部和虚部)。而在许多应用中,只保留幅度谱即可完成任务(如频谱分析或压缩),省去了存储和处理相位的开销。


两者结合不是更好吗?

理论上,幅度谱和相位谱结合确实能完整描述信号,因为:

  • 幅度谱:提供频率分量的强度;
  • 相位谱:提供频率分量的空间排列。

完整的 DFT 重构(使用 ( F ( u , v ) F(u, v) F(u,v)) 的实部和虚部)需要两者结合,否则无法准确恢复原始信号。然而,在实践中:

  • 特定任务不需要完整信息:如频谱分析只看幅度,压缩只用幅度简化计算。
  • 相位的重要性因应用而异:在信号传输或某些逆问题(如相位检索)中,相位至关重要,但在图像可视化或压缩中,幅度往往足够。

总结

  • 为什么只显示幅度谱? 因为它直观反映能量分布,易于可视化和分析,满足大多数应用需求。
  • 为什么不常关心相位谱? 因为相位对视觉感知的影响不如幅度明显,且处理复杂,在压缩或滤波中常被简化。
  • 两者结合更好吗? 是的,在需要完整信号重构或特定任务(如相位检索)时,相位不可或缺。但在图像处理的常见场景中,幅度谱已足够实用。

希望这个解答和代码能让你更清楚地理解幅度谱和相位谱的角色!

后记

2025年3月3日15点58分于上海,在grok3大模型辅助下完成。

相关文章:

离散傅里叶变换(Discrete Fourier Transform, DFT)及其在图像处理中的应用

离散傅里叶变换(DFT)及其在图像处理中的应用 什么是离散傅里叶变换? 离散傅里叶变换(Discrete Fourier Transform, DFT)是一种强大的数学工具,用于将离散信号从时域(或空间域)转换…...

两周学习安排

日常安排 白天 看 MySQL实战45讲,每日一讲 看 图解设计模式 每天1-2道力扣算法题(难度中等以上) 每天复习昨天的单词,记20个单词,写一篇阅读 晚上 写服创项目 每日产出 MySQL实战45讲 读书笔记 设计模式 读书笔…...

vscode通过ssh远程连接(linux系统)不能跳转问题

1.问题描述 unbantu中的vscode能够通过函数跳转到函数定义,而windows通过ssh连接unbantu的vscode却无法跳转 2.原因: 主要原因是这里缺少插件,这里是unbantu给主机的服务器,与ubantu本地vscode插件相互独立,能否跳转…...

eMMC存储器详解(存储区域结构、EXT_CSD[179]、各分区介绍、主要引脚、命令格式与类型等)

读本篇博文所需要的先行知识 关于芯片内部的ROM的作用、工作原理的介绍,链接如下: https://blog.csdn.net/wenhao_ir/article/details/145969584 eMMC的物理结构、特点、用途 这个标题的相关内容见我的另一篇博文,博文链接如下&#xff1a…...

洛谷 P11830 省选联考2025 幸运数字 题解

题意 小 X 有 n n n 个正整数二元组 ( a i , b i ) ( 1 ≤ i ≤ n ) (a_i, b_i) (1 \leq i \leq n) (ai​,bi​)(1≤i≤n)。他将会维护初始为空的可重集 S S S,并对其进行 n n n 轮操作。第 i ( 1 ≤ i ≤ n ) i (1 \leq i \leq n) i(1≤i≤n) 轮操作中&#…...

win11编译pytorchaudio cuda128版本流程

1. 前置条件 本篇续接自 win11编译pytorch cuda128版本流程,阅读前请先参考上一篇配置环境。 访问https://kkgithub.com/pytorch/audio/archive/refs/tags/v2.6.0.tar.gz下载源码,下载后解压; 2. 编译 在visual studio 2022安装目录下查找…...

JAVA面经2

ConcurrentHashMap 并发程序出现问题的根本原因 线程池 线程池的执行原理(核心参数) 线程池的常见阻塞队列 ArrayBlockingQueue插入和删除数据,只采用了一个lock,而LinkedBlockingQueue则是在插入和删除分别采用了putLock和takeL…...

NLP学习记录十一:位置编码

目录 一、位置编码的意义 二、位置编码方法 三、代码实现 一、位置编码的意义 在标准的注意力机制中,每个查询都会关注所有的键-值对并生成一个注意力输出,模型并没有考虑到输入序列每个token的顺序关系。 以["我&qu…...

CF 886A.ACM ICPC(Java实现)

题目分析 输入6个值,判断某三个值的和能够等于另外三个值的和 思路分析 首先判断总和是不是一个偶数,如果不是就“NO”。由于小何同学算法不好,只能使用三层for循环强行判断某三个值是否能等于总和的一半,可以就“YES”。 代码 …...

【音视频】H265解码Nalu后封装rtp包

概述 基于ZLM流媒体框架以及简单RTSP服务器开源项目分析总结,相关源码参考以下链接 H265-rtp提取Nalu逻辑 通过rtsp流地址我们可以获取视频流中的多个rtp包,其中每个RTP包中又会包含一个或者多个Nalu,将其提取处理 总体逻辑分析 核心逻辑在…...

Linux -- I/O接口,文件标识符fd、file结构体、缓冲区、重定向、简单封装C文件接口

一、理解文件 狭隘理解(传统视角) 聚焦物理存储:文件特指存储在磁盘等外存设备上的二进制数据集合输入输出特性: 写入文件:CPU 通过总线将数据输出到磁盘读取文件:磁盘通过 DMA 将数据输入到内存 &#xff…...

系统讨论Qt的并发编程2——介绍一下Qt并发的一些常用的东西

目录 QThreadPool与QRunnable 互斥机制:QMutex, QMutexLocker, QSemaphore, QWaitCondition 跨线程的通信 入门QtConcurrent,Qt集成的一个并发框架 一些参考 QThreadPool与QRunnable QThreadPool自身预备了一些QThread。这样,我们就不需…...

【数据挖掘】Pandas之DataFrame

在 Pandas 中,DataFrame 提供了丰富的数据操作功能,包括 查询、编辑、分类和汇总。 1. 数据查询(Filtering & Querying) 1.1 按索引或列名查询 import pandas as pddata {"ID": [101, 102, 103, 104, 105],"…...

C++:volatile、const、mutable关键字

文章目录 volatile、const、mutable 关键字的作用、联系与区别 1️⃣ **volatile** —— 防止编译器优化,确保变量每次访问都从内存读取**作用****使用场景****示例** 2️⃣ **const** —— 限制变量的修改,保证不可变性**作用****使用场景****示例** 3️…...

linux离线安装miniconda环境

1 下载安装包 可以在官网下载最新版 https://www.anaconda.com/download/success#miniconda 或者在软件目录选择合适的版本 https://repo.anaconda.com/miniconda/ 安装包传入离线服务器 ./Miniconda3-py311_24.9.2-0-Linux-x86_64.sh2 运行安装包 ./Miniconda3-py311_24…...

考研408数据结构线性表核心知识点与易错点详解(附真题示例与避坑指南)

一、线性表基础概念 1.1 定义与分类 定义:线性表是由n(n≥0)个相同类型数据元素构成的有限序列,元素间呈线性关系。 分类: 顺序表:元素按逻辑顺序存储在一段连续的物理空间中(数组实现&…...

selenium用例执行过程采集操作形成测试报告上的回复

在代码执行的过程中不断的进行截图,把截图拼接成gif动态图,放在测试报告上 1、每条用例执行启动一个线程,这个线程会每隔0.3秒进行截图 项目下创建一个临时目录video用来存储所有截图以及gif动态图封装不断截图的方法,每隔0.3秒…...

多元数据直观表示(R语言)

一、实验目的: 通过上机试验,掌握R语言实施数据预处理及简单统计分析中的一些基本运算技巧与分析方法,进一步加深对R语言简单统计分析与图形展示的理解。 数据: 链接: https://pan.baidu.com/s/1kMdUWXuGCfZC06lklO5iXA 提取码: …...

【JavaEE】线程安全

【JavaEE】线程安全 一、引出线程安全二、引发线程安全的原因三、解决线程安全问题3.1 synchronized关键字(解决修改操作不是原子的)3.1.1 synchronized的特性3.1.1 synchronized的使用事例 3.2 volatile 关键字(解决内存可见性) …...

HarmonyOS 5.0应用开发——多线程Worker和@Sendable的使用方法

【高心星出品】 文章目录 多线程Worker和Sendable的使用方法开发步骤运行结果 多线程Worker和Sendable的使用方法 Worker在HarmonyOS中提供了一种多线程的实现方式,它允许开发者在后台线程中执行长耗时任务,从而避免阻塞主线程并提高应用的响应性。 S…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

微信小程序之bind和catch

这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...