@@ -17,15 +17,17 @@ Image processing. Getting data from images in form of matrix with numbers, slici
17
17
18
18
## Content
19
19
Codes (it'll send you to appropriate file):
20
- * [ Opening_png_jpg] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Opening_png_jpg.py )
21
- * [ Converting_RGB_to_GreyScale] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Converting_RGB_to_GreyScale.py )
22
- * [ Simple_Filtering] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Simple_Filtering.py )
20
+ * [ Opening_png_jpg.py] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Opening_png_jpg.py )
21
+ * [ Converting_RGB_to_GreyScale.py] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Converting_RGB_to_GreyScale.py )
22
+ * [ Simple_Filtering.py] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Simple_Filtering.py )
23
+ * [ Convolution_of_Images.py] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Convolution_of_Images.py )
23
24
24
25
<br />
25
26
Experimental results (figures and tables on this page):
26
27
27
28
* <a href =" #RGB channels of the image separately " >RGB channels of the image separately</a >
28
29
* <a href =" #Examples of Simple Filtering for Edge Detection " >Examples of Simple Filtering for Edge Detection</a >
30
+ * <a href =" #Convolution of Images " >Convolution of Images</a >
29
31
30
32
<br />
31
33
@@ -142,6 +144,225 @@ Full code is available here: [Simple_Filtering.py](https://github.com/sichkar-va
142
144
143
145
<br />
144
146
147
+ ### <a name =" Convolution of Images " >Convolution of Images</a >
148
+ Implementing image processing via convolution operation.
149
+ <br />Creating dunction for convolution, defining filters and showing resulted images.
150
+
151
+ Reading images, cropping and resizing them.
152
+ <br />Consider following part of the code:
153
+
154
+ ``` py
155
+ # Importing needed libraries
156
+ import numpy as np
157
+ import matplotlib.pyplot as plt
158
+ from scipy.misc import imread, imresize
159
+
160
+ # Reading images
161
+ cat, dog = imread(' images/cat.jpg' ), imread(' images/dog.jpg' )
162
+
163
+ # Defining difference between width and height
164
+ print (cat.shape) # (1080, 1920, 3)
165
+ print (dog.shape) # (1050, 1680, 3)
166
+ difference_cat = cat.shape[1 ] - cat.shape[0 ]
167
+ difference_dog = dog.shape[1 ] - dog.shape[0 ]
168
+ # Cropping images to make it square size
169
+ # Cropping by width and taking middle part
170
+ cat_cropped = cat[:, int (difference_cat / 2 ):int (- difference_cat / 2 ), :]
171
+ dog_cropped = dog[:, int (difference_dog / 2 ):int (- difference_dog / 2 ), :]
172
+ print (cat_cropped.shape) # (1080, 1080, 3)
173
+ print (dog_cropped.shape) # (1050, 1050, 3)
174
+
175
+ # Defining needed image size for resizing
176
+ image_size = 200
177
+ # Defining output array for new images
178
+ # For 2 images with height = width = image_size and 3 channels
179
+ # (channels come at the end in order to show resized image)
180
+ image_resized = np.zeros((2 , image_size, image_size, 3 ))
181
+ print (image_resized.shape) # (2, 200, 200, 3)
182
+ # Resizing two images
183
+ image_resized[0 , :, :, :] = imresize(cat_cropped, (image_size, image_size)) # (200, 200, 3)
184
+ image_resized[1 , :, :, :] = imresize(dog_cropped, (image_size, image_size)) # (200, 200, 3)
185
+ ```
186
+
187
+ Preparing data for convolution operation.
188
+ <br />Consider following part of the code:
189
+
190
+ ``` py
191
+ # Defining output array for new image
192
+ # For 2 images with 3 channels and height = width = image_size
193
+ x = np.zeros((2 , 3 , image_size, image_size))
194
+ # Resizing two images
195
+ # And transposing in order to put channels first
196
+ x[0 , :, :, :] = imresize(cat_cropped, (image_size, image_size)).transpose((2 , 0 , 1 ))
197
+ x[1 , :, :, :] = imresize(dog_cropped, (image_size, image_size)).transpose((2 , 0 , 1 ))
198
+ print (x[0 ].shape) # (3, 200, 200)
199
+ print (x[1 ].shape) # (3, 200, 200)
200
+ ```
201
+
202
+ Preparing weights for convolution for 2 filters with 3 channels and size 3x3.
203
+ <br />Consider following part of the code:
204
+
205
+ ``` py
206
+ # Defining array for weights
207
+ w = np.zeros((2 , 3 , 3 , 3 ))
208
+
209
+ # First filter converts images into grayscale
210
+ # Defining three channels for this filter - red, green and blue
211
+ w[0 , 0 , :, :] = [[0 , 0 , 0 ], [0 , 0.3 , 0 ], [0 , 0 , 0 ]]
212
+ w[0 , 1 , :, :] = [[0 , 0 , 0 ], [0 , 0.6 , 0 ], [0 , 0 , 0 ]]
213
+ w[0 , 2 , :, :] = [[0 , 0 , 0 ], [0 , 0.1 , 0 ], [0 , 0 , 0 ]]
214
+
215
+ # Second filter will detect horizontal edges in the blue channel
216
+ w[1 , 2 , :, :] = [[1 , 2 , 1 ], [0 , 0 , 0 ], [- 1 , - 2 , - 1 ]]
217
+
218
+ # Defining 128 biases for the edge detection filter
219
+ # in order to make output non-negative
220
+ b = np.array([0 , 128 ])
221
+ ```
222
+
223
+ Defining function for naive forward pass with convolution.
224
+ <br />Consider following part of the code:
225
+
226
+ ``` py
227
+ """
228
+ Input consists of following:
229
+ x of shape (N, C, H, W) - N data, each with C channels, height H and width W.
230
+ w of shape (F, C, HH, WW) - We convolve each input with F different filters,
231
+ where each filter spans all C channels; each filter has height HH and width WW.
232
+
233
+ 'cnn_params' is a dictionary with following keys:
234
+ 'stride' - step for sliding
235
+ 'pad' - zero-pad frame around input
236
+
237
+ Function returns volume of feature maps of shape (N, F, H', W') where:
238
+ H' = 1 + (H + 2 * pad - HH) / stride
239
+ W' = 1 + (W + 2 * pad - WW) / stride
240
+
241
+ N here is the same as we have it as number of input images.
242
+ F here is as number of channels of each N (that are now as feature maps)
243
+
244
+ """
245
+
246
+
247
+ def cnn_forward_naive (x , w , b , cnn_params ):
248
+ # Preparing parameters for convolution operation
249
+ stride = cnn_params[' stride' ]
250
+ pad = cnn_params[' pad' ]
251
+ N, C, H, W = x.shape
252
+ F, _, HH , WW = w.shape
253
+
254
+ # Applying to the input image volume Pad frame with zero values for all channels
255
+ # As we have in input x N as number of inputs, C as number of channels,
256
+ # then we don't have to pad them
257
+ # That's why we leave first two tuples with 0 - (0, 0), (0, 0)
258
+ # And two last tuples with pad parameter - (pad, pad), (pad, pad)
259
+ # In this way we pad only H and W of N inputs with C channels
260
+ x_padded = np.pad(x, ((0 , 0 ), (0 , 0 ), (pad, pad), (pad, pad)), mode = ' constant' , constant_values = 0 )
261
+
262
+ # Defining spatial size of output image volume (feature maps) by following formulas:
263
+ height_out = int (1 + (H + 2 * pad - HH ) / stride)
264
+ width_out = int (1 + (W + 2 * pad - WW ) / stride)
265
+ # Depth of output volume is number of filters which is F
266
+ # And number of input images N remains the same - it is number of output image volumes now
267
+
268
+ # Creating zero valued volume for output feature maps
269
+ feature_maps = np.zeros((N, F, height_out, width_out))
270
+
271
+ # Implementing convolution through N input images, each with F filters
272
+ # Also, with respect to C channels
273
+ # For every image
274
+ for n in range (N):
275
+ # For every filter
276
+ for f in range (F):
277
+ # Defining variable for indexing height in output feature map
278
+ # (because our step might not be equal to 1)
279
+ height_index = 0
280
+ # Convolving every channel of the image with every channel of the current filter
281
+ # Result is summed up
282
+ # Going through all input image (2D convolution) through all channels
283
+ for i in range (0 , H, stride):
284
+ # Defining variable for indexing width in output feature map
285
+ # (because our step might not be equal to 1)
286
+ width_index = 0
287
+ for j in range (0 , W, stride):
288
+ feature_maps[n, f, height_index, width_index] = \
289
+ np.sum(x_padded[n, :, i:i+ HH , j:j+ WW ] * w[f, :, :, :]) + b[f]
290
+ # Increasing index for width
291
+ width_index += 1
292
+ # Increasing index for height
293
+ height_index += 1
294
+
295
+ # Returning resulted volumes of feature maps and cash
296
+ return feature_maps
297
+ ```
298
+
299
+ Implementing convolution of each image with each filter and offsetting by bias.
300
+ <br />Consider following part of the code:
301
+
302
+ ``` py
303
+ results = cnn_forward_naive(x, w, b, {' stride' : 1 , ' pad' : 1 })
304
+ print (results.shape) # (2, 2, 200, 200) - two images with two channels
305
+ ```
306
+
307
+ Creating function for normalizing resulted images.
308
+ <br />Consider following part of the code:
309
+
310
+ ``` py
311
+ def normalize_image (img ):
312
+ image_max, image_min = np.max(img), np.min(img)
313
+ return 255 * (img - image_min) / (image_max - image_min)
314
+ ```
315
+
316
+ Preparing figures for plotting.
317
+ <br />Consider following part of the code:
318
+
319
+ ``` py
320
+ figure_1, ax = plt.subplots(nrows = 2 , ncols = 5 )
321
+ # 'ax 'is as (2, 5) np array and we can call each time ax[0, 0]
322
+
323
+ # Plotting original, cropped and resized images
324
+ # By adding 'astype' we convert float numbers to integer
325
+ ax[0 , 0 ].imshow(cat)
326
+ ax[0 , 0 ].set_title(' Original (900, 1600, 3))' )
327
+ ax[0 , 1 ].imshow(cat_cropped)
328
+ ax[0 , 1 ].set_title(' Cropped (900, 900, 3)' )
329
+ ax[0 , 2 ].imshow(image_resized[0 , :, :, :].astype(' int' ))
330
+ ax[0 , 2 ].set_title(' Resized (200, 200, 3)' )
331
+ ax[0 , 3 ].imshow(normalize_image(results[0 , 0 ]), cmap = plt.get_cmap(' gray' ))
332
+ ax[0 , 3 ].set_title(' Grayscale' )
333
+ ax[0 , 4 ].imshow(normalize_image(results[0 , 1 ]), cmap = plt.get_cmap(' gray' ))
334
+ ax[0 , 4 ].set_title(' Edges' )
335
+
336
+ ax[1 , 0 ].imshow(dog)
337
+ ax[1 , 0 ].set_title(' Original (1050, 1680, 3)' )
338
+ ax[1 , 1 ].imshow(dog_cropped)
339
+ ax[1 , 1 ].set_title(' Cropped (1050, 1050, 3)' )
340
+ ax[1 , 2 ].imshow(image_resized[1 , :, :, :].astype(' int' ))
341
+ ax[1 , 2 ].set_title(' Resized (200, 200, 3)' )
342
+ ax[1 , 3 ].imshow(normalize_image(results[1 , 0 ]), cmap = plt.get_cmap(' gray' ))
343
+ ax[1 , 3 ].set_title(' Grayscale' )
344
+ ax[1 , 4 ].imshow(normalize_image(results[1 , 1 ]), cmap = plt.get_cmap(' gray' ))
345
+ ax[1 , 4 ].set_title(' Edges' )
346
+
347
+ # Setting axes 'off'
348
+ for i in range (2 ):
349
+ for j in range (5 ):
350
+ ax[i, j].set_axis_off()
351
+
352
+ # Giving the name to the window with figure
353
+ figure_1.canvas.set_window_title(' Image convolution' )
354
+ # Showing the plots
355
+ plt.show()
356
+ ```
357
+
358
+ Showing resulted images on the figure.
359
+
360
+ ![ Convolution_of_Images] ( images/Image_convolution.png )
361
+
362
+ Full code is available here: [ Convolution_of_Images.py] ( https://github.com/sichkar-valentyn/Image_processing_in_Python/tree/master/Codes/Convolution_of_Images.py )
363
+
364
+ <br />
365
+
145
366
### MIT License
146
367
### Copyright (c) 2018 Valentyn N Sichkar
147
368
### github.com/sichkar-valentyn
0 commit comments