Image Processing with scikit-image

Zeeshan Patel
7 min readJun 2, 2020
A scratch assay time series analysis.

Image processing is very applicable in present times. COVID-19 has brought upon new challenges for researchers across the globe, whether it be for developing a cure or to find new ways to detect the virus. In order to conduct research on COVID-19, researchers often need to perform heavy computations on images to detect specific elements that would be useful to draw new insights and conclusions.

In this article, I’ll go through the basics of image processing and a small tutorial detailing how image processing can be used for thresholding and segmentation, two very powerful techniques in image processing. In this article, I will use scikit-image, so a basic background in Python and possibly some advanced mathematics might be required to completely understand the concept.

What is scikit-image?

scikit-image is a Python library dedicated for image processing. It can be used in unison with Scipy libraries and other Python libraries that may help with computations. In order to fully use scikit-image, the user must also use Matplotlib in order to display the transformed images and to perform image analysis. In this tutorial, I will use specific functions within the scikit-image library, Matplotlib, and NumPy in order to perform analysis on a scratch assay.

What is a Scratch Assay?

Most of you probably have no idea what a scratch assay is unless you have heavy experience in biology. I’ll provide a brief summary of what a scratch assay is and I’ll jump right into the tutorial.

A scratch assay is a technique used by biologists to track cell movement and interaction. Specifically, biologists take a sample of cells in a petri dish and create an artificial wound on the plane of cells. After developing the artificial wound, biologists take images of any cell movements periodically to develop a time series of images for analysis.

In the following tutorial, I will be processing the image provided below, so download this image and add it to your project directory before starting.

Scratch Assay Image Obtained from Microscope

Scratch Assay Analysis Tutorial

First, we need to determine what we are trying to do to process this image. To gain more insights from this image, we’ll be using various segmentation techniques in order to separate the region of cells from the scratched region (the clear space). As you can see, we can’t just segment this image based on color due to the pixel value being essentially the same all across the image. However, we can use texture as a parameter for determining which region of the petri dish has cells and which doesn’t. To do this, we will apply a special filter to our image before we begin segmenting it.

First, let’s begin by importing all of the necessary libraries into our Python script:

Then, import the image I provided above. I named the image “scratch.jpg” in the code snippet below.

In the above code, I used the io package within scikit-image to use the imread function which allows me to input the image data. This function works exactly like the Pandas read_csv method for CSV files. Additionally, I used the Entropy filter from scikit-image’s morphology package, which will allow me to analyze the texture of the image by searching for disorder in certain pixels. If you would like to further learn about the functionalities and parameters of all of these functions, please visit the scikit-image documentation. You can play around with the disk parameter, but for this image, optimal results are obtained at a disk value of 10.

Now we will apply the Otsu thresholding filter which is derived from the skimage.filters package. This simple, one-line command will allow us to apply an Otsu thresholding filter. Otsu thresholding is a specific algorithm which iterates over every pixel in the image and separates the pixels into two classes, the background and foreground. You’ll understand the effect of this once we actually plot the image.

The thresholding filter only returns a single number. This value is the exact value that the Otsu algorithm calculated for optimized image segmentation and will aid us in generating our final image.

In this line of code, we’re setting the variable “binary” to all of the pixel values of entropy_img. Then, we use a logical operator so that all of the pixel values in the entropy_img that are less than or equal to our threshold value are set to True. Remember, images are translated into NumPy ndarrays when using scikit-image, so our binary image is actually just an array. This means that we can use a logical operator to compare the float threshold value with the pixel values of entropy_img. Our binary image in this scenario will set the area where there are no cells in the assay as True and those with cells as False.

Finally, this is where we get to see the results of our image segmentation. In this code, I defined a subplot in which the original image, the image with the Entropy filter, and the image with both the Entropy filter and Otsu filter will be shown. The image of the “Segmented Assay w Otsu Filter” will be the final result of our scratch assay analysis. Let’s see the output of all this code:

As you can see in the above images, the Entropy filter created a drastic change in the original image. The Entropy filter detected minute changes in the pixels of the image and divided up pixels based on complexity of certain regions of the image. As you can see in the second image, the black strip represents the region without cells while the gray region represent the region with cells. The Otsu filter solidifies this segmentation by implementing a threshold, allowing us to exactly pinpoint the location of the cells at that exact moment of the scratch assay analysis.

Finally, we can print the number of pixels representing the cell-free region of the assay to gain a better understanding of how the cells are moving and proliferating over time.

Further Remarks

This specific project is great for understanding some basic aspects of image processing. The image being analyzed in the tutorial was extremely hard to segment due to all the pixels having the same RGB value. However, with the help of the Entropy filter, we were able to produce an image that was processed based on its texture and then we could use an Otsu threshold to gain more insight into the cell positions at that point in time.

A scratch assay consists of a time series, and we only analyzed one image in that time series. Biologists loop through this process many times across several images to produce a time series representation of cell movement. As they go through each image, biologists record changes in cell movement and position, which gives them more info about the rate of cell proliferation and cell migration patterns.

Many image processing filters require knowledge of complex Gaussian mathematics, which most people do not have experience in. However, scikit-image removes the requirement of knowing advanced mathematics in order to implement such filters. However, knowledge of Gaussian kernels and other such computational tools can allow researchers to gain more accurate visualizations that prepackaged software can provide.

I have added the full code Gist below, along with a few resources that might help you understand the Scratch Assay Analysis better.

Code

--

--

Zeeshan Patel

I’m a freshman studying CS and Statistics at UC Berkeley. Feel free to contact me at zeeshanp@berkeley.edu.