{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Image denoising by FFT\n\nDenoise an image (:download:`../../../../data/moonlanding.png`) by\nimplementing a blur with an FFT.\n\nImplements, via FFT, the following convolution:\n\n\\begin{align}f_1(t) = \\int dt'\\, K(t-t') f_0(t')\\end{align}\n\n\\begin{align}\\tilde{f}_1(\\omega) = \\tilde{K}(\\omega) \\tilde{f}_0(\\omega)\\end{align}\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Read and plot the image\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\nimport matplotlib.pyplot as plt\n\nim = plt.imread(\"../../../../data/moonlanding.png\").astype(float)\n\nplt.figure()\nplt.imshow(im, \"gray\")\nplt.title(\"Original image\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Compute the 2d FFT of the input image\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import scipy as sp\n\nim_fft = sp.fft.fft2(im)\n\n# Show the results\n\n\ndef plot_spectrum(im_fft):\n    from matplotlib.colors import LogNorm\n\n    # A logarithmic colormap\n    plt.imshow(np.abs(im_fft), norm=LogNorm(vmin=5))\n    plt.colorbar()\n\n\nplt.figure()\nplot_spectrum(im_fft)\nplt.title(\"Fourier transform\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Filter in FFT\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# In the lines following, we'll make a copy of the original spectrum and\n# truncate coefficients.\n\n# Define the fraction of coefficients (in each direction) we keep\nkeep_fraction = 0.1\n\n# Call ff a copy of the original transform. NumPy arrays have a copy\n# method for this purpose.\nim_fft2 = im_fft.copy()\n\n# Set r and c to be the number of rows and columns of the array.\nr, c = im_fft2.shape\n\n# Set to zero all rows with indices between r*keep_fraction and\n# r*(1-keep_fraction):\nim_fft2[int(r * keep_fraction) : int(r * (1 - keep_fraction))] = 0\n\n# Similarly with the columns:\nim_fft2[:, int(c * keep_fraction) : int(c * (1 - keep_fraction))] = 0\n\nplt.figure()\nplot_spectrum(im_fft2)\nplt.title(\"Filtered Spectrum\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Reconstruct the final image\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Reconstruct the denoised image from the filtered spectrum, keep only the\n# real part for display.\nim_new = sp.fft.ifft2(im_fft2).real\n\nplt.figure()\nplt.imshow(im_new, \"gray\")\nplt.title(\"Reconstructed Image\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Easier and better: :func:`scipy.ndimage.gaussian_filter`\n\n Implementing filtering directly with FFTs is tricky and time consuming.\n We can use the Gaussian filter from :mod:`scipy.ndimage`\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "im_blur = sp.ndimage.gaussian_filter(im, 4)\n\nplt.figure()\nplt.imshow(im_blur, \"gray\")\nplt.title(\"Blurred image\")\n\nplt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.11"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}