Upload 6 files
Browse files- autoencoders_MNIST_denoiser.py +126 -0
- autoencoders_face_reconstructions.py +136 -0
- denoising_autoencoder.model/keras_metadata.pb +3 -0
- denoising_autoencoder.model/saved_model.pb +3 -0
- denoising_autoencoder.model/variables/variables.data-00000-of-00001 +3 -0
- denoising_autoencoder.model/variables/variables.index +3 -0
autoencoders_MNIST_denoiser.py
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Autoencoder usages for denoising MNIST dataset.
|
2 |
+
# Learning how to use autoencoder for a denoising task.
|
3 |
+
# This will later be used in my project for denoising sensor data of MOS for gas sensing.
|
4 |
+
|
5 |
+
# YouTube Resource Credits: https://www.youtube.com/watch?v=Sm54KXD-L1k
|
6 |
+
|
7 |
+
# We are going to encode an image and then decode it to see if the image is denoised, in which the bottleneck layer will loss some information,
|
8 |
+
# which will be used to learn the features of the image.
|
9 |
+
|
10 |
+
# Noise Reduction is a common problem, in which autoencoders are used to solve this problem by reconstructing the image.
|
11 |
+
|
12 |
+
# We will be using Keras and Tensorflow for this task.
|
13 |
+
from keras.datasets import mnist
|
14 |
+
from tensorflow.keras.layers import Conv2D, MaxPooling2D, UpSampling2D
|
15 |
+
from tensorflow.keras.models import Sequential
|
16 |
+
import numpy as np
|
17 |
+
import random, cv2
|
18 |
+
from matplotlib import pyplot as plt
|
19 |
+
|
20 |
+
|
21 |
+
def sp_noise(image,prob):
|
22 |
+
'''
|
23 |
+
Add salt and pepper noise to image
|
24 |
+
prob: Probability of the noise
|
25 |
+
'''
|
26 |
+
output = np.zeros(image.shape,np.uint8)
|
27 |
+
thres = 1 - prob
|
28 |
+
for i in range(image.shape[0]):
|
29 |
+
for j in range(image.shape[1]):
|
30 |
+
rdn = random.random()
|
31 |
+
if rdn < prob:
|
32 |
+
output[i][j] = 0
|
33 |
+
elif rdn > thres:
|
34 |
+
output[i][j] = 255
|
35 |
+
else:
|
36 |
+
output[i][j] = image[i][j]
|
37 |
+
return output
|
38 |
+
|
39 |
+
(x_train, _), (x_test, _) = mnist.load_data() # We are not interested in the labels. 28x28x1 images.
|
40 |
+
|
41 |
+
# Same as normal face constructor, we simply test based on the MNIST and (transformed) blurred dataset
|
42 |
+
|
43 |
+
# Convert to 0-1 range
|
44 |
+
x_train = x_train.astype('float32') / 255.0
|
45 |
+
x_test = x_test.astype('float32') / 255.0
|
46 |
+
|
47 |
+
# Reshape the dataset
|
48 |
+
x_train = x_train.reshape((len(x_train), 28, 28, 1))
|
49 |
+
x_test = x_test.reshape((len(x_test), 28, 28, 1))
|
50 |
+
|
51 |
+
|
52 |
+
# Add noise to the dataset
|
53 |
+
|
54 |
+
# Guassin noise factor.
|
55 |
+
noise_factor = 0.5
|
56 |
+
x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train.shape)
|
57 |
+
x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test.shape)
|
58 |
+
|
59 |
+
# Clip the dataset to 0-1 range
|
60 |
+
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
|
61 |
+
x_test_noisy = np.clip(x_test_noisy, 0., 1.)
|
62 |
+
|
63 |
+
#Displaying images with noise
|
64 |
+
# plt.figure(figsize=(20, 2))
|
65 |
+
# for i in range(1,10):
|
66 |
+
# ax = plt.subplot(1, 10, i)
|
67 |
+
# plt.imshow(x_test_noisy[i].reshape(28, 28), cmap="binary")
|
68 |
+
# plt.show()
|
69 |
+
|
70 |
+
SIZE = 28
|
71 |
+
DIMENSIONS = 1
|
72 |
+
model = Sequential()
|
73 |
+
# Encoder Layer
|
74 |
+
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(SIZE, SIZE, DIMENSIONS)))
|
75 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Shrinking
|
76 |
+
model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
|
77 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Shrinking
|
78 |
+
model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
|
79 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Bottleneck
|
80 |
+
model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
|
81 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Bottleneck
|
82 |
+
model.add(Conv2D(512, (3, 3), activation='relu', padding='same'))
|
83 |
+
|
84 |
+
# Middle Layer
|
85 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Shrinking
|
86 |
+
|
87 |
+
# Decoder Layer
|
88 |
+
model.add(Conv2D(512, (3, 3), activation='relu', padding='same'))
|
89 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
90 |
+
model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
|
91 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
92 |
+
model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
|
93 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
94 |
+
model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
|
95 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
96 |
+
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
|
97 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
98 |
+
|
99 |
+
# Output Layer
|
100 |
+
model.add(Conv2D(DIMENSIONS, (5, 5), activation='relu'))
|
101 |
+
|
102 |
+
model.compile(optimizer='adam', loss='mean_squared_error', metrics=['accuracy'])
|
103 |
+
|
104 |
+
model.summary()
|
105 |
+
model.fit(x=x_train_noisy, y=x_train, epochs=3, batch_size=256, shuffle=True, validation_data=(x_test_noisy, x_test))
|
106 |
+
|
107 |
+
|
108 |
+
model.evaluate(x_test_noisy, x_test)
|
109 |
+
|
110 |
+
|
111 |
+
# Save model and show model outputs.
|
112 |
+
model.save('denoising_autoencoder.model')
|
113 |
+
|
114 |
+
no_noise_img = model.predict(x_test_noisy)
|
115 |
+
|
116 |
+
plt.figure(figsize=(40, 4))
|
117 |
+
for i in range(10):
|
118 |
+
# display original
|
119 |
+
ax = plt.subplot(3, 20, i + 1)
|
120 |
+
plt.imshow(x_test_noisy[i].reshape(28, 28), cmap="binary")
|
121 |
+
|
122 |
+
# display reconstructed (after noise removed) image
|
123 |
+
ax = plt.subplot(3, 20, 40 + i + 1)
|
124 |
+
plt.imshow(no_noise_img[i].reshape(28, 28), cmap="binary")
|
125 |
+
|
126 |
+
plt.waitforbuttonpress()
|
autoencoders_face_reconstructions.py
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Learning the basic structure of an autoencoder.
|
2 |
+
import tensorflow as tf
|
3 |
+
print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))
|
4 |
+
|
5 |
+
|
6 |
+
from tensorflow.keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
|
7 |
+
from tensorflow.keras.models import Sequential, Model
|
8 |
+
from keras.utils.image_utils import img_to_array, load_img
|
9 |
+
from matplotlib.pyplot import imshow
|
10 |
+
from PIL import Image, ImageDraw
|
11 |
+
import numpy as np
|
12 |
+
import cv2
|
13 |
+
|
14 |
+
np.random.seed(342) # Seed for reproducibility, we want to see the same results every time we run the code,
|
15 |
+
# reproducibility.
|
16 |
+
|
17 |
+
# Image Preprocessing
|
18 |
+
# Convert to an image numpy array: (float32)
|
19 |
+
# Batches
|
20 |
+
# Normalise the image.
|
21 |
+
profile_img = cv2.imread('profile.PNG')
|
22 |
+
profile_img = cv2.cvtColor(profile_img, cv2.COLOR_BGR2RGB) # convert to RGB.
|
23 |
+
print(profile_img.shape) # (28, 28, 3)
|
24 |
+
|
25 |
+
reshaped = cv2.resize(profile_img, (256, 256))
|
26 |
+
print(reshaped.shape) # (256, 256, 3)
|
27 |
+
img_array = img_to_array(reshaped).astype('float32') / 255. # Normalise the image.
|
28 |
+
# Need 1 batch of the image.
|
29 |
+
img_array = np.expand_dims(img_array, axis=0)
|
30 |
+
|
31 |
+
# cv2.imshow('Image', reshaped)
|
32 |
+
# cv2.waitKey(0)
|
33 |
+
|
34 |
+
# Get the image dimensions at batch x height x width x channels
|
35 |
+
# Roughly 1x28x28x3 dims.
|
36 |
+
print(img_array.shape) # (1, 256, 256, 3)
|
37 |
+
|
38 |
+
SIZE = 256
|
39 |
+
model = Sequential()
|
40 |
+
# Encoder Layer
|
41 |
+
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(SIZE, SIZE, 3)))
|
42 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Shrinking
|
43 |
+
model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
|
44 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Shrinking
|
45 |
+
model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
|
46 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Bottleneck
|
47 |
+
model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
|
48 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Bottleneck
|
49 |
+
model.add(Conv2D(512, (3, 3), activation='relu', padding='same'))
|
50 |
+
|
51 |
+
# Middle Layer
|
52 |
+
model.add(MaxPooling2D((2, 2), padding='same')) # Shrinking
|
53 |
+
|
54 |
+
# Decoder Layer
|
55 |
+
model.add(Conv2D(512, (3, 3), activation='relu', padding='same'))
|
56 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
57 |
+
model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
|
58 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
59 |
+
model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
|
60 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
61 |
+
model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
|
62 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
63 |
+
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
|
64 |
+
model.add(UpSampling2D((2, 2))) # Expanding
|
65 |
+
|
66 |
+
# Output Layer
|
67 |
+
model.add(Conv2D(3, (3, 3), activation='relu', padding='same'))
|
68 |
+
|
69 |
+
model.compile(optimizer='adam', loss='mean_squared_error', metrics=['accuracy'])
|
70 |
+
|
71 |
+
|
72 |
+
|
73 |
+
|
74 |
+
if __name__ == '__main__':
|
75 |
+
model.summary()
|
76 |
+
|
77 |
+
# Image Gif Generator based on keras callbacks.
|
78 |
+
model_outputs = []
|
79 |
+
|
80 |
+
|
81 |
+
def on_epoch_end(epoch, logs):
|
82 |
+
model_outputs.append(model.predict(img_array))
|
83 |
+
|
84 |
+
|
85 |
+
# Callbacks
|
86 |
+
predict_callback = tf.keras.callbacks.LambdaCallback(on_epoch_end=on_epoch_end)
|
87 |
+
|
88 |
+
# I realised Keras is really easy to use, and I am loving it.
|
89 |
+
# Training the model
|
90 |
+
model.fit(x=img_array, y=img_array, epochs=1000, batch_size=20, shuffle=True, callbacks=[predict_callback])
|
91 |
+
|
92 |
+
|
93 |
+
predict = model.predict(x=img_array) # We hope to get similar to the original image.
|
94 |
+
cv2.imshow("output", predict[0].reshape(SIZE, SIZE, 3))
|
95 |
+
cv2.waitKey(0)
|
96 |
+
|
97 |
+
print("Creating a gif/video from the model outputs.")
|
98 |
+
# Make a gif creator from an array of given images.
|
99 |
+
print(len(model_outputs)) # 50
|
100 |
+
|
101 |
+
images = [(output[0] * 255).astype('uint8') for output in model_outputs]
|
102 |
+
try:
|
103 |
+
images = [(output[0] * 255).astype('uint8') for output in model_outputs]
|
104 |
+
|
105 |
+
# Specify the video file name and codec
|
106 |
+
video_filename = 'model_outputs_5.4.mp4'
|
107 |
+
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Use appropriate codec for your system
|
108 |
+
|
109 |
+
# Get the height and width from the first image
|
110 |
+
height, width, _ = images[0].shape
|
111 |
+
|
112 |
+
# Create a VideoWriter object
|
113 |
+
fps = 30 # Adjust the frames per second (FPS) as needed
|
114 |
+
video = cv2.VideoWriter(video_filename, fourcc, fps, (width, height))
|
115 |
+
|
116 |
+
# Write each image to the video
|
117 |
+
for image in images:
|
118 |
+
# Convert BRG to RGB
|
119 |
+
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
120 |
+
video.write(rgb_image)
|
121 |
+
|
122 |
+
# Release the VideoWriter
|
123 |
+
video.release()
|
124 |
+
except Exception as e:
|
125 |
+
print(e)
|
126 |
+
images = [Image.fromarray((output[0] * 255).astype('uint8')) for output in model_outputs]
|
127 |
+
images[0].save('model_outputs_5.4m_param.gif', save_all=True, append_images=images[1:], optimize=False, duration=20,
|
128 |
+
loop=0)
|
129 |
+
#
|
130 |
+
|
131 |
+
# # Save the images as a GIF
|
132 |
+
#
|
133 |
+
|
134 |
+
images = [Image.fromarray((output[0] * 255).astype('uint8')) for output in model_outputs]
|
135 |
+
images[0].save('model_outputs_5.4m_param.gif', save_all=True, append_images=images[1:], optimize=False, duration=20,
|
136 |
+
loop=0)
|
denoising_autoencoder.model/keras_metadata.pb
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:68231aeb20103b779df4e60a2b53505d605cea8000cf0d18540dffbbbb393641
|
3 |
+
size 45912
|
denoising_autoencoder.model/saved_model.pb
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:216047dc3ab6b1cb38c3d93874e16a02f506d04f4fed5da2108c8fb67b262859
|
3 |
+
size 348938
|
denoising_autoencoder.model/variables/variables.data-00000-of-00001
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:dd07a3d1b98010a29c044ee1019dbc2394c481c2d8a0432ece60d03d6a287c0e
|
3 |
+
size 65972683
|
denoising_autoencoder.model/variables/variables.index
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:a0129990d23ee787363b7d7209534166ec9a34a1fe87d19ec0192c230e5df4b5
|
3 |
+
size 5371
|