Task

Apply repeatedly the 3 by 3 blurring kernel to the image of the full car plate, until the digits are no longer recognizable.

Original car plate image and Blurred car plate after 20 iterations

Figure 1: Original image on the left and filtered image after applying the blur 20 times on the right.

After 20 blurring iterations, the image has been completely blurred and the numbers are no longer recognizable. Notice that a black outline has appeared around the image, even though the original one does not have many black pixels in that region: this is due to the black padding that has been added at each iteration. The zero padding pixels are averaged with the image ones, effectively darkening the result. More sophisticated padding techniques can be used to avoid this effect, such as creating a padding that repeats the values of the pixels on the image border.

In order to blur the image, we replace each pixel with its average with its 8 neighbors. Averaging pixel values has the effect of smoothing the image: a light smoothing effect can be used to remove noise from an image, while a more aggressive smoothing can erase details altogether.

We formalized this procedure as a discrete convolution, denoted with the symbol  * , between the input image A and a second matrix K, called kernel: given an input image A \in \mathbb{R}^{M \times N}, a kernel K \in \mathbb{R}^{(2r+1)\times(2r+1)}, the discrete convolution of A and K is an image R \in \mathbb{R}^{(M-2r)\times(N-2r)}, defined as:

 R_{i,j} = (A * K)_{i,j} = \sum_{m=0}^{2r}\sum_{n=0}^{2r} A_{i+m, j+n} K_{m,n}

The gray-level value of each pixel of the output image R is the weighted sum of pixels in the  (2r+1)\times(2r+1) neighborhood around the corresponding pixel in the input image, with the weights equal to the elements of the kernel.


Now that you have all the information you need to complete the task, use at least one of the two workspaces from previous lessons (Python or MATLAB) and write the code that gives the correct solution.

To achieve this, we need to call im_filtering in a loop. At each iteration, we filter the result of the previous one after having reapplied the padding using the for loop as follows:


# Number of times to apply the blur
N = 20

for i in range(N):
    R = im_filtering(Ap, K)
    # Reapply the padding to the blurred image
    Ap[1:-1, 1:-1] = R

The complete Python code for the solution is the following:


import numpy as np
from PIL import Image
from helper_functions import *

def local_convolution(A, K, i, j):
    v = 0
    for m in range(3):
        for n in range(3):
            v += A[i - 1 + m, j - 1 + n] * K[m, n]
    return v

def im_filtering(A, K):
    rows, cols = A.shape
    # Create an output matrix for the result
    R = np.zeros(shape=(rows - 2, cols - 2))

    for i in range(1, rows - 1):        # internal rows
        for j in range(1, cols - 1):    # internal columns
            R[i - 1, j - 1] = local_convolution(A, K, i, j)
    return R

# Load the image and convert it to gray scale
A = np.array(Image.open("plate.png").convert('L'))

# Create the convolution kernel
K = np.ones((3, 3)) / 9

# Padding
Ap = np.zeros((A.shape[0] + 2, A.shape[1] + 2))
Ap[1:-1, 1:-1] = A

# Number of times to apply the blur
N = 20

for i in range(N):
    R = im_filtering(Ap, K)
    # Reapply the padding to the blurred image
    Ap[1:-1, 1:-1] = R

compare_images(A, R)

To achieve this, we need to call im_filtering in a loop. At each iteration, we filter the result of the previous one after having reapplied the padding using the for loop as follows:


% Number of times to apply the blur
N = 20

for i = 1 : 20
    R = im_filtering(Ap, K)
    % Reapply the padding to the blurred image
    Ap(2 : end - 1, 2 : end - 1) = R
end

The complete Matlab code for the solution is the following:


% Load the image and convert it to gray scale
A = double(rgb2gray(imread("plate.png")));

% Create the convolution kernel
K = ones(3, 3) / 9;

% Padding
Ap = zeros(size(A, 1) + 2, size(A, 2) + 2);
Ap(2 : end - 1, 2 : end - 1) = A;

% Number of times to apply the blur
N = 20;

for i = 1 : 20
    R  = im_filtering(Ap, K);
    % Reapply the padding to the blurred image
    Ap(2 : end - 1, 2 : end - 1) = R;
end

R = uint8(R);
compare_images(A, R)