Image Processing II

(c) 2020 Justin Bois. This work is licensed under a Creative Commons Attribution License CC-BY 4.0. All code contained herein is licensed under an MIT license.

This document was prepared at Caltech with support financial support from the Donna and Benjamin M. Rosen Bioengineering Center.

This tutorial was generated from an Jupyter notebook. You can download the notebook here.


In this tutorial, we will expand on what we learned in the first image processing tutorial and develop some further skills to help us with segmentation of images of bacteria for the LacI titration experiment. The idea is to use the images in the red channel, which show constitutively expressed mCherry, to segment the image, identifying individual bacteria. We will then know where to look in fluorescent channel to quantify the YFP signal in single bacteria. In the example images, which you can download here, the YFP channel is labeled FITC, which is the closest filter the microscope has for YFP.

Importantly, we are free to manipulate the brightfield and mCherry images as we like in order to get good segmentation. After we have identified which pixels below to which cells, we have to be very careful adjusting the fluorescent images as the pixel values in these images are the signal we are measuring. We will only employ a median filter with a very small structuring element to deal with the known camera issue of occasional rogue high intensity pixels.

As usual, we will start by importing the modules we will need.

In [1]:
import numpy as np

import skimage.io
import skimage.exposure
import skimage.filters
import skimage.morphology
import skimage.segmentation

import bokeh.io
import bokeh.plotting

import colorcet

import bi1x

bokeh.io.output_notebook()
Loading BokehJS ...

Loading and viewing images

We will start by loading and viewing the images. We have a brightfield image, an mCherry image, and a FTIC image.

In [2]:
# Load images
im_phase = skimage.io.imread('img_000000000_Brightfield_000.tif')
im_mcherry = skimage.io.imread('img_000000000_MCherry_000.tif')
im_yfp = skimage.io.imread('img_000000000_FITC_000.tif')

Some of the cameras on the microscopes have hot pixels, so we will filter those out with a median filter.

In [3]:
# Perform median filtering
selem = skimage.morphology.disk(1)
im_phase_median = skimage.filters.median(im_phase, selem)
im_mcherry_median = skimage.filters.median(im_mcherry, selem)
im_yfp_median = skimage.filters.median(im_yfp, selem)

Now, let's take a look at the images.

In [4]:
ip_dist = 0.0636  # microns
ims = [im_phase_median, im_mcherry_median, im_yfp_median]
plots = [
    bi1x.viz.imshow(
        im, plot_height=250, interpixel_distance=ip_dist, length_units="┬Ám"
    )
    for im in ims
]

# Link the plots
for pl in plots[1:]:
    pl.x_range = plots[0].x_range
    pl.y_range = plots[0].y_range

bokeh.io.show(bokeh.layouts.gridplot(plots, ncols=2))