|
| 1 | +# Input RGB image and implementing simple filtering |
| 2 | + |
| 3 | +# Importing needed libraries |
| 4 | +import numpy as np |
| 5 | +from PIL import Image |
| 6 | +import matplotlib.pyplot as plt |
| 7 | + |
| 8 | +# Creating an array from image data |
| 9 | +input_image = Image.open("images/eagle.jpeg") |
| 10 | +image_np = np.array(input_image) |
| 11 | + |
| 12 | +# Checking the type of the array |
| 13 | +print(type(image_np)) # <class 'numpy.ndarray'> |
| 14 | +# Checking the shape of the array |
| 15 | +print(image_np.shape) # (270, 480, 3) |
| 16 | + |
| 17 | +# Showing image with every channel separately |
| 18 | +channel_0 = image_np[:, :, 0] |
| 19 | +channel_1 = image_np[:, :, 1] |
| 20 | +channel_2 = image_np[:, :, 2] |
| 21 | + |
| 22 | +# Checking if all channels are different |
| 23 | +print(np.array_equal(channel_0, channel_1)) # False |
| 24 | +print(np.array_equal(channel_1, channel_2)) # False |
| 25 | + |
| 26 | +# Creating a figure with subplots |
| 27 | +f, ax = plt.subplots(nrows=2, ncols=2) |
| 28 | +# ax is (2, 2) np array and to make it easier to read we use 'flatten' function |
| 29 | +# Or we can call each time ax[0, 0] |
| 30 | +ax0, ax1, ax2, ax3 = ax.flatten() |
| 31 | + |
| 32 | +# Adjusting first subplot |
| 33 | +ax0.imshow(channel_0, cmap=plt.get_cmap('Reds')) |
| 34 | +ax0.set_xlabel('') |
| 35 | +ax0.set_ylabel('') |
| 36 | +ax0.set_title('First channel') |
| 37 | + |
| 38 | +# Adjusting second subplot |
| 39 | +ax1.imshow(channel_1, cmap=plt.get_cmap('Greens')) |
| 40 | +ax1.set_xlabel('') |
| 41 | +ax1.set_ylabel('') |
| 42 | +ax1.set_title('Second channel') |
| 43 | + |
| 44 | +# Adjusting third subplot |
| 45 | +ax2.imshow(channel_2, cmap=plt.get_cmap('Blues')) |
| 46 | +ax2.set_xlabel('') |
| 47 | +ax2.set_ylabel('') |
| 48 | +ax2.set_title('Third channel') |
| 49 | + |
| 50 | +# Adjusting fourth subplot |
| 51 | +ax3.imshow(image_np) |
| 52 | +ax3.set_xlabel('') |
| 53 | +ax3.set_ylabel('') |
| 54 | +ax3.set_title('Original image') |
| 55 | + |
| 56 | +# Function to make distance between figures |
| 57 | +plt.tight_layout() |
| 58 | +# Giving the name to the window with figure |
| 59 | +f.canvas.set_window_title('GreyScaled image with three identical channels') |
| 60 | +# Showing the plots |
| 61 | +plt.show() |
| 62 | + |
| 63 | +# Preparing image for Edge detection |
| 64 | +# Converting RGB image into GrayScale image |
| 65 | +# Using formula: |
| 66 | +# Y' = 0.299 R + 0.587 G + 0.114 B |
| 67 | +image_GrayScale = image_np[:, :, 0] * 0.299 + image_np[:, :, 1] * 0.587 + image_np[:, :, 2] * 0.114 |
| 68 | +# Checking the type of the array |
| 69 | +print(type(image_GrayScale)) # <class 'numpy.ndarray'> |
| 70 | +# Checking the shape of the array |
| 71 | +print(image_GrayScale.shape) # (270, 480) |
| 72 | +# Giving the name to the window with figure |
| 73 | +plt.figure('GrayScale image from RGB') |
| 74 | +# Showing the image by using obtained array |
| 75 | +plt.imshow(image_GrayScale, cmap=plt.get_cmap('gray')) |
| 76 | +plt.show() |
| 77 | + |
| 78 | +# Applying to the GrayScale image Pad frame with zero values |
| 79 | +# Using NumPy method 'pad' |
| 80 | +GrayScale_image_with_pad = np.pad(image_GrayScale, (1, 1), mode='constant', constant_values=0) |
| 81 | +# Checking the shape |
| 82 | +print(GrayScale_image_with_pad.shape) # (272, 482) |
| 83 | + |
| 84 | +# Preparing image for convolution |
| 85 | +# In order to get filtered image (convolved input image) in the same size, it is needed to set Hyperparameters |
| 86 | +# Filter (kernel) size, K_size = 3 |
| 87 | +# Step for sliding (stride), Step = 1 |
| 88 | +# Processing edges (zero valued frame around image), Pad = 1 |
| 89 | +# Consequently, output image size is (width and height are the same): |
| 90 | +# Width_Out = (Width_In - K_size + 2*Pad)/Step + 1 |
| 91 | +# Imagine, that input image is 5x5 spatial size (width and height), then output image: |
| 92 | +# Width_Out = (5 - 3 + 2*1)/1 + 1 = 5, and this is equal to input image |
| 93 | + |
| 94 | +# Preparing zero valued output arrays for filtered images (convolved images) |
| 95 | +# The shape is the same with input image according to the chosen Hyperparameters |
| 96 | +# For three filters for Edge detection and implementing it only for one GrayScale channel |
| 97 | +output_image_1 = np.zeros(image_GrayScale.shape) |
| 98 | +output_image_2 = np.zeros(image_GrayScale.shape) |
| 99 | +output_image_3 = np.zeros(image_GrayScale.shape) |
| 100 | + |
| 101 | +# Declaring standard filters (kernel) with size 3x3 for edge detection |
| 102 | +filter_1 = np.array([[1, 0, -1], [0, 0, 0], [-1, 0, 1]]) |
| 103 | +filter_2 = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]]) |
| 104 | +filter_3 = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) |
| 105 | +# Checking the shape |
| 106 | +print(filter_1.shape, filter_2.shape, filter_3.shape) |
| 107 | +# ((3, 3) (3, 3) (3, 3) |
| 108 | + |
| 109 | + |
| 110 | +# In order to prevent appearing values that are less than -1 |
| 111 | +# Following function is declared |
| 112 | +def relu(array): |
| 113 | + # Preparing array for output result |
| 114 | + r = np.zeros_like(array) |
| 115 | + # Using 'np.where' setting condition that every element in 'array' has to be more than appropriate element in 'r' |
| 116 | + result = np.where(array > r, array, r) |
| 117 | + # Returning resulted array |
| 118 | + return result |
| 119 | + |
| 120 | + |
| 121 | +# In order to prevent appearing values that are more than 255 |
| 122 | +# The following function is declared |
| 123 | +def image_pixels(array): |
| 124 | + # Preparing array for output result |
| 125 | + # Creating an empty array |
| 126 | + r = np.empty(array.shape) |
| 127 | + # Filling array with 255 value for all elements |
| 128 | + r.fill(255) |
| 129 | + # Using 'np.where' setting condition that every element in 'array' has to be less than appropriate element in 'r' |
| 130 | + result = np.where(array < r, array, r) |
| 131 | + # Returning resulted array |
| 132 | + return result |
| 133 | + |
| 134 | + |
| 135 | +# Implementing convolution operation for Edge detection for GrayScale image |
| 136 | +# Going through all input image with pad frame |
| 137 | +for i in range(GrayScale_image_with_pad.shape[0] - 2): |
| 138 | + for j in range(GrayScale_image_with_pad.shape[1] - 2): |
| 139 | + # Extracting 3x3 patch (the same size with filter) from input image with pad frame |
| 140 | + patch_from_input_image = GrayScale_image_with_pad[i:i+3, j:j+3] |
| 141 | + # Applying elementwise multiplication and summation - this is convolution operation |
| 142 | + # With filter_1 |
| 143 | + output_image_1[i, j] = np.sum(patch_from_input_image * filter_1) |
| 144 | + # With filter_2 |
| 145 | + output_image_2[i, j] = np.sum(patch_from_input_image * filter_2) |
| 146 | + # With filter_3 |
| 147 | + output_image_3[i, j] = np.sum(patch_from_input_image * filter_3) |
| 148 | + |
| 149 | +# Applying 'relu' and 'image_pixels' function to get rid of negative values and that ones that more than 255 |
| 150 | +output_image_1 = image_pixels(relu(output_image_1)) |
| 151 | +output_image_2 = image_pixels(relu(output_image_2)) |
| 152 | +output_image_3 = image_pixels(relu(output_image_3)) |
| 153 | + |
| 154 | +# Showing results on the appropriate figures |
| 155 | +figure_1, ax = plt.subplots(nrows=3, ncols=1) |
| 156 | + |
| 157 | +# Adjusting first subplot |
| 158 | +ax[0].imshow(output_image_1, cmap=plt.get_cmap('gray')) |
| 159 | +ax[0].set_xlabel('') |
| 160 | +ax[0].set_ylabel('') |
| 161 | +ax[0].set_title('Edge #1') |
| 162 | + |
| 163 | +# Adjusting second subplot |
| 164 | +ax[1].imshow(output_image_2, cmap=plt.get_cmap('gray')) |
| 165 | +ax[1].set_xlabel('') |
| 166 | +ax[1].set_ylabel('') |
| 167 | +ax[1].set_title('Edge #2') |
| 168 | + |
| 169 | +# Adjusting third subplot |
| 170 | +ax[2].imshow(output_image_3, cmap=plt.get_cmap('gray')) |
| 171 | +ax[2].set_xlabel('') |
| 172 | +ax[2].set_ylabel('') |
| 173 | +ax[2].set_title('Edge #3') |
| 174 | + |
| 175 | +# Function to make distance between figures |
| 176 | +plt.tight_layout() |
| 177 | +# Giving the name to the window with figure |
| 178 | +figure_1.canvas.set_window_title('Convolution with filters (simple filtering)') |
| 179 | +# Showing the plots |
| 180 | +plt.show() |
0 commit comments