Scikit-image, a Python-based image processing library

In this tutorial, we will learn image processing using scikit-image in Python.

From silly status updates to high profile documentation, images have become an integral part of digital data. Hence came in the need to process image. Enhancing the image, compressing them, extracting data and analyzing them, image processing is used in various fields such as artificial intelligence, data forensics, computer graphics, medical research and many more.

Due to its growing popularity and availability of many easy-to-use libraries, Python is an excellent choice for image processing. There are many image processing libraries available in Python like Numpy, Scipy, Scikit, OpenCV, Python Image Library (PIL), etc. This tutorial is focussed on Scikit-image.

Scikit-image:

Scikit-Image is an open-source Python package. Before getting any deeper, let’s check out the very basics of a digital image.

“Number rules the universe” -Pythagoras

An image is made up of numbers which we may digitally represent them by 2D arrays. Each grid of an array represents a pixel in the image. This makes the process of image segmentation quite simple. The scikit-image package works with NumPy arrays.

A digital image can be broadly classified into 2 types of channels: grayscale and multichannel. As the name suggests, a grayscale image will only have grey shades, covering different tones of black and white. They have no further color information. Multichannel RGB, the most common one, has 3 layers: Red, Green and Blue. Different approaches to color manipulation have been introduced in further content.

Getting started with Scikit-image

Here is the full step by step tutorial to work with this library in Python.

1. Installation

On the Command Prompt, simply type-

pip install scikit-image

And the installation is done.

NOTE: If you get an error, there is a chance that it is because you don’t have NumPy and Scipy on your system and you may first need to install them manually.

2. Displaying an image

Commencing our journey with scikit-image, the very first step is to import the package using skimage. Scikit contains a file with some preloaded images in them. To access them, use the module- data. Data has some standard demo images which can be used for testing purposes. Rocket, coffee, coins, camera, page, etc.

There is another module- io. This module contains all the functions used to read and write images.

from skimage import data, io

image = data.coffee()
io.imshow(image)
io.show()

The above code applies imshow() and show() functions. imshow() displays an image. show() displays the pending images queued by imshow. We need to use show() when displaying images from non-interactive shells.

Output:

Scikit-image, a Python-based image processing library

Hence, we have successfully completed our first code and imported an image.

Now, let’s import an image from a directory in our system.

import os
from skimage import io 
file = os.path.join('skimage_data', 'books.jpg')  
book = io.imread(file) 
io.imshow(book) 
io.show()

Output:

Scikit-image, a Python-based image processing library

Fig 2.2 Imported books image

3. Saving an image

Isn’t saving the most important part of any type of image processing? It can be done by using imsave() function. Imsave() takes the location along with desired name and format and of course, the image that needs to be saved as parameters.

from skimage import data, io
image = data.logo()
io.imsave('skimage/logo.png', image)

Run the code and done! The image will be saved at the chosen location.

4. Shape manipulation using scikit-image

The shape of an image plays an important role in manipulating an image. You can retrieve the size of an image using the shape attribute.

from skimage import data

image = data.coffee()
print(image.shape)

Output:

(400, 600, 3)

Here, 400 and 600 are height and width respectively. 3 indicates that the image is a multicolour image.

Now, let’s resize this image.

from skimage import data, io, transform
image = data.coffee()
img = transform.resize(image, (100, 100), anti_aliasing=True)
io.imshow(img)
io.show()
print(img.shape)

The resize function of transform library is used. The output will give the resized image shape and print the new size.

Output:

Scikit-image, a Python-based image processing library

Fig 4.1 Resized coffee image

(100, 100, 3)

Note that when zoomed in, the image quality has declined.

You can even try rotating an image using the transform library.

from skimage import transform, io, data
image = data.coffee()
image_rotated = trasform.rotate(image, angle=45, resize=True)
io.imshow(image)
io.show()

Output:

Fig 4.2 Rotated coffee image

Fig 4.2 Rotated coffee image

Go all the way 180º for an upside-down image. Note that the resize parameter is used; if that is off, the rotation would be done with the original size and you may lose some important data. By default, resize is set False. The output will be displayed like the following when the resize flag is not True.

Fig 4.2 Rotated coffee image

5. Colour manipulation using scikit-image

1.Grayscale image

Grayscale images are simply an image having shades of black and white. They basically depict the intensity of light and do not give any other colour information. The tonal representation of the image can range from 0 (pure black) to 255 (pure white).

2. Colour image

Colour images broadly have 3 layers- Red, Green and Blue (RGB). These layers are called channels. You can separate each channel (red, green, blue) like this-

from skimage import data, io

image = data.chelsea()
image[:, :, 0] = 0
io.imshow(image)
io.show()

The other color channels can be filtered out using [:, :, 1] or [:, :, 2]. Here’s how each output will appear like-

Fig 5.1 Filtering out colors

Fig 5.1 Filtering out colors

The RGB image can be converted to grayscale and vice versa. Computational complexity is reduced when a grayscale image is used. As discussed above, the format of image shape is specified as [height, width, channel]. A grayscale image would not have a channel since it does not give any colour information.

from skimage import data, color

image = data.astronaut()
gray = color.rgb2grey(image) #conversion to grayscale
color = color.grey2rgb(img)  #back to colour

print(gray.shape)
print(color.shape)

Output:

(512, 512)
(512, 512, 3)
Fig 5.2 Grayscaling image

Fig 5.2 Grayscaling image

You can try the same with other color channels like HSV (hue, saturation, value), CEILAB, XYZ, etc. Let us see an example of one of them briefly-

  • Hue: The degree on the color wheel starting with 0º at red, 120º at blue, 240º at the green and 360º back at red.
  • Saturation: The percentage of color, 0 being white and 100 being full color
  • Value: The amount of white or black color in an image.
Fig 5.3 HSV color space

Fig 5.3 HSV color space

We’ll take an example,

from skimage import data, io, color
image = data.coffee()

img = color.rgb2hsv(image)
io.imshow(img)
io.show()

Output:

Fig 5.4 RGB to HSV

Fig 5.4 RGB to HSV

Exploring further, a grayscale image can even be tinted to the color of your choice simply by zeroing-out other colors. Here’s how you do it-

from skimage import data, io, color
grayscale_image = data.camera()
image = color.gray2rgb(grayscale_image)

red_multiplier = [1, 0, 0]
yellow_multiplier = [1, 1, 0]

io.imshow(yellow_multiplier * image)
io.show()
io.imshow(red_multiplier * image)
io.show()
Fig. 5.5 Image tinting

Fig. 5.5 Image tinting

6. Editing an image using scikit-image

1. Applying filters

Scikit-image incorporates a wide variety of image editing tools. Filters module is one of them which assists in various thresholding techniques and applying numerous filter algorithms onto an image.

from skimage import filters
from skimage import data, io

image = data.astronaut()
image_median = filters.median(image)

io.imshow(image_median)
io.show()

Median returns a smoothened out image. Comparing with the original, here’s how the output will appear like.

Fig 6.1 Smooth image and Original image

Fig 6.1 Smooth image and Original image

2. Adjusting brightness

Exposure module in scikit-image is highly useful for analyzing image light intensities using histograms.

from skimage import exposure, io, data
image = data.rocket()
image_bright = exposure.adjust_gamma(image, gamma=0.5)
image_dark = exposure.adjust_gamma(image, gamma=2)

io.imshow(image)
io.show()

io.imshow(image_bright)
io.show()

io.imshow(image_dark)
io.show()

By default, the gamma value is 1.

Output:

Fig. 6.2 Original, Lighter and darker images (from left to right)

Fig. 6.2 Original, Lighter and darker images (from left to right)

7. Image Segmentation using scikit-image

The process of dividing an image into segments or better known as pixels for highlighting and detecting areas of interest in an image which would help in more effective image analysis is known as Image Segmentation. There are many algorithms such as Chan-Vese, Random walker, Felzenswalb, etc to aid in segmenting an image. Scikit provides built-in modules of some of these algorithms in segmentation. Let us see a very simple example of image segmentation.

#import the required modules and image
from skimage import data, io, feature, segmentation
image = data.coins()

#use canny edge detector from feature module
edges = feature.canny(image, sigma=3)

#use mark_boundaries from segmentation module to mark the edges and display the image
io.imshow(segmentation.mark_boundaries(image, edges))
io.show()

The feature module contains a wide range of functions to attain object detection and image segmentation. The canny() function is one of them. It is a multi-stage edge detector which as the name goes, detects the edges of objects present in the image. We used the sigma parameter as 3; this effectively reduces the noise and gives a clear edge.

Another module used is segmentation. The segmentation module as mentioned previously incorporates many algorithms along with various object detection and image segmentation functions. We used mark_boundaries() that will mark the boundaries detected by the canny edge detector. The executed code will display the following output.

Fig. 7.1 Segmentation

Fig. 7.1 Segmentation

8. Histogram

Wikipedia describes image histogram as a type of histogram that acts as a graphical representation of the tonal distribution in a digital image. The intensity of an image at each different pixel depending on its color is depicted using a histogram. The red, the green and the blue each have a corresponding histogram; the intensities being 0 at pure black and 255 at pure white.

Let’s take a simple example of a histogram.

from skimage import data
import matplotlib.pyplot as plt
image = data.coins()
histogram = plt.hist(image.ravel(), bins=8)
plt.show()

The histogram is plotted with the aid of plt.hist() function of Matplotlib library. The range of intensities, as mentioned previously, is from 0 to 255 i.e. a total of 256 bins. Sometimes, representing each intensity value is not needed. In those cases, we can quantize them into several groups known as bins. Here, we plotted the histogram using 8 bins.

Output:

Fig. 8.1 Histogram

Fig. 8.1 Histogram

Let’s take another example of histogram using scikit’s exposure module, together with matplotlib library.

from skimage import data
import matplotlib.pyplot as plt
from skimage.exposure import histogram
image = data.coins()
hist = histogram(image)
plt.plot(hist[0])
plt.show()

Output:

Fig 8.2 Histogram using Scikit

Fig 8.2 Histogram using Scikit

Note: Make sure you have matplotlib package installed.

The histogram has many applications in image processing which includes thresholding, adjusting brightness and contrast, analyzing an image, etc. Thresholding is known to be the simplest method image segmentation.

9. Image thresholding using scikit-image

Thresholding comes in very handy when it comes to isolating objects in an image for applications like facial recognition and object detection. It chiefly separates the background from the foreground and hence it is the simplest method of image segmentation.

Thresholding works best in high contrasted images. There are two types of thresholding in Scikit- Global and Local. The global threshold is histogram-based and performs well with a uniform background. The local threshold is adaptive and is used for images with unevenly illuminated backgrounds.

Basic steps for thresholding:

  1. Convert an RGB image to grayscale.
  2. Set a threshold value, say, 127.
  3. Use “>” operator for thresholding and “<=” for inverted thresholding.
  4. Show the image.
from skimage import data, io

image = data.camera()
thresh = 127

binary = image > thresh 
#binary = image <= thresh --for inverted thresholding 

io.imshow(binary)
io.show()
Fig 9 Threshold and Inverted Threshold

Fig 9 Threshold and Inverted Threshold

1. Global threshold

As mentioned above, global thresholding is applied when the image is highly contrasted and has a uniform background. Initially, let’s call all the global thresholding algorithms.  Applying them on the image selected presents the output of multiple images.

from skimage.filters import try_all_threshold
from skimage import data, io
image = data.page()
thresh = try_all_threshold(image)
io.show()

Output:

Fig 9.1.1 All global thresholds

Fig 9.1.1 All global thresholds

Or we can take one of them, suppose, threshold_otsu.

from skimage.filters import threshold_otsu
from skimage import data, io

image = data.page()

thresh = threshold_otsu(image)
binary = image > thresh

io.imshow(binary)
io.show()

Output:

Fig 9.1.2 Global threshold Otsu

2. Local threshold

When in doubt, use the local threshold. Local threshold divides the image into small regions and applies the thresh value to it.

from skimage.filters import threshold_local
from skimage import data, io

image = data.page()

thresh = threshold_local(image, block_size=35, offset=10)
binary = image > thresh

io.imshow(binary)
io.show()

We’ve set the block_size to 35 and offset to 10 which is the constant to balance the opposite contrast for obtaining a clearer image.

Output:

Fig 9.2.1 Local threshold

Fig 9.2.1 Local threshold

Through observations, it is clear that Local threshold achieves better results in this case.

End Notes

The more you practice, the more you’ll uncover and discover the possibilities.

Summing-up the entire tutorial of scikit-image, we started with basic installation and importing of skimage package.  Next, we displayed and saved the images using the io module. Going further, we learned shape manipulation followed by color manipulation in scikit-image. Under shape manipulation, we basically worked with transform library for rotation and resizing of images. Colour manipulation fundamentally divided the images into grayscale and colored images. Operating on various color channels as well as conversions between different color models were done using the color module.

Advancing deeper, we discovered scikit-image highly aids in the process of editing images. Though there can be numerous tools to effectively achieve the edits desired, we implemented two of them. The filters module which used the median function and the exposure module which adjusted the gamma correction of the image.

And finally, we arrived at the most significantly applied approach which has abundant applications in diverse fields. The Image Segmentation. Image Segmentation guided us to realize that a digital image is, in fact, an array of pixelled numbers. Scikit-image provides many image segmentation algorithms. Initiating a basic object detection program, we detected edges of the object present in the image and marked boundaries.

Histograms give explicit details on the image intensities. Hence, we plotted histograms using both matplotlib and scikit-image libraries. Ultimately winding-up our journey through scikit-image learning, we lastly implemented thresholding. There were various algorithms to achieve the optimal thresh value, and it was the simplest method of attaining image segmentation.

Concluding, there are innumerable applications of scikit-image in image processing and many more advanced functions that when combined with other libraries like NumPy and Scipy would produce amazing results. Scikit-image being python-based and extremely well documented is thus highly preferred.

Scikit-image is well documented; you can find detailed documentation on its official website, here.

Also read: Malaria Image prediction in Python using Machine Learning

Leave a Reply

Your email address will not be published. Required fields are marked *