Pixel-Level Operations refer to a category of image processing techniques that directly manipulate the pixel values within an image based on their local intensity, color, or other attributes, without altering their spatial coordinates. Unlike Coordinate Transformations—such as translation, rotation, shear, and perspective transformation—that change the geometric arrangement of pixels by moving them to new locations, pixel-level operations focus on modifying the intensity or color of each pixel based on certain rules or filters.
These operations are essential for enhancing image quality, extracting important features, and preparing images for further analysis. Common pixel-level operations include spatial filtering, which smooths or sharpens an image, and edge and corner detection, which identifies object boundaries and key points. By applying these techniques, we can reduce noise, enhance details, and highlight features crucial for tasks like object recognition, segmentation, and computer vision.
Spatial filtering works by convolving a filter (or kernel) with the image. A kernel is a small matrix that slides over the image, modifying each pixel's value based on its neighbors. The kernel is applied to each pixel in the image to calculate a new pixel value. Common sizes for kernels include 3x3, 5x5, and 7x7 matrices. We still use the Lenna image.
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
!wget <https://raw.githubusercontent.com/yyhtbs-yye/data4wget/main/images/image_proc_lenna.png>
# Load the image
image = np.array(Image.open('image_proc_lenna.png'))
The convolution (convolving) operation involves sliding the kernel over each pixel of the image, multiplying the kernel's coefficients by the pixel values they overlap, and summing up the results to produce the new pixel value. Spatial filters can be categorized based on their effect on the image:
Low-pass filters smooth the image by averaging the pixel values within a specified neighborhood. They are often used to reduce noise and soften sharp transitions in images.
Averaging Filter (Mean Filter)
The averaging filter replaces each pixel's value with the average value of its neighbors, using a kernel such as:
$$ K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix} $$
To understand why this filter can effectively reduce noise, we first need to understand what noise looks like in an image. Noise (specifically, additive thermal noise or standard Gaussian noise) affects an image by randomly altering the intensity of different pixels to some degree. As a result, we observe anomalous color spots, which could appear as bright or dark specks in grayscale images.
Additional Note: Standard Gaussian noise has a key characteristic: its mean tends to zero. The more values are averaged, the closer the result will approach zero.
The reason the averaging filter is used for noise reduction is that it works by averaging the pixel values within a local neighborhood to update the central pixel's value. If the noise is relatively dense and widespread, then due to the properties of noise, a 3x3 kernel will compute the average of the surrounding noise for each pixel. This averaging process reduces the influence of noise on the pixel's intensity, driving it closer to zero. As a result, the noise becomes less visible, effectively smoothing out the image.
from scipy.ndimage import convolve
# Define the averaging filter (mean filter) kernel
kernel = np.ones((7, 7)) / 49.0
# Separate the RGB channels and apply the convolution on each channel
smoothed_channels = []
for channel in range(3):
smoothed_channel = convolve(noisy_image_np[:, :, channel], kernel)
smoothed_channels.append(smoothed_channel)
# Stack the smoothed channels back together to form the smoothed RGB image
smoothed_image_np = np.stack(smoothed_channels, axis=-1)
# Convert the smoothed NumPy array back to a PIL image
smoothed_image = Image.fromarray(smoothed_image_np.astype(np.uint8))
Important: There's no free lunch when it comes to noise reduction. While this kernel effectively reduces noise, it also causes the edges of the image to become blurred. Let's apply the filter to a simple image and examine the results below.
You'll notice that the image becomes noticeably blurred. This blurring occurs because the filter "spreads" the original pixel values to their neighboring positions. This happens because, during convolution, each pixel contributes to the output for all the pixels within its 3x3 neighborhood, resulting in a smoothing effect that blurs fine details and edges.
Gaussian Filter