OpenCV in Python: Morphological Transformations

Morphological Transformation OpenCV header

Image processing is a crucial field in multiple disciplines, from medical applications to industrial automation. OpenCV (Open Source Computer Vision Library) represents a powerful tool in this context, offering a wide range of features for image manipulation and analysis. Among the most used techniques are morphological transformations, which allow you to model the shape of objects in an image.

[wpda_org_chart tree_id=38 theme_id=50]

This article will focus on morphological transformations in OpenCV using the Python programming language. We will explore how these operations can be employed to manipulate the shape of objects in an image, opening the door to a wide range of practical applications.

Morphological Transformations

Morphological transformations play a crucial role in image processing and computer vision. They help address common challenges such as removing noise, separating connected objects, and closing gaps in images. Understanding these techniques is critical for those who work with visual data, as they provide powerful tools for improving the quality and usefulness of processed images.

Binary Images and Grayscale

To fully understand morphological transformations, it is essential to have a solid understanding of binary and grayscale images. A binary image is composed of only black and white pixels, with no shades in between. These images are often used to represent on/off or presence/absence information.

Grayscale images, on the other hand, contain pixel intensity levels ranging from 0 (black) to 255 (white), with shades of gray in between. These images are more realistic and contain a greater amount of information than binary images.

Kernel

The kernel is a square or rectangular matrix of defined dimensions that is used in morphological transformations. It is placed on the image and scans across the pixels. The values in the kernel affect the transformation of the corresponding pixel in the output image.

Kernel values are often defined as 0 and 1, where 1 represents the region of interest. For example, a 3×3 sized kernel might look like this:

1 1 1
1 1 1
1 1 1

This uniform kernel is commonly used in operations such as dilation and erosion.

Practical Implementation

Before proceeding with morphological transformations, it is essential to load an image and convert it to the appropriate format, usually grayscale. This preparatory step is essential to ensure that the transformations can be applied correctly.

Let’s start with an image like the following (the Mole Antonelliana of Turin) which we will call Torino.jpg and which we will use throughout the article:

Torino
import cv2
import numpy as np
import matplotlib.pyplot as plt

# Upload a color image
image = cv2.imread('Torino.jpg')

# Convert the image to grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Displays the image in grayscale
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale image')
plt.axis('off')  # Nasconde gli assi
plt.show()

Performing the conversion you will obtain the new image:

Torino - grayscale image

With this preliminary understanding, we can proceed to explore basic morphological transformations, such as erosion and dilation, in subsequent sections.

Erosion

Erosion is one of the fundamental morphological transformations used in OpenCV to manipulate the shape of objects in an image. This operation involves reducing the regions of interest, eliminating the outlines and narrowing the characteristics of the objects present.

Erosion occurs by applying a kernel to the image, placing it on each pixel, and changing the pixel value based on the values in the kernel. If all pixels covered by the kernel are “active” (with a value of 1), the central pixel retains its value; otherwise, it is “eroded” (set to 0).

The result is a reduction in the size of objects in the image, making them thinner and more separated.

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Upload a grayscale image
img = cv2.imread('Torino.jpg', 0)

# Define the kernel for erosion
kernel = np.ones((5, 5), np.uint8)

# Apply erosion to the image
erosion = cv2.erode(img, kernel, iterations=1)

# Displays the original and eroded image
plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.imshow(img, cmap='gray')
plt.axis('off')  # Hides the axes
plt.title('Original Image')

plt.subplot(1, 2, 2)
plt.imshow(erosion, cmap='gray')
plt.axis('off')  # Hides the axes
plt.title('Image After Erosion')

plt.show()

In the sample code, the grayscale image is eroded using a square kernel of size 5×5. The effect of erosion is highlighted by viewing the image before and after applying the operation.

Torino - Erosion image

Erosion has applications in a variety of contexts, including removing noise, separating connected objects, and establishing more precise boundaries between objects. In the next paragraphs, we will explore practical applications of erosion through specific examples and further implementation details.

The Dilation

Dilation is another fundamental operation in morphological transformations, often used in combination with erosion. Dilation works to expand the regions of interest in an image, increasing the size of the objects present.

Similar to erosion, dilation involves applying a kernel to the image. However, in this case, the value of the central pixel in the output image is determined by considering the pixels covered by the kernel. If at least one of them is “active” (with a value of 1), the central pixel is set to 1.

The result is an increase in the size of objects, merging separate regions and closing any holes present.

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Upload a grayscale image
img = cv2.imread('Torino.jpg', 0)

# Define the kernel for dilation
kernel = np.ones((5, 5), np.uint8)

# Apply dilation to the image
dilation = cv2.dilate(img, kernel, iterations=1)

# Displays the original and dilated image
plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.imshow(img, cmap='gray')
plt.axis('off')  
plt.title('Original Image')

plt.subplot(1, 2, 2)
plt.imshow(dilation, cmap='gray')
plt.axis('off')
plt.title('Image after Dilation')

plt.show()

In the example code, the grayscale image is stretched using a square kernel of size 5×5. The difference between the original image and the dilated one is highlighted through the display.

Torino - Dilatation Image

Dilation is widely used in a variety of situations, such as filling holes in images, connecting separate components, and making objects more prominent. In the next paragraphs, we will explore practical applications of dilation with specific examples and implementation details.

The Opening and Closing

The opening and closing operations are combinations of erosion and dilation that allow more specific results to be obtained in morphological transformations.

Opening is a sequence of erosion followed by dilation. This is useful for removing noise in the image, separating connected objects and opening them, as well as maintaining the dimensions of the original objects.

Closure is the reverse operation, i.e. a sequence of dilation followed by erosion. This technique is effective at closing small holes in the image, merging regions of objects, and maintaining the overall shape of the original objects.

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Upload a grayscale image
img = cv2.imread('Torino.jpg', 0)

# Define the kernel for opening and closing
kernel = np.ones((5, 5), np.uint8)

# Apply the opening
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

#Apply the closure
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

# Displays the original image and those that have been opened and closed
plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.imshow(opening, cmap='gray')
plt.axis('off') 
plt.title('Immage after Opening')

plt.subplot(1, 2, 2)
plt.imshow(closing, cmap='gray')
plt.axis('off')  
plt.title('Immage after Closing')

plt.show()

In the example code, the opening and closing are applied to the grayscale image using a square kernel of size 5×5. Observe how these operations affect the removal of noise and the closing of any holes.

Torino - Opening and Closing

Opening and closing are particularly useful in contexts where it is necessary to clean the image or maintain certain characteristics of the objects. In the next sections, we will explore specific cases where these operations are crucial, providing implementation details and visual results.

Leave a Reply