NAME : KARTHIKEYAN RAVICHANDRAN
PSID : 2260006
EDS 6397 - DIGITAL IMAGE PROCESSING
LAB -2 IMAGE ENHANCEMENT – SPATIAL DOMAIN
TASK 1 - IMAGE THRESHOLDING
In [25]: #importing the necessary libraries
import cv2
import matplotlib.pyplot as plt
import numpy as np
Loading the grayscale image
In [26]: img_gray = cv2.imread("DIP_output_2.png", cv2.IMREAD_GRAYSCALE)
# Checking if the image was loaded successfully
if img_gray is None:
print("Error: Unable to load image.")
else:
# Displaying the grayscale image
plt.imshow(img_gray, cmap='gray')
plt.axis('off') # Turn off axis
plt.show()
In [138… cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_2.png",img_gray)
True
Out[138]:
Applying Binary Thresholding to the above image with a threshold value of 127
In [27]: ret,binary_threshold = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
#we are using the threshold function of opencv
#ret - return value of the function holding the threshold value (optional parameter)
#binary_threshold - return value which holds the output thresholded image
# 1st parameter holds the input grayscale image
# 2nd and 3rd parameter holds the threshold and the maximum pixel intensity value where pixels with intensity values greater than this threshold will be set to the maximum value (255 in this case), and pixels with intensity values
#4 th parameter - type of threshold
In [28]: #Displaying the output thresholded image
plt.imshow(binary_threshold,cmap="gray")
<matplotlib.image.AxesImage at 0x1daf2effee0>
Out[28]:
In [78]: cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_1_Thresh_Bin.png",binary_threshold)
True
Out[78]:
Applying binary inverse thresholding on the image with a threshold value of 127
In [29]: ret, binary_inverse_threshold = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
#we are using the threshold function of opencv
#ret - return value of the function holding the threshold value (optional parameter)
#binary_inverse_threshold - return value which holds the output thresholded image
# 1st parameter holds the input grayscale image
# 2nd and 3rd parameter holds the threshold and the maximum pixel intensity value where pixels with intensity values greater than this threshold will be set to the 0, and pixels with intensity values less than or equal to this thr
#4 th parameter - type of threshold
In [30]: #Displaying the output image
plt.imshow(binary_inverse_threshold,cmap="gray")
<matplotlib.image.AxesImage at 0x1daf2efcd30>
Out[30]:
In [79]: cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_2_Inv_Thresh_Bin.png",binary_inverse_threshold)
True
Out[79]:
INFERENCE:
In binary thresholding, pixel values above the threshold become white (255), and pixel values below the threshold become black (0).
In binary inverse thresholding, pixel values above the threshold become black (0), and pixel values below the threshold become white (255).
In summary, both methods are useful for segmenting objects from the background, but the choice between binary thresholding and binary inverse thresholding depends on the characteristics of the image and the specific task at hand.
Validation to check if the image is Binary
In [31]: #Check data type
if binary_threshold.dtype == 'uint8':
print("The image is likely in binary format.")
else:
print("The image is not in binary format.")
The image is likely in binary format.
TASK 2 - BIT PLANE SLICING
Loading the grayscale image from LAB 1 and convert it into its binary representation.</h3
In [34]: img_gray = cv2.imread("DIP_output_2.png", cv2.IMREAD_GRAYSCALE)
In [36]: #using binary threshold process to convert it into a binary image
ret,binary_rep = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
Implemention of bit-plane slicing to extract specific bit-planes
In [39]: # Function to extract a specific bit plane
def extract_bit_plane(image, bit):
return (image >> bit) & 1
# Visualize each bit plane separately
for i in range(8): # Assuming 8-bit grayscale image
bit_plane = extract_bit_plane(img_gray, i)
plt.subplot(3, 3, i+1)
plt.imshow(bit_plane, cmap='gray')
plt.title(f'Bit-Plane {i}')
plt.axis('off')
plt.show()
INFERENCE:
We can observe that from MSB-->LSB, the image quality is deteriorating.
Hence for the compression task, I am considering the top most 3 bits.
In [125… # Combining 3 planes of choice
compressed_image = (extract_bit_plane(img_gray, 5)) | (extract_bit_plane(img_gray, 6) << 1) | (extract_bit_plane(img_gray, 7)<<2)
# Display the compressed image
plt.imshow(compressed_image, cmap='gray')
plt.title('Compressed Image (3-bit)')
plt.axis('off')
plt.show()
In [127… result = cv2.normalize(compressed_image, dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
In [129… cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_3_Compressed_img.png",result)
True
Out[129]:
INFERENCE:
We can observe that we are able to almost get the most details from the original 8 bit image while compressing the image to 3 bit when we are considering the top 3 MSB bits.
Still we don't get a few depths which signifies that even the LSB play a role in image representation.
Yet, when we consider the storage which is effective as we consider only 3 planes and also in real time application, data transfer will also be faster. Hence this compression is beneficial.
Alternative approach to extract each bit plane
In [74]: # Get the number of rows and columns in the image
rows, cols = img_gray.shape
# Extract MSB (Most Significant Bit)
msb = img_gray & 0x80 # Mask with 10000000
msb_2=img_gray & 0x40 #Mask with 01000000
# Extract LSB (Least Significant Bit)
lsb = img_gray & 0x01 # Mask with 00000001
# Display MSB and LSB
plt.figure(figsize=(10, 5))
plt.subplot(1, 3, 1)
plt.imshow(msb, cmap='gray')
plt.title('MSB (Bit 7)')
plt.axis('off') # Turn off axis labels
plt.subplot(1, 3, 2)
plt.imshow(msb_2, cmap='gray')
plt.title('MSB (Bit 6)')
plt.axis('off') # Turn off axis labels
plt.subplot(1, 3, 3)
plt.imshow(lsb, cmap='gray')
plt.title('LSB (Bit 0)')
plt.axis('off') # Turn off axis labels
plt.show()
TASK 3 - SMOOTHING WITH LOW-PASS FILTER
In [81]: # Load the color image
color_image = cv2.imread('DIP_output_1.png')
# Apply average filter with different kernel sizes
filter_sizes = [3, 5, 7,17]
smoothened_images = []
for size in filter_sizes:
# Apply average filter
kernel = np.ones((size, size), np.float32) / (size * size)
smoothened_image = cv2.filter2D(color_image, -1, kernel)
smoothened_images.append(smoothened_image)
# Display original and smoothed images
plt.figure(figsize=(15, 5))
plt.subplot(1, len(filter_sizes) + 1, 1)
plt.imshow(cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
for i, size in enumerate(filter_sizes):
plt.subplot(1, len(filter_sizes) + 1, i + 2)
plt.imshow(cv2.cvtColor(smoothened_images[i], cv2.COLOR_BGR2RGB))
plt.title(f'Smoothened Image (n={size})')
plt.show()
In [98]: cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_1.png", color_image)
True
Out[98]:
In [102… cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_4_smoothed_image_3.png", smoothened_images[0])
cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_4_smoothed_image_5.png", smoothened_images[1])
cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_4_smoothed_image_7.png", smoothened_images[2])
True
Out[102]:
INFERENCE:
We can observe that as the filter size increases, we are getting a more smoothened image representing reduction in noise.
But as we increase the filter images, the high frequency components like edges are also blurred, so the quality of the image decreases.( I have added a filter size=17 to demonstrate the increase in blur and to differentiate from all other smoothened images.
TASK 4 - SMOOTHING WITH MEDIAN FILTER
Loading the Noisy image
In [11]: a=cv2.imread("mandril_spnoise_0.2.jpg",cv2.IMREAD_COLOR)
In [46]: #displaying the image
plt.imshow(a)
<matplotlib.image.AxesImage at 0x1daf1c9c820>
Out[46]:
Implementation of a median filter to remove the noise while preserving edges and details.
In [68]: median = cv2.medianBlur(a,9)
plt.imshow(median)
<matplotlib.image.AxesImage at 0x1daf25801c0>
Out[68]:
INFERENCE:
The kernel size needs to be an odd number. I have taken kernel value as 9 here.
Since the median filter works by taking the median value from a neighborhood of pixels, and using an odd-sized kernel ensures that there is a central pixel for which the median is calculated.
IMPLEMENTATION OF MEDIAN FILTER WITH DIFFERENT KERNEL SIZES
In [111… # Define kernel sizes
kernel_sizes = [3, 5, 7]
# Create subplots for each denoised image
fig, axs = plt.subplots(1, len(kernel_sizes), figsize=(15, 5))
denoised_images=[]
# Applying median filter with different kernel sizes
for i, kernel_size in enumerate(kernel_sizes):
denoised_image = cv2.medianBlur(a, kernel_size)
denoised_images.append(denoised_image)
# Displaying the denoised image
axs[i].imshow(denoised_image)
axs[i].set_title(f'Kernel Size - {kernel_size}')
axs[i].axis('off')
# Show the plot
plt.show()
In [134… result1 = cv2.normalize(denoised_images[0], dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_5_median_3.png",result1)
result2 = cv2.normalize(denoised_images[1], dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_5_median_5.png",result2)
result3 = cv2.normalize(denoised_images[2], dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
cv2.imwrite(r"C:\Users\karth\OneDrive\Documents\GitHub\lab-assignment-2-Karthiknmsd37\output_images\DIP_output_5_median_7.png",result3)
True
Out[134]:
INFERENCE
We can observe that as we increase the kernel size, the salt and pepper noise reduces.
But the image gets more blur resulting in the loss of sharpness and minute details.
Hence we need to find an optimized value which balances by providing the details as well as reducing noise.
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]: