A core part of the ImageMorphology package is grayscale or binarized images. You have already learned how to create grayscale images. Binary images are those whose pixels are represented by either 1 or 0. Most of the examples you will find in this book and online have the following standard notation:
- 0 or black is used for the background
- 1 or white is used for the foreground, that is, our object
We will use the following code to create a binary image by a simple thresholding of a grayscale, that is, for example, assigning a 1 if the pixel value is over 0.5 and a 0 if it is below 0.5.
Binary and grayscale images are not perfect because they may contain numerous imperfections and are distorted by noise or texture. Morphological image transformations are targeted at removing these imperfections by using the form and structure of the image. These operations rely only on the relative ordering of the pixel values, not on their numerical values, and they are widely used to identify and process text, documents, and other shapes, such as lines and boxes.
The following code will demonstrate how to create a binary image with a threshold of 0.5. We will start by loading an image and applying a simple mathematical transformation to a grayscale version of the image:
using Images, ImageView, ImageMorphology
# load an image
img = load("sample-images/bird-3183441_640.jpg");
# convert image to grayscale and binarise the only channel
img_binary = 1 * (Gray.(img) .> 0.5);
A binary image one-liner executes three different operations:
- It converts the image to grayscale
- It converts all values over 0.5 to true and below 0.5 to false
- It converts true and false values to 1 or 0 by multiplying 1 by the result array
You can preview the original image in line with the binary version. This is achieved by following these steps:
- Scale the original and binary images using the restrict function
- Identify the width of a scaled version of the image using size
- Create a new image, using the fill function, that is twice as large in width
- Put the images in step 1 together
Consider the following code:
# resize images by half for preview
img = restrict(img)
img_binary = restrict(RGB.(Gray.(img_binary)))
# stack 2 images together in line and preview
img_width = size(img, 2)
combined_image = fill(RGB4{Float32}(0.,0.,0.), size(img) .* (1, 2))
combined_image[:, 1:img_width] = img
combined_image[:, img_width+1:img_width*2] = img_binary
imshow(combined_image)
This will result in the original image being shown together with the binarized image. This time we are lucky, and there is no noise to remove and the contours are clear, as seen in the following photos:
Morphological operations can also be applied to grayscale images so that their light transfer functions are unknown, and therefore their absolute pixel values are of no or little interest.