pythonnumpyconvolutiongaussianblur

Convolving with a gaussian kernel vs Gaussian blur


While looking for a way to generate spatially varying noise, I came across this answer, which is able to do what I wanted. But I am getting confused about how the code works.

From what I understand, the first step of the code generates a gaussian kernel:

import numpy as np
import scipy.signal
import matplotlib.pyplot as plt

# Compute filter kernel with radius correlation_scale (can probably be a bit smaller)
correlation_scale = 150
x = np.arange(-correlation_scale, correlation_scale)
y = np.arange(-correlation_scale, correlation_scale)
X, Y = np.meshgrid(x, y)
print(X.shape,Y.shape)
dist = np.sqrt(X*X + Y*Y)
filter_kernel = np.exp(-dist**2/(2*correlation_scale))

which when visualized looks as follows:

The second step of the code generates a random noise grid:

n = 512
noise = np.random.randn(n, n)

that looks like:

enter image description here

The third step convolves the random noise generated in step 2 with the filter generated in step 1.

noise1 = scipy.signal.fftconvolve(noise, filter_kernel, mode='same')

and the output of this step looks like this:

enter image description here

My question is how does the output of step 3 end up looking like this instead of a smoothed out version of the random noise? Isn't convolution with a Gaussian kernel the same as applying a Gaussian blur? For instance, if I apply a Gaussian filter on the random noise generated, the output would look like this:

from scipy.ndimage import gaussian_filter
noise  = gaussian_filter(noise , sigma=1, radius=10)

enter image description here

Why are the last two images so different from each other?


Solution

  • I've played a bit with the code you provided, and this seems to be related to the fact that you use standard deviations for your gaussian kernel that are very different, your correlation_scale is 150 in the first example whereas sigma is one in your second example. If I take similar values for both, I get similar results.

    Unrelated, but feel free to truncate your gaussian kernel a bit (noise_trunc=noise[len(X)//2-50:len(X)//2+50, len(Y)//2-50:len(Y)//2+50]), or at least to set the very low coeffs to 0 (noise[noise<1e-5]=0), to greatly increase the speed of your computations