Image Filtering Techniques in Image Processing — Part 1

Henrique Vedoveli
11 min readAug 25, 2023

--

1. Introduction

Image processing techniques play a pivotal role in enhancing, restoring, and analyzing digital images. This article delves into fundamental image filtering techniques, unveiling the mechanisms behind their operations, applications, and outcomes. In this first part, we explore linear image filters, with a focus on the Sobel filter, Gaussian filter, and mean filter.

2. Linear Image Filters

Linear image filters are essential tools in the realm of image processing, particularly when it comes to noise reduction. These filters operate by applying a convolution operation on an image, using a predefined kernel or filter mask. The beauty of linear filters lies in their simplicity and effectiveness in reducing various types of noise, such as salt-and-pepper noise or Gaussian noise.

The process of applying linear image filters for noise reduction involves a concept known as convolution. Convolution is the mathematical operation where the filter mask is successively overlaid on each pixel of the image, and the product of the filter’s coefficients and the corresponding pixel values is computed. This process is repeated for every pixel, resulting in a new filtered image.

One of the significant advantages of linear image filters for noise reduction is their ability to process images in near-real-time, making them suitable for applications where computational efficiency is crucial. Linear filters can be implemented using simple mathematical operations, allowing for fast processing on both hardware and software platforms. Despite their effectiveness in many scenarios, linear filters may struggle with more complex and nonlinear noise patterns, where non-linear filters come into play.

2.1 Mean Filter

Mean filtering is a widely employed technique within the realm of image processing, serving as a crucial tool for noise reduction and smoothing. By adopting spatial filtering principles, mean filtering aids in eliminating random variations or noise present in an image, all while retaining its essential features. In this context, we will explore the mechanics, advantages, and limitations of mean filtering.

The fundamental concept behind mean filtering is elegantly simple: each pixel in an image is substituted with the average value derived from neighboring pixels confined within a specified window or kernel. The size of this kernel determines the degree of smoothing, with larger kernels inducing more potent smoothing effects at the potential cost of finer detail loss.

Mean Filter applied to an image.

In essence, mean filtering involves the replacement of each pixel’s value with the average value of its neighboring pixels, including the pixel itself. This process proves effective in removing pixel values that diverge significantly from their surroundings. Conceptually aligned with a convolution filter, mean filtering revolves around a kernel that defines the shape and size of the neighborhood encompassed for mean calculation. While a standard 3×3 square kernel is frequently employed, the utilization of larger kernels — like 5×5 squares — can intensify the smoothing for more substantial noise reduction.

Mean Filters Kernels

Several iterations of mean smoothing exist, among which is Threshold Averaging. Here, smoothing is contingent upon a condition: the central pixel value undergoes alteration only if the difference between its initial value and the computed average surpasses a preset threshold. This approach efficiently reduces noise while preserving more image detail than traditional mean filtering.

In the realm of computational simplicity, mean filtering stands as an exemplar. Its straightforward implementation and efficiency render it an easily accessible tool. However, mean filtering’s suitability is not universal; images containing sharp edges or intricate details may experience edge blurring due to the averaging procedure. Notably effective against Gaussian or salt-and-pepper noise, mean filtering harnesses the context of surrounding pixels to mitigate random noise values.

While mean filtering holds its place in preprocessing images for subsequent intricate tasks like edge detection or object recognition, its significance is underscored in image restoration and enhancement processes. Notably, in domains like medical imaging, mean filtering’s application contributes to enhanced diagnostic precision and improved visual quality.

In summary, mean filtering emerges as an uncomplicated yet potent technique in image processing. Its prowess in noise reduction and texture smoothing bestows it with versatility across diverse applications. Nevertheless, judicious selection of kernel size remains pivotal to striking a balance between noise reduction and vital image feature preservation. When judiciously employed, mean filtering profoundly elevates image quality and facilitates comprehensive image analysis. Despite its computational efficiency, it is imperative to acknowledge its limitations; alternative convolution filters, such as the Gaussian smoothing filter, present distinct trade-offs between noise reduction and detail preservation.

2.1.1 Implementing the Mean Filter

import cv2
import numpy as np

def mean_filter(image, kernel_size):
# Pad the image to handle borders using zero-padding
# This ensures that the filter can be applied to border pixels as well
padded_image = cv2.copyMakeBorder(image,
kernel_size//2,
kernel_size//2,
kernel_size//2,
kernel_size//2,
cv2.BORDER_CONSTANT)

# Create an empty image to store the filtered result
filtered_image = np.zeros_like(image)

# Iterate over each pixel in the image
for y in range(image.shape[0]):
for x in range(image.shape[1]):
# Extract the local window centered at the current pixel
window = padded_image[y:y+kernel_size, x:x+kernel_size]
# Calculate the mean value of the window
mean_value = np.mean(window)
# Assign the mean value to the corresponding pixel in the filtered image
filtered_image[y, x] = mean_value

return filtered_image

# Load the image in grayscale mode
image = cv2.imread('your_img.jpeg', cv2.IMREAD_GRAYSCALE)

# Define the kernel size for the mean filter
kernel_size = 3

# Apply the mean filter to the image
filtered_image = mean_filter(image, kernel_size)

# Display the original and filtered images
cv2.imshow('Original Image', image)
cv2.imshow('Mean Filtered Image', filtered_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.1.2 Code Explanation

  • The “mean_filter” function takes two arguments: “image” (input grayscale image) and “kernel_size” (size of square kernel for mean filtering).
  • It calculates the height and width of the input image and initializes an empty output image of the same size. Additionally, it pads the input image using “cv2.copyMakeBorder” to manage boundary pixels and prevent errors near image edges.
  • For each pixel in the original image, the function extracts the surrounding region through slicing based on “kernel_size.” Then, it computes the mean value of this region using “np.mean()”. The resulting mean value becomes the new pixel value in the output image.
  • The code segment loads the grayscale input image, ‘your_img.jpg,’ employing “cv2.imread()” with the “cv2.IMREAD_GRAYSCALE” flag. It defines the “kernel_size” (e.g., 5x5) and utilizes the “mean_filter()” function to acquire the filtered output image.
  • Execution of the code showcases two windows portraying the original and mean-filtered variations of the input image. Notably, the filtered image exhibits smoother attributes with diminished noise.

2.2 Gaussian Filter

Gaussian filtering is a critical tool in the field of image processing, especially for noise reduction. By applying a Gaussian kernel, the filter gives central pixels more weight than surrounding regions, effectively reducing noise while preserving image structure. The essential parameter σ controls the filter’s scope and subsequent smoothing. Gaussian filters are excellent at removing random, subtle image noise patterns, making them vital in many image processing applications.

Gaussian Filter applied to an image.

Among the many linear smoothing filters used for noise reduction, the Gaussian filter stands out as a crucial tool. It uses weights derived from the Gaussian distribution to effectively reduce noise in images. However, before using the Gaussian filter, it is important to preprocess the image and remove any outliers or spikes. While it is adept at handling random noise, the Gaussian filter has its limitations. It tends to blend noise into the result, causing indiscriminate smoothing along edges.

Square support Gaussian weights; σ=3, n=273

In summary, the Gaussian filter is a popular linear filter for reducing image noise in image processing. Its ability to assign accurate weights to pixels based on the Gaussian distribution enables it to reduce random, subtle noise patterns while preserving the underlying structure of the image. However, it is important to recognize its limitations and take preliminary steps when dealing with specific types of noise and preserving edges. When combined with other image filtering techniques, the Gaussian filter becomes a valuable tool, improving image quality and producing visually pleasing results.

2.2.1 Implementing the Gaussian Filter

import cv2
import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage import convolve

def gaussian_kernel(size, size_y=None):
size = int(size)
if not size_y:
size_y = size
else:
size_y = int(size_y)
x, y = np.mgrid[-size:size+1, -size_y:size_y+1]
g = np.exp(-(x**2/float(size) + y**2/float(size_y)))
return g / g.sum()

# Make the Gaussian kernel by calling the function
kernel_size = 7

gaussian_kernel_array = gaussian_kernel(kernel_size)

# Load a generic image in grayscale (replace 'lenna.jpeg' with the actual path)
image = cv2.imread('you_img.jpeg', cv2.IMREAD_GRAYSCALE)


# Apply Gaussian filter to the image
filtered_image = convolve(image, gaussian_kernel_array)

# Display the original and filtered images
cv2.imshow('Original Image', image)
cv2.imshow('Gaussian Filtered Image', filtered_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.2.2 Code Explanation

  • The “gaussian_kernel” function generates a 2D Gaussian kernel according to the provided size. The size parameter governs the kernel’s extent, influencing the degree of image smoothing during filtering.
  • Employing NumPy, the function constructs a meshgrid of x and y values and computes Gaussian values at each point. The kernel is normalized by dividing its values by the sum of all components, ensuring a cumulative weight of 1.
  • The “gaussian_kernel” function is invoked to produce a Gaussian kernel with a size of 5.
  • The code loads an image named ‘your_img.jpeg’ using “plt.imread().” It is important to substitute this filename with the actual image path.
  • An empty array named “filtered_image” is created to accommodate the filtered version of the image.
  • The code iterates through each color channel using a for loop (assuming RGB format). The “scipy.ndimage.convolve” function is employed to individually apply the convolution operation to each channel. This operation entails sliding the Gaussian kernel across the image, computing weighted pixel value sums in the pixel neighborhood, effectively implementing the Gaussian filter for image smoothing.
  • Following the filtration of all color channels, the “filtered_image” contains the outcome of applying the Gaussian filter to each channel of the original image.

2.3 Sobel Filter

The Sobel filter, introduced by Irwin Sobel and Gary M. Feldman in 1968, is a crucial tool in image processing and computer vision. Its primary purpose is to detect edges within images, playing a foundational role in various edge detection algorithms. By enhancing image edges, the Sobel filter significantly contributes to tasks such as object detection, image segmentation, and edge enhancement.

Sobel Filter apllied to an image.

At its core, the Sobel filter is ingeniously crafted as a compact, integer-valued filter that operates along both the horizontal and vertical directions of an image. This well-thought-out design choice underscores computational efficiency, rendering the Sobel filter an indispensable cornerstone of edge detection methodologies.

The essence of the Sobel operator lies in its ability to compute the gradient of the intensity function at each discrete point within the image. This process entails two separate convolutions: one with the horizontal kernel, often referred to as Gx, and the other with the vertical kernel, known as Gy.

The Horizontal Sobel Kernel (Gx) takes the form:

Conversely, the Vertical Sobel Kernel (Gy) is represented as:

These convolution kernels play a fundamental role in the image convolution process. As the kernels traverse the image pixel by pixel, they perform multiplication between the pixel values and corresponding kernel coefficients. The resulting products are then summed, yielding the filtered pixel value. The Horizontal Sobel Kernel excels at identifying vertical edges, whereas the Vertical Sobel Kernel adeptly highlights horizontal edges.

Upon completing the convolutions, the Sobel filter computes the gradient magnitude using the Pythagorean theorem:

This magnitude computation unveils insights into the rate of intensity variation and the presence of edges throughout the image. Moreover, the orientation of these edges is determined counterclockwise concerning the direction of maximum contrast, extending from black to white.

In summation, the Sobel filter assumes a foundational role in the landscape of image processing and computer vision. Through its compact design, strategic use of convolution kernels (Gx and Gy), and astute gradient calculation mechanisms, the Sobel filter emerges as a pivotal player in the realm of edge detection algorithms. By harnessing the power of the Sobel filter, practitioners can delve deeper into comprehending image structure and extracting invaluable insights from visual data.

2.3.1 Implementing the Sobel Filter

import cv2
import numpy as np

def sobel_filter(image):
sobel_x_kernel = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])

sobel_y_kernel = np.array([[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]])

# Apply convolution with Sobel kernels
sobel_x = cv2.filter2D(image, cv2.CV_64F, sobel_x_kernel)
sobel_y = cv2.filter2D(image, cv2.CV_64F, sobel_y_kernel)

# Calculate gradient magnitude
gradient_magnitude = np.sqrt(sobel_x**2 + sobel_y**2)

# Normalize the gradient magnitude to the range [0, 255]
normalized_gradient = cv2.normalize(gradient_magnitude, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)

return normalized_gradient

# Load the image in grayscale
image_path = 'input_image.jpg' # Change this to your image path
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

# Apply Sobel filter
output_edge_image = sobel_filter(image)

# Display the original and edge-detected images (optional)
cv2.imshow('Original Image', image)
cv2.imshow('Edge Detected Image (from scratch)', output_edge_image)
cv2.waitKey(0)
cv2.destroyAllWindows()2.3.2 Code Explanation

2.3.2 Code Explanation

  • Import necessary libraries: Import the required libraries, including cv2 for image processing and numpy for array operations.
  • Define the sobel_filter function: This function is defined to perform Sobel edge detection on the input image. It initializes the Sobel kernels for the x and y directions.
  • Apply convolution with Sobel kernels: The cv2.filter2D function is used to apply convolution with the Sobel kernels to the input image. This results in the gradient components along the x and y directions (i.e., sobel_x and sobel_y).
  • Calculate gradient magnitude: The gradient magnitude is calculated using the Euclidean formula from the gradient components.
  • Normalize the gradient magnitude: The gradient magnitude values are normalized to the range [0, 255] using cv2.normalize.
  • Load the input image: Load the input image (replace ‘input_image.jpg’ with your image path) using cv2.imread.
  • Apply Sobel filter: The sobel_filter function is called with the loaded image to obtain the edge-detected result.

3. Conclusion

In conclusion, this article provided an insightful introduction to fundamental linear image filtering techniques in the domain of image processing. The covered techniques included the Sobel filter, Gaussian filter, and mean filter. These techniques serve various purposes, from noise reduction and image smoothing to edge detection and enhancement. The article delved into the mechanisms behind each technique, highlighting their strengths, limitations, and applications.

The Sobel filter emerged as a critical tool for edge detection, efficiently highlighting image edges by convolving the image with horizontal and vertical kernels. The Gaussian filter, on the other hand, excelled in noise reduction through its weighted averaging approach based on the Gaussian distribution. The mean filter offered a simple yet effective solution for noise reduction by replacing each pixel with the average of its neighbors.

It’s important to note that while these linear filters offer valuable contributions to image processing, they might encounter challenges in scenarios involving non-linear noise patterns or intricate details. In the next part of the article, non-linear filters will be explored, offering solutions to address such challenges and further enhancing image processing capabilities. Non-linear filters can handle more complex noise patterns and are crucial for maintaining finer details in images. Stay tuned for the upcoming article where these non-linear techniques will be unveiled and discussed in detail.

References

[1] https://homepages.inf.ed.ac.uk/rbf/HIPR2/mean.htm

[2] https://docs.opencv.org/3.3.1/d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1

[3] https://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm

[4] https://reference.wolfram.com/language/ref/GaussianFilter.html#:~:text=Background%20%26%20Context-,GaussianFilter%20is%20a%20filter%20commonly%20used%20in%20image%20processing%20for,matrix%20as%20its%20underlying%20kernel.

[5] https://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm

[6] https://www.researchgate.net/publication/239398674_An_Isotropic_3x3_Image_Gradient_Operator

--

--

Henrique Vedoveli

Maters Student in Computer Science and Machine Learning Engineer🦜