Background removal filters#

There are also background removal filters. If there is a more or less homogeneous intensity spread over the whole image, potentially increasing in a direction, it is recommended to remove this background before segmenting the image.

import numpy as np
from skimage.io import imread
from pyclesperanto_prototype import imshow
from skimage.filters import gaussian
from skimage.restoration import rolling_ball 
from skimage.morphology import disk
import matplotlib.pyplot as plt
from skimage.filters import difference_of_gaussians
from skimage.morphology import white_tophat

As example image, we will work with a zebrafish eye data set (Courtesy of Mauricio Rocha Martins, Norden lab, MPI CBG). As you can see, there is some intensity spread around the nuclei we want to segment later on. The source of this background signal is out-of-focus light.

# load zfish image and extract a channel
zfish_image = imread('../../data/zfish_eye.tif')[:,:,0]

imshow(zfish_image)
../_images/03_background_removal_3_0.png

To subtract the background, we need to determine it first. We can use the rolling-ball algorithm for that. The radius parameter configures how distant pixels should be taken into account for determining the background intensity.

background_rolling = rolling_ball(zfish_image, radius=25)

imshow(background_rolling)
../_images/03_background_removal_5_0.png

Afterwards, we subtract the background from the original and display all three images:

zfish_rolling = zfish_image - background_rolling

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

# first row
imshow(zfish_image, plot=axs[0])
axs[0].set_title("Original")
imshow(background_rolling, plot=axs[1])
axs[1].set_title("Background (rolling ball)")
imshow(zfish_rolling, plot=axs[2])
axs[2].set_title("Background subtracted")
Text(0.5, 1.0, 'Background subtracted')
../_images/03_background_removal_7_1.png

We could do the same using a Gaussian blur filter.

background_gaussian = gaussian(zfish_image, sigma=20, preserve_range=True)

zfish_gaussian = zfish_image - background_gaussian

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

# first row
imshow(zfish_image, plot=axs[0])
axs[0].set_title("Original")
imshow(background_gaussian, plot=axs[1])
axs[1].set_title("Background (Gaussian)")
imshow(zfish_gaussian, plot=axs[2])
axs[2].set_title("Background subtracted")
Text(0.5, 1.0, 'Background subtracted')
../_images/03_background_removal_9_1.png

In some scenarios it also makes sense to divide the image by the background. This helps for example to make all nuclei in this image have similar intensities. This could be advantageous for nuclei segmentation.

background_gaussian = gaussian(zfish_image, sigma=50, preserve_range=True)

zfish_gaussian = zfish_image / background_gaussian

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

# first row
imshow(zfish_image, plot=axs[0])
axs[0].set_title("Original")
imshow(background_gaussian, plot=axs[1])
axs[1].set_title("Background (Gaussian)")
imshow(zfish_gaussian, plot=axs[2])
axs[2].set_title("Background divided")
Text(0.5, 1.0, 'Background divided')
../_images/03_background_removal_11_1.png

Other background subtraction techniques#

There are other techniques for background subtraction such as the top-hat. Furthwermore, the Difference of Gaussians (DoG) is a technique for combined denoising and background removal.

# DoG

zfish_dog = difference_of_gaussians(zfish_image, 0, 15)

# Top-Hat
zfish_top_hat = white_tophat(zfish_image, disk(15))

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

# first row
imshow(zfish_dog, plot=axs[0], min_display_intensity=0)
axs[0].set_title("Difference of Gaussian")
imshow(zfish_top_hat, plot=axs[1])
axs[1].set_title("Top hat")
imshow(zfish_rolling, plot=axs[2])
axs[2].set_title("Rolling ball algorithm")
Text(0.5, 1.0, 'Rolling ball algorithm')
../_images/03_background_removal_13_1.png

Exercise#

Apply different algorithms and radii to remove the background in the zebrafish eye dataset. Zoom into the dataset using cropping and figure out how to make the background go away optimally.