Image Processing

Idea: Replace each pixel value with a function of its neighborhood using a filter kernel (e.g. a 3x3 matrix).

Standard Filters

Average

Replace each pixel with the average of its neighborhood using a filter kernel like

\[ \frac{1}{9} \cdot \begin{pmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{pmatrix} \]

Sharpen

To sharpen the original image, add the subtraction of the blurred image from the original image to the original image.

\[ \begin{pmatrix} 0 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 0 \end{pmatrix} - \frac{1}{9} \cdot \begin{pmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{pmatrix} + \begin{pmatrix} 0 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 0 \end{pmatrix} = \begin{pmatrix} -\frac{1}{9} & -\frac{1}{9} & -\frac{1}{9} \\ -\frac{1}{9} & 2 - \frac{1}{9} & -\frac{1}{9} \\ -\frac{1}{9} & -\frac{1}{9} & -\frac{1}{9} \end{pmatrix} \]

Gaussian Blur

Weight neighboring pixels by a Gaussian distribution \[ G_\sigma = \frac{1}{2\pi\sigma^2} \cdot e^{-\frac{x^2+y^2}{2\sigma^2}}
\]

e.g. for a 5x5 kernel with \( \sigma = 1 \)

\[ \begin{pmatrix} 0.003 & 0.013 & 0.022 & 0.013 & 0.003 \\ 0.013 & 0.059 & 0.097 & 0.059 & 0.013 \\ 0.022 & 0.097 & 0.159 & 0.097 & 0.022 \\ 0.013 & 0.059 & 0.097 & 0.059 & 0.013 \\ 0.003 & 0.013 & 0.022 & 0.013 & 0.003 \end{pmatrix} \]

Gradient filters / Edge detection

The gradient \(\mathrm{grad}(f) = \begin{pmatrix} \frac{\partial f}{\partial x} & \frac{\partial f}{\partial y} \end{pmatrix}^T\) measures the rate of change of function \(f\) in the \(x\) and \(y\) directions. Hence, the magnitude \(|\mathrm{grad}(f)|\) measures how quickly the function changes.

image

Applying a filter using convolution

import numpy as np

def convolve(image, kernel):
    # Pad image with zeros to avoid boundary effects
    padded_image = np.pad(image, kernel.shape[0] // 2, mode='constant')
    output = np.zeros_like(image)
    
    # Loop over every pixel of the image
    for x in range(image.shape[1]):
        for y in range(image.shape[0]):
            output[y, x] = (kernel * padded_image[y:y + kernel.shape[0], x:x + kernel.shape[1]]).sum()
    return output

kernel = np.ones((3, 3)) / 9
filtered_image = convolve(my_image, kernel)