.. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_intro_scipy_auto_examples_solutions_plot_image_blur.py: ======================================================= Simple image blur by convolution with a Gaussian kernel ======================================================= Blur an an image (:download:`../../../../data/elephant.png`) using a Gaussian kernel. Convolution is easy to perform with FFT: convolving two signals boils down to multiplying their FFTs (and performing an inverse FFT). .. code-block:: python import numpy as np from scipy import fftpack import matplotlib.pyplot as plt The original image #################################################################### .. code-block:: python # read image img = plt.imread('../../../../data/elephant.png') plt.figure() plt.imshow(img) .. image:: /intro/scipy/auto_examples/solutions/images/sphx_glr_plot_image_blur_001.png :class: sphx-glr-single-img Prepare an Gaussian convolution kernel #################################################################### .. code-block:: python # First a 1-D Gaussian t = np.linspace(-10, 10, 30) bump = np.exp(-0.1*t**2) bump /= np.trapz(bump) # normalize the integral to 1 # make a 2-D kernel out of it kernel = bump[:, np.newaxis] * bump[np.newaxis, :] Implement convolution via FFT #################################################################### .. code-block:: python # Padded fourier transform, with the same shape as the image # We use :func:`scipy.signal.fftpack.fft2` to have a 2D FFT kernel_ft = fftpack.fft2(kernel, shape=img.shape[:2], axes=(0, 1)) # convolve img_ft = fftpack.fft2(img, axes=(0, 1)) # the 'newaxis' is to match to color direction img2_ft = kernel_ft[:, :, np.newaxis] * img_ft img2 = fftpack.ifft2(img2_ft, axes=(0, 1)).real # clip values to range img2 = np.clip(img2, 0, 1) # plot output plt.figure() plt.imshow(img2) .. image:: /intro/scipy/auto_examples/solutions/images/sphx_glr_plot_image_blur_002.png :class: sphx-glr-single-img Further exercise (only if you are familiar with this stuff): A "wrapped border" appears in the upper left and top edges of the image. This is because the padding is not done correctly, and does not take the kernel size into account (so the convolution "flows out of bounds of the image"). Try to remove this artifact. A function to do it: :func:`scipy.signal.fftconvolve` #################################################################### The above exercise was only for didactic reasons: there exists a function in scipy that will do this for us, and probably do a better job: :func:`scipy.signal.fftconvolve` .. code-block:: python from scipy import signal # mode='same' is there to enforce the same output shape as input arrays # (ie avoid border effects) img3 = signal.fftconvolve(img, kernel[:, :, np.newaxis], mode='same') plt.figure() plt.imshow(img3) .. image:: /intro/scipy/auto_examples/solutions/images/sphx_glr_plot_image_blur_003.png :class: sphx-glr-single-img Note that we still have a decay to zero at the border of the image. Using :func:`scipy.ndimage.gaussian_filter` would get rid of this artifact .. code-block:: python plt.show() **Total running time of the script:** ( 0 minutes 0.064 seconds) .. _sphx_glr_download_intro_scipy_auto_examples_solutions_plot_image_blur.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download :download:`Download Python source code: plot_image_blur.py ` .. container:: sphx-glr-download :download:`Download Jupyter notebook: plot_image_blur.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_