I'm following this post to generate pink noise with a certain frequency distribution using fourier transforms. I need to be able to give it an image to match the frequencies, and dimensions for the size of the output noise. The issue I have is my current code generates sometimes generates horizontal black bars in the noise. I've traced the issue down to the line "pinktransformed = fouriertransformed / f**2" where a divide by zero error occurs given certain images as inputs. This doesn't happen for most input images.
Here is an example of the black bars
I think the problem I'm having is that my value for f is incorrect. Right now I am just using the fourier transform of the image as f, but I don't think that's right. The link above says
f is an array that contains the frequencies corresponding to each bin of the fourier transform. Your original image takes a spatial position in the image and translates it to an "energy" which is white noise. You are taking a Fourier transform which means that while the value is still energy, the position in the array corresponds to a spatial "frequency" or a 1/wavelength. These are called wave vectors and correspond to plane waves. You need to divide each position by the magnitude of the wave vector at that position.
I think my current code would work if I just created this correct value for f, but I just don't understand what it means to divide each position by the magnitude of the wave vector at that position. What would I have to modify in my code to solve this?
Here is my current function (img is loaded as a PIL Image then converted to a numpy array, dim is a 2-tuple):
def generatenoise(img,dim):
whitenoise = np.random.uniform(0,256,(img.shape[0],img.shape[1],3))
fouriertransformed = np.fft.fftshift(np.fft.fft2(whitenoise))
f = np.fft.fftshift(np.fft.fft2(img))
pinktransformed = fouriertransformed / f**2
pinknoise = np.fft.ifft2(np.fft.ifftshift(pinktransformed)).real
pinknoise = np.resize(pinknoise, (dim[0],dim[1],3))
return pinknoise