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 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.
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.
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()
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)
(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.
(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()
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.
5. Colour manipulation using scikit-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-
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)
(512, 512) (512, 512, 3)
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.
We’ll take an example,
from skimage import data, io, color image = data.coffee() img = color.rgb2hsv(image) io.imshow(img) io.show()
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()
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.
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.
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.
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.
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) plt.show()
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:
- Convert an RGB image to grayscale.
- Set a threshold value, say, 127.
- Use “>” operator for thresholding and “<=” for inverted thresholding.
- 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()
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()
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()
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.
Through observations, it is clear that Local threshold achieves better results in this case.
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.