如何生成 2D 有色噪声

问题描述 投票:0回答:3

我没有成功地尝试生成粉红噪声的二维数组。谁能解释我该怎么做?否则,是否有一个Python库可以生成2D(或更高维度)有色噪声(1/f噪声)?

python image-processing signal-processing noise noise-generator
3个回答
2
投票

此处和相关问题中给出的答案(如何生成粉红噪声图像?)为您提供了大部分图片 - 但我想我应该列出完整的逐步步骤来展示一切是如何发生的一起。

尤其是人们似乎在理解“频率矩阵”时遇到了问题。

将白噪声转换为粉红噪声

  1. 产生一些白噪声:
    whitenoise = np.random.uniform(0, 1, (256, 256))
  2. 傅立叶变换并将低频移至中心(这使得生成“频率矩阵”更加直观):
    ft_arr = np.fft.fftshift(np.fft.fft2(whitenoise))
  3. 生成“频率矩阵”。在一维情况下,这将是与变换给出的幅度相对应的实际频率的数组。在二维情况下,这是距我们的 fftshifted 傅立叶空间中心的距离,随着我们距离边缘越远,在该点捕获的频率就越大。这可以通过 np.meshgrid
    np.hypot
    生成:
     

    _x, _y = np.mgrid[0:ft_arr.shape[0], 0:ft_arr.shape[1]]
    f = np.hypot(_x - ft_arr.shape[0] / 2, _y - ft_arr.shape[1] / 2)
    
    然后我们将傅里叶空间除以频率。 

    pink_ft_arr = ft_arr / f
    消除由于零频率分量而出现的奇点。 (可能有一种更聪明的方法来做到这一点,但这无论如何都给了我预期的输出):

  4. pink_ft_arr = np.nan_to_num(pink_ft_arr, nan=0, posinf=0, neginf=0)
    
    
    将傅里叶空间粉红噪声转换回图像空间:
  5. pinknoise = np.fft.ifft2(np.fft.ifftshift(pink_ft_arr)).real
    
    
  6. 然后您可以使用 matplotlibs
plt.imshow

绘制此图,或将其缩放到某个合理的范围并将其写为图像。

White noise, from np.random.uniform
Pink noise generated by the above.


1
投票
    生成二维白噪声,例如使用
  1. np.random.randn

    
    

  2. 计算其FFT_2D (
  3. numpy.fft.fft2

    )

    
    

  4. 将结果(二维频谱)乘以
  5. 1/f**2

    矩阵,计算方式如下:

    1/f_along_x * 1/f_along_y
    。 这就是我如何解释
    N 维粉红噪声的定义
    ,但我不确定我是否正确! 编辑:Cris Luengo 版本(请参阅下面的评论) - 1/sqrt(f_x**2+f_y**2) - 对我来说似乎更好,但由你决定使用哪种 2d 粉红噪声定义。
    
    

  6. 使用IFFT_2D获取粉红噪声图像(numpy.fft.ifft2)

0
投票
ckyleda 的答案

,它使用 matplotlib 绘制 3D 景观。我使用正常的白噪声,而不是均匀的白噪声,并且我使用现代的 NumPy random 界面。 在我的测试中,使用

np.hypot

的频率绘制的图太尖了。正如维基百科的

粉红噪声的幂律谱
中所建议的,使用这些频率的平方似乎可以给出更好的结果。 """ Pink noise surface in matplotlib Written by PM 2Ring 2023.10.20 """ import numpy as np import matplotlib.pyplot as plt from matplotlib import cm def pink_noise(size, rand, roughness): white = rand(size=(size, size)) white_ft = np.fft.fftshift(np.fft.fft2(white)) hsize = size / 2 y, x = np.ogrid[-hsize:hsize, -hsize:hsize] freq = (x**2 + y**2) ** (1 / roughness) pink_ft = np.divide(white_ft, freq, out=np.zeros_like(white_ft), where=freq!=0) pink = np.fft.ifft2(np.fft.ifftshift(pink_ft)).real lo, hi = np.min(pink), np.max(pink) return (pink - lo) / (hi - lo) def test(size=128, seed=None, roughness=1, scale=1/4): rng = np.random.default_rng(seed) Z = pink_noise(size, rng.normal, roughness) Y, X = np.ogrid[0:size, 0:size] #plt.style.use('dark_background') fig, ax = plt.subplots(subplot_kw={"projection": "3d"}, figsize=(8, 8), constrained_layout=True) ax.plot_surface(X, Y, Z, rstride=1, cstride=1, antialiased=False, cmap=cm.terrain) ax.set_box_aspect((1, 1, scale)) plt.axis('off') plt.show() test(size=128, seed=137, roughness=1, scale=1/4)

输出

这是相同

size

seed
的结果,但使用
roughness=2
,因此它使用上图中使用的频率的平方根。

这是一个
版本

,还有一些需要调整的参数。它运行在 SageMath 服务器上,但代码大部分是纯 Python。它只是使用 Sage 来获取参数并进行交互式 3D 渲染(实际上是由 Three.js 在浏览器中完成的)。 这是

相机控件

// Orbit - left mouse / touch: one-finger move // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move

右下角有一个信息菜单,可用于保存屏幕截图,或保存 HTML,以便您可以在没有 Sage 的情况下查看景观。

要生成云景,请选择“Blues_r”颜色图,然后将

scale

设置为较小的值,例如 1/20(如果您想从下面查看云,请将比例设为负值)。将

gamma
参数增加到 2 或 3 以获得更蓝的天空。
    

© www.soinside.com 2019 - 2024. All rights reserved.