Filtering Operators

Basic
kornia.filters
Blur
In this tutorial we are going to learn how to apply blurring and sharpening filters to images with kornia.filters components.
Author

Edgar Riba

Published

July 6, 2021

Open in google colab

Open in HF Spaces

%%capture
!pip install kornia
!pip install kornia-rs
import io

import requests


def download_image(url: str, filename: str = "") -> str:
    filename = url.split("/")[-1] 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


url = "https://github.com/kornia/data/raw/main/doraemon.png"
download_image(url)
import kornia as K
import kornia.utils
import numpy as np
import torch
import torchvision
from matplotlib import pyplot as plt
from PIL import Image

We use Kornia to load an image to memory represented directly in a tensor

x_rgb: torch.Tensor = (K.image_to_tensor(np.array(Image.open("doraemon.png").convert("RGB"))).float() / 255.0)[
    None, ...
]  # BxCxHxW

x_gray = K.color.rgb_to_grayscale(x_rgb)
def imshow(input: torch.Tensor):
    if input.shape != x_rgb.shape:
        input = K.geometry.resize(input, size=(x_rgb.shape[-2:]))
    out = torch.cat([x_rgb, input], dim=-1)
    out = torchvision.utils.make_grid(out, nrow=2, padding=5)
    out_np = K.utils.tensor_to_image(out)
    plt.imshow(out_np)
    plt.axis("off")
    plt.show()
imshow(x_rgb)

Box Blur

x_blur: torch.Tensor = K.filters.box_blur(x_rgb, (9, 9))
imshow(x_blur)

Blur Pool

x_blur: torch.Tensor = K.filters.blur_pool2d(x_rgb, kernel_size=9)
imshow(x_blur)

Gaussian Blur

x_blur: torch.Tensor = K.filters.gaussian_blur2d(x_rgb, (11, 11), (11.0, 11.0))
imshow(x_blur)

The GaussianBlur2d module

Besides the functional API used above, kornia also provides the GaussianBlur2d module, which can be composed inside nn.Sequential pipelines. We first import the required libraries and download a second example image.

import kornia
import numpy as np
from PIL import Image

kornia.__version__

Now we download the example image.

import io

import requests


def download_image(url: str, filename: str = "") -> str:
    filename = url.split("/")[-1] 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


url = "https://github.com/kornia/data/raw/main/bennett_aden.png"
download_image(url)
import matplotlib.pyplot as plt
import torch

# read the image with kornia
data = kornia.image_to_tensor(np.array(Image.open("./bennett_aden.png").convert("RGB"))).float()[None, ...] / 255.0  # BxCxHxW

To apply a filter, we create the Gaussian Blur filter object and apply it to the data:

# create the operator
gauss = kornia.filters.GaussianBlur2d((11, 11), (10.5, 10.5))

# blur the image
x_blur: torch.tensor = gauss(data)

That’s it! We can compare the pre-transform image and the post-transform image:

# convert back to numpy
img_blur = kornia.tensor_to_image(x_blur)

# Create the plot
fig, axs = plt.subplots(1, 2, figsize=(16, 10))
axs = axs.ravel()

axs[0].axis("off")
axs[0].set_title("image source")
axs[0].imshow(kornia.tensor_to_image(data))

axs[1].axis("off")
axs[1].set_title("image blurred")
axs[1].imshow(img_blur)

pass

Max Pool

x_blur: torch.Tensor = K.filters.max_blur_pool2d(x_rgb, kernel_size=11)
imshow(x_blur)

Median Blur

x_blur: torch.Tensor = K.filters.median_blur(x_rgb, (5, 5))
imshow(x_blur)

Motion Blur

x_blur: torch.Tensor = K.filters.motion_blur(x_rgb, 9, 90.0, 1)
imshow(x_blur)

Unsharp Mask (sharpening)

Filtering is not only about blurring: the unsharp mask operator uses a gaussian blur internally to sharpen an image. We download one more example image and apply kornia.filters.UnsharpMask to it.

import kornia
import kornia.utils
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

kornia.__version__

Downloading the example image.

import io

import requests


def download_image(url: str, filename: str = "") -> str:
    filename = url.split("/")[-1] 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


url = "https://github.com/kornia/data/raw/main/squirrel.jpg"
download_image(url)
# Read the image with Kornia
data = kornia.image_to_tensor(np.array(Image.open("squirrel.jpg").convert("RGB"))).float()[None, ...] / 255.0  # BxCxHxW

We create Unsharp Mask filter object and apply it to data. The unsharp mask filter is initialized with the format kornia.filters.UnsharpMask(kernel_size, sigma). You can tune these parametres and experiment!

sharpen = kornia.filters.UnsharpMask((9, 9), (2.5, 2.5))
sharpened_tensor = sharpen(data)
difference = (sharpened_tensor - data).abs()
# Converting the sharpened tensor to image
sharpened_image = kornia.utils.tensor_to_image(sharpened_tensor)
difference_image = kornia.utils.tensor_to_image(difference)

So, let us understand how we arrived till here.

  1. In the unsharp mask technique, first a gaussian blur is applied to the data.
  2. Then the blur is subtracted from the orignal data.
  3. The resultant is added to the origanl data.
  4. So, what do we get? Sharpened data!
# To display the input image, sharpened image and the difference image
fig, axs = plt.subplots(1, 3, figsize=(16, 10))
axs = axs.ravel()

axs[0].axis("off")
axs[0].set_title("image source")
axs[0].imshow(kornia.tensor_to_image(data))

axs[1].axis("off")
axs[1].set_title("sharpened")
axs[1].imshow(sharpened_image)

axs[2].axis("off")
axs[2].set_title("difference")
axs[2].imshow(difference_image)
plt.show()