%%capture
!pip install kornia
!pip install kornia-rsIntroduction 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:
filename = url.split("/")[-1].split("?")[0] if len(filename) == 0 else filename
# Download
bytesio = io.BytesIO(requests.get(url).content)
# 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
device = "cpu" # 'cuda:0' for GPUimg_t = K.io.load_image("img.jpg", K.io.ImageLoadType.RGB32, device=device)[None, ...]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.
kernel = torch.tensor([[0, 1, 0], [1, 1, 1], [0, 1, 0]]).to(device)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(K.tensor_to_image(img_t))
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
Erosion
eroded_image = morph.erosion(img_t, kernel) # Erosion
plot_morph_image(eroded_image) # Plot
Open
opened_image = morph.opening(img_t, kernel) # Open
plot_morph_image(opened_image)
Close
closed_image = morph.closing(img_t, kernel) # Close
plot_morph_image(closed_image) # Plot
Morphological Gradient
graded_image = morph.gradient(img_t, kernel) # Morphological gradient
plot_morph_image(1.0 - graded_image)
Bottom Hat
bottom_image = morph.bottom_hat(img_t, kernel) # Black Hat
plot_morph_image(1.0 - bottom_image)
Top Hat
toph_image = morph.top_hat(img_t, kernel) # Top Hat
plot_morph_image(1.0 - toph_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!