Skip to content

Commit 62bf396

Browse files
Update README.md
1 parent 9119fa7 commit 62bf396

File tree

1 file changed

+180
-1
lines changed

1 file changed

+180
-1
lines changed

README.md

Lines changed: 180 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
4144
import 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

47226
Full 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

Comments
 (0)