%%capture
!pip install kornia
!pip install kornia-rs
Introduction to 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.
Prepare the image
With kornia.morphology
, you can apply morphological operators in 3 channel color images. Besides, all operators are differentiable. Let’s download the image
import io
import requests
def download_image(url: str, filename: str = "") -> str:
= url.split("/")[-1].split("?")[0] if len(filename) == 0 else filename
filename # Download
= io.BytesIO(requests.get(url).content)
bytesio # Save file
with open(filename, "wb") as outfile:
outfile.write(bytesio.getbuffer())
return filename
download_image("https://image.shutterstock.com/image-photo/portrait-surprised-cat-scottish-straight-260nw-499196506.jpg", "img.jpg"
)
'img.jpg'
Imports and read the image
import kornia as K
import torch
= "cpu" # 'cuda:0' for GPU device
= K.io.load_image("img.jpg", K.io.ImageLoadType.RGB32, device=device)[None, ...] img_t
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.
= torch.tensor([[0, 1, 0], [1, 1, 1], [0, 1, 0]]).to(device) kernel
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
= K.tensor_to_image(tensor.squeeze(0)) # Tensor to image
image
# Plot before-after
"figure.figsize"] = 20, 20
rcParams[= plt.subplots(1, 2)
fig, ax 0].axis("off")
ax[0].imshow(K.tensor_to_image(img_t))
ax[1].axis("off")
ax[1].imshow(image) ax[
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
= morph.dilation(img_t, kernel) # Dilation
dilated_image # Plot plot_morph_image(dilated_image)
Erosion
= morph.erosion(img_t, kernel) # Erosion
eroded_image # Plot plot_morph_image(eroded_image)
Open
= morph.opening(img_t, kernel) # Open
opened_image plot_morph_image(opened_image)
Close
= morph.closing(img_t, kernel) # Close
closed_image # Plot plot_morph_image(closed_image)
Morphological Gradient
= morph.gradient(img_t, kernel) # Morphological gradient
graded_image 1.0 - graded_image) plot_morph_image(
Bottom Hat
= morph.bottom_hat(img_t, kernel) # Black Hat
bottom_image 1.0 - bottom_image) plot_morph_image(
Top Hat
= morph.top_hat(img_t, kernel) # Top Hat
toph_image 1.0 - toph_image) plot_morph_image(
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!