In [1]:
# import the usual modules
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# nice plots
import seaborn as sns
sns.set(style="ticks") # turns the grid lines off 

# show images in viridis by default
plt.rcParams["image.cmap"] = "viridis"

# for getting file names
import glob

# skimage submodules we need
import skimage.io
import skimage.measure
import skimage.filters
import skimage.exposure

Part 1: using phase image to get segmentation mask

1.1 Background subtraction

In [2]:
# read in a sample image
im = skimage.io.imread("./data/lacI_titration/O2_R124_phase_pos_02.tif")

plt.imshow(im)
Out[2]:
<matplotlib.image.AxesImage at 0x1c223f44e0>
In [8]:
# normalize the image
im_norm = (im - np.min(im))/(np.max(im) - np.min(im))

# find the background image
gauss_radius = 50
im_bg = skimage.filters.gaussian(im_norm, gauss_radius)

# show this background image
plt.imshow(im_bg)
Out[8]:
<matplotlib.image.AxesImage at 0x1c240df160>
In [10]:
# perform background subtraction
im_bs = im_norm - im_bg

# show original the original and background subtracted side-by-side
fig, ax = plt.subplots(1,2)
ax[0].imshow(im_norm)
ax[1].imshow(im_bs)
Out[10]:
<matplotlib.image.AxesImage at 0x1c243fd1d0>

1.2 Thresholding

Let's plot pixel intensities

In [14]:
hist, pixel_vals = skimage.exposure.histogram(im_bs)

plt.plot(pixel_vals, hist, '.')
plt.yscale("log")
plt.xlabel("pixel values")
plt.ylabel("counts")
Out[14]:
Text(0,0.5,'counts')
In [16]:
# choose a threshold based on plot above
threshold = -0.2

# threshold the image
im_thresh = im_bs < threshold

# show the thresholded image, bacteria are 1, backround is 0
plt.imshow(im_thresh)
Out[16]:
<matplotlib.image.AxesImage at 0x1c2539ec50>

1.3 label objects in the image and get their sizes

In [17]:
# label the objects in the binary image
im_label = skimage.measure.label(im_thresh)

# show the labeled image 
plt.imshow(im_label)
Out[17]:
<matplotlib.image.AxesImage at 0x1c254d9278>
In [23]:
# find the number of object in the image
num_objs = np.max(im_label)
num_objs
Out[23]:
179

plot the size of the objects in the image

In [32]:
# length calibration
pixel_size = 0.16 # um

# array to store are values in 
areas = np.zeros(num_objs+1)

# obtain the areas of all labeled objects
for i in range(1,num_objs+1):
    # determine area for given object
    area = np.sum(im_label == i)
    areas[i] = area * pixel_size**2
In [34]:
# plot these areas
_ = plt.hist(areas, bins=20)
plt.yscale("log")
plt.xlabel("area (um)^2")
plt.ylabel("count")
Out[34]:
Text(0,0.5,'count')

1.4 Remove non-bacteria objects from the image

In [35]:
# set threshold on what we call a bacterium
lower_area = 1 # um^2
upper_area = 4 # um^2

# create a blank image with dimensions of im_label
im_mask = np.zeros_like(im_label)

# loop through objects of im_label
# add to im_mask *only* if the right size
for i in range(1,num_objs+1):
    # get area for given object
    pixel_area = np.sum(im_label == i)
    um_area = pixel_area * pixel_size**2
    
    # if area is within bounds, add this object to the mask
    if (um_area > lower_area) and (um_area < upper_area):
        im_mask = im_mask + (im_label == i)
In [37]:
# show the masked image
plt.imshow(im_mask)
Out[37]:
<matplotlib.image.AxesImage at 0x1c24fed588>

1.5 "write" a masking function

In [38]:
import pboc_utils as pboc
In [42]:
test_mask = pboc.create_mask(im, area_high=4)

plt.imshow(test_mask)
Out[42]:
<matplotlib.image.AxesImage at 0x1c27085ba8>