在Python中生成不同颜色的噪声

13
我希望用Python生成不同颜色的噪声,就像维基百科所提到的那样:https://en.wikipedia.org/wiki/Colors_of_noise
例如,白噪声、粉噪声、布朗噪声、蓝噪声和紫噪声。我希望它们具有与该网站类似的频谱。
如果我只需调整一些参数即可完成,那将是非常有帮助的。任何链接或提示都将不胜感激!非常感谢。

我不明白你的问题,“调整几个参数”是指什么? - TGrif
3个回答

21

我们可以使用numpy计算噪声,使用matplotlib绘制结果。

import numpy as np
import matplotlib.pyplot as plt

def plot_spectrum(s):
    f = np.fft.rfftfreq(len(s))
    return plt.loglog(f, np.abs(np.fft.rfft(s)))[0]

这是Python装饰器的一个很好的使用案例。

def noise_psd(N, psd = lambda f: 1):
        X_white = np.fft.rfft(np.random.randn(N));
        S = psd(np.fft.rfftfreq(N))
        # Normalize S
        S = S / np.sqrt(np.mean(S**2))
        X_shaped = X_white * S;
        return np.fft.irfft(X_shaped);

def PSDGenerator(f):
    return lambda N: noise_psd(N, f)

@PSDGenerator
def white_noise(f):
    return 1;

@PSDGenerator
def blue_noise(f):
    return np.sqrt(f);

@PSDGenerator
def violet_noise(f):
    return f;

@PSDGenerator
def brownian_noise(f):
    return 1/np.where(f == 0, float('inf'), f)

@PSDGenerator
def pink_noise(f):
    return 1/np.where(f == 0, float('inf'), np.sqrt(f))

PSDGenrator函数接受一个函数作为输入,并返回另一个函数,该函数将生成一个具有与给定函数相应的功率谱形状的随机信号。

S = S / np.sqrt(np.mean(S**2))确保有色噪声将保留白噪声的能量。

让我们测试一下。

plt.style.use('dark_background')
plt.figure(figsize=(12, 8), tight_layout=True)
for G, c in zip(
        [brownian_noise, pink_noise, white_noise, blue_noise, violet_noise], 
        ['brown', 'hotpink', 'white', 'blue', 'violet']):
    plot_spectrum(G(30*50_000)).set(color=c, linewidth=3)
plt.legend(['brownian', 'pink', 'white', 'blue', 'violet'])
plt.suptitle("Colored Noise");
plt.ylim([1e-3, None]);

consistently_colored_noise


我给了你产生具有所需频谱分布和单位能量的噪声的函数。例如尝试 brownian_noise(2**16),它将生成一份布朗噪声样本。 - Bob
抱歉,那是一个错误,Pink 应该有一个平方根。已修复。 - Bob
抱歉,最后一个问题,x轴上的值不应该是频率吗?如果是这样,为什么这么小? - JeffreyLai
2
因为它是归一化频率,即频率除以采样率,所以它的范围从0到0.5(奈奎斯特频率)。 - Bob
2
@Ash,感谢您的反馈,这是为了保留白噪声的能量。 - Bob
显示剩余4条评论

3

有一个用于处理 Python 中彩色噪声的库。

https://pypi.org/project/colorednoise/

!pip install colorednoise
import colorednoise as cn
from matplotlib import pylab as plt

#input values
beta = 0         # the exponent: 0=white noite; 1=pink noise;  2=red noise (also "brownian noise")
samples = 2**16  # number of samples to generate (time series extension)

#Deffing some colores
A = cn.powerlaw_psd_gaussian(beta, samples)

#Ploting first subfiure
plt.plot(A, color='black', linewidth=1)
plt.title('Colored Noise for β='+str(beta))
plt.xlabel('Samples (time-steps)')
plt.ylabel('Amplitude(t)', fontsize='large')
plt.xlim(1,5000)
plt.show()

enter image description here


2

支持@Bob的出色回答,我包含了他代码生成的噪声的时间序列图。下面是我使用的绘图代码。

SAMPLE_FREQ_HZ  = 125 * HERTZ
SAMPLE_INTV_SEC = 1/SAMPLE_FREQ_HZ
def plot_test_points(sample_count: int = None):
    n = sample_count if sample_count else 1000
    fig, ax_list = plt.subplots(5, 1, figsize=(12, 8), tight_layout=True)
    i = 0
    for G, c, l in zip(
            [brownian_noise, pink_noise, white_noise, blue_noise, violet_noise],
            ['brown', 'hotpink', 'black', 'blue', 'violet'],
            ['brown', 'pink', 'white', 'blue', 'violet']):
        ax = ax_list[i]
        t = [x*SAMPLE_INTV_SEC for x in range(0, n)]
        ax.plot(t, G(n), color=c, linewidth=0.5, label=l)
        ax.legend(loc='lower left')
        ax.set_xlabel("Time [sec]")
        i += 1
    plt.suptitle(f"Colored Noise (n={n} points; sampling rate = {SAMPLE_FREQ_HZ}Hz)")
    plt.show()

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接