@@ -38,11 +38,190 @@ Experimental results (figures and tables on this page):
3838### <a name =" Examples of Simple Filtering " >Examples of Simple Filtering</a >
3939
4040``` py
41+ # Input RGB image and implementing simple filtering
42+
43+ # Importing needed libraries
4144import numpy as np
45+ from PIL import Image
46+ import matplotlib.pyplot as plt
47+
48+ # Creating an array from image data
49+ input_image = Image.open(" images/eagle.jpeg" )
50+ image_np = np.array(input_image)
51+
52+ # Checking the type of the array
53+ print (type (image_np)) # <class 'numpy.ndarray'>
54+ # Checking the shape of the array
55+ print (image_np.shape) # (270, 480, 3)
56+
57+ # Showing image with every channel separately
58+ channel_0 = image_np[:, :, 0 ]
59+ channel_1 = image_np[:, :, 1 ]
60+ channel_2 = image_np[:, :, 2 ]
61+
62+ # Checking if all channels are different
63+ print (np.array_equal(channel_0, channel_1)) # False
64+ print (np.array_equal(channel_1, channel_2)) # False
65+
66+ # Creating a figure with subplots
67+ f, ax = plt.subplots(nrows = 2 , ncols = 2 )
68+ # ax is (2, 2) np array and to make it easier to read we use 'flatten' function
69+ # Or we can call each time ax[0, 0]
70+ ax0, ax1, ax2, ax3 = ax.flatten()
71+
72+ # Adjusting first subplot
73+ ax0.imshow(channel_0, cmap = plt.get_cmap(' Reds' ))
74+ ax0.set_xlabel(' ' )
75+ ax0.set_ylabel(' ' )
76+ ax0.set_title(' First channel' )
77+
78+ # Adjusting second subplot
79+ ax1.imshow(channel_1, cmap = plt.get_cmap(' Greens' ))
80+ ax1.set_xlabel(' ' )
81+ ax1.set_ylabel(' ' )
82+ ax1.set_title(' Second channel' )
83+
84+ # Adjusting third subplot
85+ ax2.imshow(channel_2, cmap = plt.get_cmap(' Blues' ))
86+ ax2.set_xlabel(' ' )
87+ ax2.set_ylabel(' ' )
88+ ax2.set_title(' Third channel' )
89+
90+ # Adjusting fourth subplot
91+ ax3.imshow(image_np)
92+ ax3.set_xlabel(' ' )
93+ ax3.set_ylabel(' ' )
94+ ax3.set_title(' Original image' )
95+
96+ # Function to make distance between figures
97+ plt.tight_layout()
98+ # Giving the name to the window with figure
99+ f.canvas.set_window_title(' GreyScaled image with three identical channels' )
100+ # Showing the plots
101+ plt.show()
102+
103+ # Preparing image for Edge detection
104+ # Converting RGB image into GrayScale image
105+ # Using formula:
106+ # Y' = 0.299 R + 0.587 G + 0.114 B
107+ image_GrayScale = image_np[:, :, 0 ] * 0.299 + image_np[:, :, 1 ] * 0.587 + image_np[:, :, 2 ] * 0.114
108+ # Checking the type of the array
109+ print (type (image_GrayScale)) # <class 'numpy.ndarray'>
110+ # Checking the shape of the array
111+ print (image_GrayScale.shape) # (270, 480)
112+ # Giving the name to the window with figure
113+ plt.figure(' GrayScale image from RGB' )
114+ # Showing the image by using obtained array
115+ plt.imshow(image_GrayScale, cmap = plt.get_cmap(' gray' ))
116+ plt.show()
117+
118+ # Applying to the GrayScale image Pad frame with zero values
119+ # Using NumPy method 'pad'
120+ GrayScale_image_with_pad = np.pad(image_GrayScale, (1 , 1 ), mode = ' constant' , constant_values = 0 )
121+ # Checking the shape
122+ print (GrayScale_image_with_pad.shape) # (272, 482)
123+
124+ # Preparing image for convolution
125+ # In order to get filtered image (convolved input image) in the same size, it is needed to set Hyperparameters
126+ # Filter (kernel) size, K_size = 3
127+ # Step for sliding (stride), Step = 1
128+ # Processing edges (zero valued frame around image), Pad = 1
129+ # Consequently, output image size is (width and height are the same):
130+ # Width_Out = (Width_In - K_size + 2*Pad)/Step + 1
131+ # Imagine, that input image is 5x5 spatial size (width and height), then output image:
132+ # Width_Out = (5 - 3 + 2*1)/1 + 1 = 5, and this is equal to input image
133+
134+ # Preparing zero valued output arrays for filtered images (convolved images)
135+ # The shape is the same with input image according to the chosen Hyperparameters
136+ # For three filters for Edge detection and implementing it only for one GrayScale channel
137+ output_image_1 = np.zeros(image_GrayScale.shape)
138+ output_image_2 = np.zeros(image_GrayScale.shape)
139+ output_image_3 = np.zeros(image_GrayScale.shape)
140+
141+ # Declaring standard filters (kernel) with size 3x3 for edge detection
142+ filter_1 = np.array([[1 , 0 , - 1 ], [0 , 0 , 0 ], [- 1 , 0 , 1 ]])
143+ filter_2 = np.array([[0 , 1 , 0 ], [1 , - 4 , 1 ], [0 , 1 , 0 ]])
144+ filter_3 = np.array([[- 1 , - 1 , - 1 ], [- 1 , 8 , - 1 ], [- 1 , - 1 , - 1 ]])
145+ # Checking the shape
146+ print (filter_1.shape, filter_2.shape, filter_3.shape)
147+ # ((3, 3) (3, 3) (3, 3)
148+
149+
150+ # In order to prevent appearing values that are less than -1
151+ # Following function is declared
152+ def relu (array ):
153+ # Preparing array for output result
154+ r = np.zeros_like(array)
155+ # Using 'np.where' setting condition that every element in 'array' has to be more than appropriate element in 'r'
156+ result = np.where(array > r, array, r)
157+ # Returning resulted array
158+ return result
159+
160+
161+ # In order to prevent appearing values that are more than 255
162+ # The following function is declared
163+ def image_pixels (array ):
164+ # Preparing array for output result
165+ # Creating an empty array
166+ r = np.empty(array.shape)
167+ # Filling array with 255 value for all elements
168+ r.fill(255 )
169+ # Using 'np.where' setting condition that every element in 'array' has to be less than appropriate element in 'r'
170+ result = np.where(array < r, array, r)
171+ # Returning resulted array
172+ return result
173+
174+
175+ # Implementing convolution operation for Edge detection for GrayScale image
176+ # Going through all input image with pad frame
177+ for i in range (GrayScale_image_with_pad.shape[0 ] - 2 ):
178+ for j in range (GrayScale_image_with_pad.shape[1 ] - 2 ):
179+ # Extracting 3x3 patch (the same size with filter) from input image with pad frame
180+ patch_from_input_image = GrayScale_image_with_pad[i:i+ 3 , j:j+ 3 ]
181+ # Applying elementwise multiplication and summation - this is convolution operation
182+ # With filter_1
183+ output_image_1[i, j] = np.sum(patch_from_input_image * filter_1)
184+ # With filter_2
185+ output_image_2[i, j] = np.sum(patch_from_input_image * filter_2)
186+ # With filter_3
187+ output_image_3[i, j] = np.sum(patch_from_input_image * filter_3)
188+
189+ # Applying 'relu' and 'image_pixels' function to get rid of negative values and that ones that more than 255
190+ output_image_1 = image_pixels(relu(output_image_1))
191+ output_image_2 = image_pixels(relu(output_image_2))
192+ output_image_3 = image_pixels(relu(output_image_3))
193+
194+ # Showing results on the appropriate figures
195+ figure_1, ax = plt.subplots(nrows = 3 , ncols = 1 )
196+
197+ # Adjusting first subplot
198+ ax[0 ].imshow(output_image_1, cmap = plt.get_cmap(' gray' ))
199+ ax[0 ].set_xlabel(' ' )
200+ ax[0 ].set_ylabel(' ' )
201+ ax[0 ].set_title(' Edge #1' )
202+
203+ # Adjusting second subplot
204+ ax[1 ].imshow(output_image_2, cmap = plt.get_cmap(' gray' ))
205+ ax[1 ].set_xlabel(' ' )
206+ ax[1 ].set_ylabel(' ' )
207+ ax[1 ].set_title(' Edge #2' )
208+
209+ # Adjusting third subplot
210+ ax[2 ].imshow(output_image_3, cmap = plt.get_cmap(' gray' ))
211+ ax[2 ].set_xlabel(' ' )
212+ ax[2 ].set_ylabel(' ' )
213+ ax[2 ].set_title(' Edge #3' )
214+
215+ # Function to make distance between figures
216+ plt.tight_layout()
217+ # Giving the name to the window with figure
218+ figure_1.canvas.set_window_title(' Convolution with filters (simple filtering)' )
219+ # Showing the plots
220+ plt.show()
42221
43222```
44223
45- ![ Four_Filters ] ( images/Four_Filters .png )
224+ ![ Convolution_with_filters_simple_filtering ] ( images/Convolution_with_filters_simple_filtering .png )
46225
47226Full code is available here: [ Simple_Filtering.py] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Simple_Filtering.py )
48227
0 commit comments