Image Processing Filters#

Filters are mathematical operations that produce a new image out of one or more images. Pixel values between input and output images may differ.

import numpy as np

import matplotlib.pyplot as plt
from skimage.io import imread
from skimage import data
from skimage import filters
from skimage import morphology
from scipy.ndimage import convolve, gaussian_laplace
import stackview

To demonstrate what specific filters do, we start with a very simple image. It contains a lot of zeros and a single pixel with value 1 in the middle.

image1 = np.zeros((5, 5))
image1[2, 2] = 1
image1
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])
plt.imshow(image1, cmap='gray')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x162d12abe80>
../_images/86f4521e41e368cb0a95b225ec7754f5b1c9aeaf103b564dd5b13fd9dbbc9b12.png

Gaussian kernel#

To apply a Gaussian blur to an image, we convolve it using a Gaussian kernel. The function gaussian in scikit-image can do this for us.

blurred = filters.gaussian(image1, sigma=1)
blurred
array([[0.00291504, 0.01306431, 0.02153941, 0.01306431, 0.00291504],
       [0.01306431, 0.05855018, 0.09653293, 0.05855018, 0.01306431],
       [0.02153941, 0.09653293, 0.15915589, 0.09653293, 0.02153941],
       [0.01306431, 0.05855018, 0.09653293, 0.05855018, 0.01306431],
       [0.00291504, 0.01306431, 0.02153941, 0.01306431, 0.00291504]])
plt.imshow(blurred, cmap='gray')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x162d1363d00>
../_images/8748e18d5a21820a77861bcb934e40fe7853adebd82db6351086a3b36c5b2019.png

Laplacian#

Whenever you wonder what a filter might be doing, just create a simple test image and apply the filter to it.

image2 = np.zeros((9, 9))
image2[4, 4] = 1

plt.imshow(image2, cmap='gray')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x162d1438fd0>
../_images/8a8e0d1f7c6fc9b520d5c800454a7709e5a9c48e935ffab76d191cca5ef3a81b.png
mexican_hat = filters.laplace(image2)

plt.imshow(mexican_hat, cmap='gray')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x162d1b312b0>
../_images/6f30d549794819cef7e5b5a6981648785f6c13d78cb00e284c721d6c1971eacb.png

Laplacian of Gaussian#

We can also combine filters, e.g. using functions. If we apply a Gaussian filter to an image and a Laplacian afterwards, we have a filter doing the Laplacian of Gaussian (LoG) per definition.

def laplacian_of_gaussian(image, sigma):
    """
    Applies a Gaussian kernel to an image and the Laplacian afterwards.
    """
    
    # blur the image using a Gaussian kernel
    intermediate_result = filters.gaussian(image, sigma)
    
    # apply the mexican hat filter (Laplacian)
    result = filters.laplace(intermediate_result)
    
    return result
log_image1 = laplacian_of_gaussian(image2, sigma=1)

plt.imshow(log_image1, cmap='gray')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x162d1bc5dc0>
../_images/8c733c9622139dd4298a685496ca5ff72d5adbd590cd828fca5cd97840203dba.png

Interactive filter parameter tuning#

To understand better what filters are doing, it shall be recommended to apply them interactively. The following code will not render on github.com. You need to execute the notebook locally use this interactive user-interface.

image3 = imread('../../data/mitosis_mod.tif').astype(float)
stackview.interact(laplacian_of_gaussian, image3, zoom_factor=4)

More filter examples#

We demonstrate some more typical filters using this nuclei example image.

plt.imshow(image3, cmap='gray')
<matplotlib.image.AxesImage at 0x162d1d5f1f0>
../_images/bf051c00d77314c1c20e16e5bdf475098e794d476f8eacf40927eb2e12b04704.png

Denoising#

Common filters for denoising images are the mean filter, the median filter and the Gaussian filter.

denoised_mean = filters.rank.mean(image3.astype(np.uint8), morphology.disk(1))

plt.imshow(denoised_mean, cmap='gray')
<matplotlib.image.AxesImage at 0x162d1dc17c0>
../_images/249b6e2df7a7a965a5352c97e133e808445f6c79b3c2592cbfdc99f5c9eeb0e6.png
denoised_median = filters.median(image3, morphology.disk(1))

plt.imshow(denoised_median, cmap='gray')
<matplotlib.image.AxesImage at 0x162d1e4d220>
../_images/9b67e818e7a1f222217492f3de3c76d3b5828ca5602c780982f038db82185042.png
denoised_median2 = filters.median(image3, morphology.disk(5))

plt.imshow(denoised_median2, cmap='gray')
<matplotlib.image.AxesImage at 0x162d30ab100>
../_images/6ee01be025bac5cd51cfb83508d71266b3e5a2005f183b8c61e7cbbfcd484ac8.png
denoised_gaussian = filters.gaussian(image3, sigma=1)

plt.imshow(denoised_gaussian, cmap='gray')
<matplotlib.image.AxesImage at 0x162d2fa1970>
../_images/55ab669c177902ce75f2c857cbc4c5b7a3c33894e80b03c5d0cefe2e55ae7cc8.png

We can also show these images side-by-side using matplotlib.

fig, axes = plt.subplots(1,3, figsize=(15,15))

axes[0].imshow(denoised_mean, cmap='gray')
axes[1].imshow(denoised_median, cmap='gray')
axes[2].imshow(denoised_gaussian, cmap='gray')
<matplotlib.image.AxesImage at 0x162d30dabb0>
../_images/ac313feebf31974fecd396d08a862943866ebbcea9853616e960ff6e2768be05.png

Top-hat filtering / background removal#

top_hat = morphology.white_tophat(image3, morphology.disk(15))

plt.imshow(top_hat, cmap='gray')
<matplotlib.image.AxesImage at 0x162d3107e50>
../_images/974560367dfd07aa075709427ac7745b489d1b2f3783453d633fd3cac4379f82.png

Edge detection#

sobel = filters.sobel(image3)

plt.imshow(sobel, cmap='gray')
<matplotlib.image.AxesImage at 0x162d314a730>
../_images/81e684baee00e9d6c4d7503b270d24c7065f3d2b26cd95172e459cb48deea089.png

Exercise#

Write a function that computes the Difference of Gaussian.

def difference_of_gaussian(image, sigma1, sigma2):
    
    # enter code here

Use a simple function call to try out the function.

dog_image = difference_of_gaussian(image3, 1, 5)

plt.imshow(dog_image, cmap='gray')

Use the stackview library to play with it interactively.

stackview.interact(difference_of_gaussian, image3)