title convolutional autoencoder for image denoising santiago l valdarramahttps twitter comsvpino date created 20210301 last modified 20210301 description how to train a deep convolutional autoencoder for image denoising accelerator gpu introduction this example demonstrates how to implement a deep convolutional autoencoder for image denoising mapping noisy digits images from the mnist dataset to clean digits images this implementation is based on an original blog post titled building autoencoders in kerashttps blog keras iobuildingautoencodersinkeras html by franois chollethttps twitter comfchollet setup normalizes the supplied array and reshapes it array array astypefloat32 255 0 array np reshapearray lenarray 28 28 1 return array def noisearray displays ten random images from each array n 10 indices np random randintlenarray1 sizen images1 array1indices images2 array2indices plt figurefigsize20 4 for i image1 image2 in enumeratezipimages1 images2 ax plt subplot2 n i 1 plt imshowimage1 reshape28 28 plt gray ax getxaxis setvisiblefalse ax getyaxis setvisiblefalse ax plt subplot2 n i 1 n plt imshowimage2 reshape28 28 plt gray ax getxaxis setvisiblefalse ax getyaxis setvisiblefalse plt show prepare the data since we only need images from the dataset to encode and decode we won t use the labels traindata testdata mnist loaddata normalize and reshape the data traindata preprocesstraindata testdata preprocesstestdata create a copy of the data with added noise noisytraindata noisetraindata noisytestdata noisetestdata display the train data and a version of it with added noise displaytraindata noisytraindata build the autoencoder input layers inputshape28 28 1 encoder x layers conv2d32 3 3 activationrelu paddingsameinput x layers maxpooling2d2 2 paddingsamex x layers conv2d32 3 3 activationrelu paddingsamex x layers maxpooling2d2 2 paddingsamex decoder x layers conv2dtranspose 32 3 3 strides2 activationrelu paddingsame x x layers conv2dtranspose 32 3 3 strides2 activationrelu paddingsame x x layers conv2d1 3 3 activationsigmoid paddingsamex autoencoder autoencoder modelinput x autoencoder compileoptimizeradam lossbinarycrossentropy autoencoder summary autoencoder fit xtraindata ytraindata epochs50 batchsize128 shuffletrue validationdatatestdata testdata predictions autoencoder predicttestdata displaytestdata predictions autoencoder fit xnoisytraindata ytraindata epochs100 batchsize128 shuffletrue validationdatanoisytestdata testdata predictions autoencoder predictnoisytestdata displaynoisytestdata predictions introduction this example demonstrates how to implement a deep convolutional autoencoder for image denoising mapping noisy digits images from the mnist dataset to clean digits images this implementation is based on an original blog post titled building autoencoders in keras https blog keras io building autoencoders in keras html by françois chollet https twitter com fchollet setup normalizes the supplied array and reshapes it adds random noise to each image in the supplied array displays ten random images from each array prepare the data since we only need images from the dataset to encode and decode we won t use the labels normalize and reshape the data create a copy of the data with added noise display the train data and a version of it with added noise build the autoencoder we are going to use the functional api to build our convolutional autoencoder encoder decoder autoencoder now we can train our autoencoder using train_data as both our input data and target notice we are setting up the validation data using the same format let s predict on our test dataset and display the original image together with the prediction from our autoencoder notice how the predictions are pretty close to the original images although not quite the same now that we know that our autoencoder works let s retrain it using the noisy data as our input and the clean data as our target we want our autoencoder to learn how to denoise the images let s now predict on the noisy data and display the results of our autoencoder notice how the autoencoder does an amazing job at removing the noise from the input images
import numpy as np
import matplotlib.pyplot as plt

from keras import layers
from keras.datasets import mnist
from keras.models import Model


def preprocess(array):
    
    array = array.astype("float32") / 255.0
    array = np.reshape(array, (len(array), 28, 28, 1))
    return array


def noise(array):
    
    noise_factor = 0.4
    noisy_array = array + noise_factor * np.random.normal(
        loc=0.0, scale=1.0, size=array.shape
    )

    return np.clip(noisy_array, 0.0, 1.0)


def display(array1, array2):
    
    n = 10
    indices = np.random.randint(len(array1), size=n)
    images1 = array1[indices, :]
    images2 = array2[indices, :]

    plt.figure(figsize=(20, 4))
    for i, (image1, image2) in enumerate(zip(images1, images2)):
        ax = plt.subplot(2, n, i + 1)
        plt.imshow(image1.reshape(28, 28))
        plt.gray()
        ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)

        ax = plt.subplot(2, n, i + 1 + n)
        plt.imshow(image2.reshape(28, 28))
        plt.gray()
        ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)

    plt.show()






(train_data, _), (test_data, _) = mnist.load_data()


train_data = preprocess(train_data)
test_data = preprocess(test_data)


noisy_train_data = noise(train_data)
noisy_test_data = noise(test_data)


display(train_data, noisy_train_data)



input = layers.Input(shape=(28, 28, 1))


x = layers.Conv2D(32, (3, 3), activation="relu", padding="same")(input)
x = layers.MaxPooling2D((2, 2), padding="same")(x)
x = layers.Conv2D(32, (3, 3), activation="relu", padding="same")(x)
x = layers.MaxPooling2D((2, 2), padding="same")(x)


x = layers.Conv2DTranspose(
    32, (3, 3), strides=2, activation="relu", padding="same"
)(x)
x = layers.Conv2DTranspose(
    32, (3, 3), strides=2, activation="relu", padding="same"
)(x)
x = layers.Conv2D(1, (3, 3), activation="sigmoid", padding="same")(x)


autoencoder = Model(input, x)
autoencoder.compile(optimizer="adam", loss="binary_crossentropy")
autoencoder.summary()



autoencoder.fit(
    x=train_data,
    y=train_data,
    epochs=50,
    batch_size=128,
    shuffle=True,
    validation_data=(test_data, test_data),
)



predictions = autoencoder.predict(test_data)
display(test_data, predictions)



autoencoder.fit(
    x=noisy_train_data,
    y=train_data,
    epochs=100,
    batch_size=128,
    shuffle=True,
    validation_data=(noisy_test_data, test_data),
)



predictions = autoencoder.predict(noisy_test_data)
display(noisy_test_data, predictions)