1. AIR UNIVERSITY
Department of Electrical and Computer Engineering
Digital Image Processing Lab
Lab #7: Image Processing Techniques for Visual Enhancement
Student Name: Umar Mustafa
Roll No: 200365
Instructor: Engr. M. Farooq Khan
Lab Tasks
Apply different trasnformations.
Subplot with and without transformation.
1)Translation Type:(Geometric Transformation)
2)Scale (Type:Geometric Transformation)
3)Histogram Equalization (Type: Gray-Level Transformation)
4)Sharpening (Type: Filtering Operation)
5)Erosion (Type: Morphological Transformation)
6)Dilation (Type: Morphological Transformation)
7)Fast Fourier Transform (FFT) (Type: Fourier Transformation)
Conclusion
Transformations include operations that modify the spatial characteristics of an image, such as its size, position, orientation, and pixel values.
Common transformations include translation, scaling, rotation, shearing, and flipping, which alter the geometric properties of an image.
Other transformations, such as histogram equalization and sharpening, focus on enhancing image quality, improving contrast, and emphasizing important features.
Image transformations often involve applying specific algorithms or mathematical operations to achieve the desired effect.
Understanding the purpose and parameters of each transformation is essential to choose the appropriate technique for a specific task or application.
By applying transformations effectively, image processing techniques can be used for tasks like image restoration, feature extraction, object recognition, and more, leading to improved
visual quality and better analysis of images.
In [3]: import cv2
import numpy as np
import matplotlib.pyplot as plt
# Load the image
image = cv2.imread('F:/imagelab/droplets.jpg')
# Define the translation matrix
tx = 50 # translation in the x-axis
ty = 30 # translation in the y-axis
# We define the translation amounts tx and ty to specify how much we want to shift the image in the x-axis and y-axis
# Adjust these values according to your requirements.
translation_matrix = np.float32([[1, 0, tx], [0, 1, ty]])
# We create a 2x3 translation matrix using np.float32().
# Apply the translation transformation
translated_image = cv2.warpAffine(image, translation_matrix, (image.shape[1], image.shape[0]))
# We apply the translation transformation to the image using cv2.warpAffine().It takes the input image, translation matrix,
# and the desired output image size (image.shape[1], image.shape[0]) as parameters.The result is stored in the translated_image
# variable.
# Display the original and filtered images
plt.subplot(221)
plt.imshow(image)
plt.title('Original')
plt.subplot(222)
plt.imshow(translated_image)
plt.title('Translated Image')
plt.show()
In [4]: # Define the scaling factors
scale_x = 1.5 # scaling factor for the x-axis
scale_y = 1.5 # scaling factor for the y-axis
# We define the scaling factors scale_x and scale_y to specify how much we want to scale the image in the x-axis and y-axis,
# respectively. Adjust these values according to your requirements. A value greater than 1 enlarges the image, while a value
# less than 1 shrinks the image.
# Determine the new dimensions
new_width = int(image.shape[1] * scale_x)
new_height = int(image.shape[0] * scale_y)
new_dimensions = (new_width, new_height)
# The new width is obtained by multiplying the original width (image.shape[1]) with the scaling factor scale_x, and the new
# height is obtained by multiplying the original height (image.shape[0]) with the scaling factor scale_y. We convert the
# dimensions to integers using int() and store them in the new_width and new_height variables. The new dimensions are then
# stored as a tuple in the new_dimensions variable.
# Apply the scaling transformation
scaled_image = cv2.resize(image, new_dimensions)
# We apply the scaling transformation to the image using cv2.resize(). It takes the input image and the new dimensions as
# parameters. The function resizes the image to the specified dimensions and stores the result in the scaled_image variable.
# Display the original and scaled images
plt.subplot(221)
plt.imshow(image)
plt.title('Original')
plt.subplot(222)
plt.imshow(scaled_image)
plt.title('Scaled Image')
plt.show()
In [13]: # Convert the image to grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply histogram equalization
equalized_image = cv2.equalizeHist(gray_image)
# We apply histogram equalization to the grayscale image using the cv2.equalizeHist() function. The function takes the grayscale
# image as input and performs histogram equalization on it. The result is stored in the equalized_image variable.
# Display the original and scaled images
plt.subplot(221)
plt.imshow(gray_image)
plt.title('Original')
plt.subplot(222)
plt.imshow(equalized_image)
plt.title('Equalized_image')
plt.show()
In [16]: # Create the sharpening kernel
# We create a sharpening kernel using np.array(). The kernel is a 3x3 matrix that defines the sharpening filter.
kernel = np.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
# This kernel enhances edges and details by emphasizing high-frequency components and reducing the contribution of the
# surrounding pixels.
# Apply the sharpening transformation
sharpened_image = cv2.filter2D(image, -1, kernel)
# We apply the sharpening transformation to the image using cv2.filter2D(). It takes the input image, the desired depth of the
# destination image (-1 indicates the same depth as the input image), and the sharpening kernel as parameters. The function
# convolves the image with the kernel, accentuating edges and details, and stores the result in the sharpened_image variable.
# Display the original and sharpened images
plt.subplot(221)
plt.imshow(image)
plt.title('Original')
plt.subplot(222)
plt.imshow(sharpened_image)
plt.title('Sharpened Image')
plt.show()
In [17]: # Create a structuring element for erosion
kernel = np.ones((5, 5), np.uint8)
# We create a structuring element for erosion using np.ones(). The structuring element is a 5x5 matrix with all elements set to
# 1. This matrix defines the neighborhood around each pixel that is considered during the erosion operation. Adjust the size of
# the structuring element according to the desired effect.
# Apply erosion
eroded_image = cv2.erode(image, kernel, iterations=1)
# We apply the erosion operation to the image using cv2.erode(). It takes the input image, the structuring element (kernel), and
# the number of iterations as parameters. In this example, we perform erosion once (iterations=1). The function erodes the
# boundaries of the foreground objects, resulting in the reduction of object sizes.
# Display the original and eroded images
plt.subplot(221)
plt.imshow(image)
plt.title('Original')
plt.subplot(222)
plt.imshow(eroded_image)
plt.title('Eroded Image')
plt.show()
In [19]: # Create a structuring element for dilation
kernel = np.ones((5, 5), np.uint8)
# We create a structuring element for dilation using np.ones(). The structuring element is a 5x5 matrix with all elements set to
# 1. This matrix defines the neighborhood around each pixel that is considered during the dilation operation. Adjust the size of
# the structuring element according to the desired effect.
# Apply dilation
dilated_image = cv2.dilate(image, kernel, iterations=1)
# We apply the dilation operation to the image using cv2.dilate(). It takes the input image, the structuring element (kernel),
# and the number of iterations as parameters. In this example, we perform dilation once (iterations=1).The function expands
# the boundaries of the foreground objects, resulting in the enlargement of object sizes and the filling of holes or gaps.
# Display the original and dilated images
plt.subplot(221)
plt.imshow(image)
plt.title('Original')
plt.subplot(222)
plt.imshow(dilated_image)
plt.title('Dilated Image')
plt.show()
In [23]: # Perform FFT
fft_image = np.fft.fft2(image)
# We perform the Fast Fourier Transform (FFT) on the image using np.fft.fft2(). This function computes the 2-dimensional FFT of
# the input image, returning a complex-valued array. The result is stored in the fft_image variable.
# Shift the zero-frequency component to the center
shifted_fft_image = np.fft.fftshift(fft_image)
# We shift the zero-frequency component (DC component) of the FFT result to the center of the spectrum using np.fft.fftshift().
# This rearrangement is necessary to visualize the spectrum properly.
# Compute the magnitude spectrum
magnitude_spectrum = np.abs(shifted_fft_image)
magnitude_spectrum = np.log1p(magnitude_spectrum)
# Applied np.log1p() instead of np.log() to compute the logarithm with added 1.This helps avoid undefined values for zero inputs
# and handles the warning properly.
magnitude_spectrum = (magnitude_spectrum - np.min(magnitude_spectrum)) / np.ptp(magnitude_spectrum)
# Normalized the magnitude_spectrum array using (magnitude_spectrum - np.min(magnitude_spectrum)) / np.ptp(magnitude_spectrum)
# to scale the values to the range [0, 1].
# Display the original image and its magnitude spectrum
plt.subplot(121)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.xticks([]), plt.yticks([]) # plt.xticks([]) and plt.yticks([]) remove the tick labels
plt.subplot(122)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum')
plt.xticks([]), plt.yticks([]) # plt.xticks([]) and plt.yticks([]) remove the tick labels,
plt.show()