Open in Colab

Introduction to Morphological Operators#

In this tutorial you are gonna explore kornia.morphology, that’s Kornia’s module for differentiable Morphological Operators.

By the end, you will be able to use morphological operations as easy as:

new_image = morph.operation(original_image, structuring_element)

But first things first, let’s prepare the environment.

Download Kornia#

If you don’t have Kornia installed, you can download it using pip.

%%capture
!pip install git+https://github.com/kornia/kornia

Prepare the image#

With kornia.morphology, you can apply morphological operators in 3 channel color images. Besides, all operators are differentiable. Let’s download and read an image.

%%capture
!wget 'https://image.shutterstock.com/image-photo/portrait-surprised-cat-scottish-straight-260nw-499196506.jpg' -O img.jpg

We can use can use OpenCV to load the image.

import cv2
 
img = cv2.imread("img.jpg") # Download Image
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # Define RGB

Structuring element#

We have the original image ready to go, now we need the second part in the operation, the structuring element (aka Kernel).

The kernel must be a 2-dim tensor with odd sides, i.e. 3x3.

import torch
import kornia as K

device = 'cpu' # 'cuda:0' for GPU
kernel = torch.tensor([[0, 1, 0],[1, 1, 1],[0, 1, 0]]).to(device)

# to torch.tensor
img_t = K.image_to_tensor(img, keepdim=False)
img_t = img_t.float() / 255.
/home/docs/checkouts/readthedocs.org/user_builds/kornia-tutorials/envs/latest/lib/python3.7/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm

Making plots!#

In this tutorial we are gonna compare the images before and after transforming them.

It make sense to create a function to plot and see the changes!

import matplotlib.pyplot as plt
from matplotlib import rcParams

def plot_morph_image(tensor):

  # kornia.tensor_to_image
  image = K.tensor_to_image(tensor.squeeze(0)) # Tensor to image

  # Plot before-after
  rcParams['figure.figsize'] = 20 ,20
  fig, ax = plt.subplots(1,2)
  ax[0].axis('off')
  ax[0].imshow(img)
  ax[1].axis('off')
  ax[1].imshow(image)

Morphology#

The main goal of kornia.morphology is that you could easily implement several morphological operator as follows:

new_image = morph.operation(original_image, structuring_element)

Let’s check them all!

Dilation#

from kornia import morphology as morph

dilated_image = morph.dilation(img_t, kernel) # Dilation
plot_morph_image(dilated_image) # Plot
_images/62c4f5ee8c70655b1a0c67ddbea7b09b22735d2ef3bda937781d8d69e19289ec.png

Erosion#

eroded_image = morph.erosion(img_t, kernel) # Erosion
plot_morph_image(eroded_image) # Plot
_images/aacf299d62171e51dc59fbd29ef32cf8fc203545828d5b34026552b42dbe0780.png

Open#

opened_image = morph.opening(img_t, kernel) # Open
plot_morph_image(opened_image)
_images/0d5c68adecb66c7aa287e11eb32e7b5f30ee191965f7e1324047302e4c99181c.png

Close#

closed_image = morph.closing(img_t, kernel) # Close
plot_morph_image(closed_image) # Plot
_images/7a9b9d6b2d1150e765c62b6dab98cedd9ac06669dfc298f8f93a05b7af0562d1.png

Morphological Gradient#

graded_image = morph.gradient(img_t, kernel) # Morphological gradient
plot_morph_image(1. - graded_image)
_images/7cdc3d4102948521f079531150a5a6587afe0042f6ff0e26889161124013c1d7.png

Bottom Hat#

bottom_image = morph.bottom_hat(img_t, kernel) # Black Hat
plot_morph_image(1. - bottom_image)
_images/bb4a6eb664810b4d3ae76ec1ecbec473baf8702df7f05cf6da9f23e65dfa75ff.png

Top Hat#

toph_image = morph.top_hat(img_t, kernel) # Top Hat
plot_morph_image(1. - toph_image)
_images/2a5e16fe331a28625eabd3ff19e7adfbed6458ae281fe6f4be3f0e5c01af0e1f.png

Conclusion#

And that’s it!

Now you know how to use Kornia to apply differentiable morphological operations in your PyTorch pipeline.

Many thanks for using Kornia, and have fun!