Introduction
- Simple Python and scikit-image techniques can be used to solve genuine image analysis problems.
 - Morphometric problems involve the number, shape, and / or size of the objects in an image.
 
Image Basics
- Digital images are represented as rectangular arrays of square pixels.
 - Digital images use a left-hand coordinate system, with the origin in the upper left corner, the x-axis running to the right, and the y-axis running down. Some learners may prefer to think in terms of counting down rows for the y-axis and across columns for the x-axis. Thus, we will make an effort to allow for both approaches in our lesson presentation.
 - Most frequently, digital images use an additive RGB model, with eight bits for the red, green, and blue channels.
 - scikit-image images are stored as multi-dimensional NumPy arrays.
 - In scikit-image images, the red channel is specified first, then the green, then the blue, i.e., RGB.
 - Lossless compression retains all the details in an image, but lossy compression results in loss of some of the original image detail.
 - BMP images are uncompressed, meaning they have high quality but also that their file sizes are large.
 - JPEG images use lossy compression, meaning that their file sizes are smaller, but image quality may suffer.
 - TIFF images can be uncompressed or compressed with lossy or lossless compression.
 - Depending on the camera or sensor, various useful pieces of information may be stored in an image file, in the image metadata.
 
Working with scikit-image
- Images are read from disk with the 
iio.imread()function. - We create a window that automatically scales the displayed image
with Matplotlib and calling 
imshow()on the global figure object. - Colour images can be transformed to grayscale using
ski.color.rgb2gray()or, in many cases, be read as grayscale directly by passing the argumentmode="L"toiio.imread(). - We can resize images with the 
ski.transform.resize()function. - NumPy array commands, such as
image[image < 128] = 0, can be used to manipulate the pixels of an image. - Array slicing can be used to extract sub-images or modify areas of
images, e.g., 
clip = image[60:150, 135:480, :]. - Metadata is not retained when images are loaded as NumPy arrays
using 
iio.imread(). 
Drawing and Bitwise Operations
- We can use the NumPy 
zeros()function to create a blank, black image. - We can draw on scikit-image images with functions such as
ski.draw.rectangle(),ski.draw.disk(),ski.draw.line(), and more. - The drawing functions return indices to pixels that can be set directly.
 
Creating Histograms
- In many cases, we can load images in grayscale by passing the
mode="L"argument to theiio.imread()function. - We can create histograms of images with the
np.histogramfunction. - We can display histograms using 
ax.plot()with thebin_edgesandhistogramvalues returned bynp.histogram(). - The plot can be customised using 
ax.set_xlabel(),ax.set_ylabel(),ax.set_xlim(),ax.set_ylim(), andax.set_title(). - We can separate the colour channels of an RGB image using slicing operations and create histograms for each colour channel separately.
 
Blurring Images
- Applying a low-pass blurring filter smooths edges and removes noise from an image.
 - Blurring is often used as a first step before we perform thresholding or edge detection.
 - The Gaussian blur can be applied to an image with the
ski.filters.gaussian()function. - Larger sigma values may remove more noise, but they will also remove detail from an image.
 
Thresholding
- Thresholding produces a binary image, where all pixels with intensities above (or below) a threshold value are turned on, while all other pixels are turned off.
 - The binary images produced by thresholding are held in two-dimensional NumPy arrays, since they have only one colour value channel. They are boolean, hence they contain the values 0 (off) and 1 (on).
 - Thresholding can be used to create masks that select only the interesting parts of an image, or as the first step before edge detection or finding contours.
 
Connected Component Analysis
- We can use 
ski.measure.labelto find and label connected objects in an image. - We can use 
ski.measure.regionpropsto measure properties of labeled objects. - We can use 
ski.morphology.remove_small_objectsto mask small objects and remove artifacts from an image. - We can display the labeled image to view the objects coloured by label.
 
Capstone Challenge
- Using thresholding, connected component analysis and other tools we can automatically segment images of bacterial colonies.
 - These methods are useful for many scientific problems, especially those involving morphometrics.