I'm unsuccessfully trying to generate a 2D array of pink noise. Can anyone explain me how to do this? Otherwise, is there a python library that allows to generate 2D (or higher dimensionality) colored noise (1/f noise)?
2 Answers
generate white noise in 2D, e.g. using
np.random.randn
calculate FFT_2D of it (
numpy.fft.fft2
)multiply result (2D spectrum) by
1/f**2
matrix, calculated in such a way:1/f_along_x * 1/f_along_y
. That's how I interpret this definition of pink noise in N-dimensions, but I am not sure I am correct! EDIT: Cris Luengo version (see the comment below) -1/sqrt(f_x**2+f_y**2)
- seems better for me, but its for you to decide which definition of 2d pink noise to use.Use IFFT_2D to get pink noise image (numpy.fft.ifft2)

- 3,172
- 1
- 23
- 35
-
1Almost correct! I think `1/f**2` translates to `1/(f_x**2+f_y**2)` (i.e. `f` is the distance to the origin). Although I'm dubious about the claim on the Wikipedia page, I think pink noise is `1/f = 1/sqrt(f_x**2+f_y**2)`, because `1/f**2` is Brownian nose. I've generated these in different number of dimensions, and it doesn't look right when the power increases with the dimensionality. – Cris Luengo Nov 23 '21 at 22:28
-
Thanks for info @CrisLuengo. I guess it is all about who defines it and what "looks right" for him/her. I like your version much more than the one from wiki, for me it looks better too :) – dankal444 Nov 23 '21 at 23:56
-
Thank you both for your replies. I understand how this method works, but I have problems trying to implement the two frequency matrix. Could you please elaborate a bit more? – ociredef Nov 25 '21 at 10:30
The answers given both here and in a related question (How to generate a pink noise image?) give you most of the picture - but I thought I'd lay out a full step-by-step to show how everything comes together.
Especially as it seems people run into issues understanding the "frequency matrix".
To convert white noise to pink noise
- Generate some white noise:
whitenoise = np.random.uniform(0, 1, (256, 256))
- Fourier transform and shift low-frequencies to centre (this makes generating the "frequency matrix" more intuitive):
ft_arr = np.fft.fftshift(np.fft.fft2(whitenoise))
- Generate the "frequency matrix". In the 1-D case this would be an array of the actual frequencies which correspond to the amplitudes given by the transform. In the 2-D case, this is the distance from the center of our fftshifted fourier space, as the further out to the edges we go, the greater the frequency captured at that point. This can be generated via
np.meshgrid
andnp.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)
We then divide the fourier space by the frequencies.
pink_ft_arr = ft_arr / f
- Remove singularities that show up due to having a zero-frequency component. (Probably there's a smarter way to do this, but this gave me the expected output regardless):
pink_ft_arr = np.nan_to_num(pink_ft_arr, nan=0, posinf=0, neginf=0)
- Convert the fourier space pink noise back into image space:
pinknoise = np.fft.ifft2(np.fft.ifftshift(pink_ft_arr)).real
You can then plot this using matplotlibs plt.imshow
, or scale it into some sensible range and write it out as an image.
White noise, from np.random.uniform
Pink noise generated by the above.

- 26
- 2