Super-resolution and Deblurring


By Prof. Seungchul Lee
http://iai.postech.ac.kr/
Industrial AI Lab at POSTECH

Table of Contents

1. Image RestorationĀ¶





  • Image restoration tries to recover original image from degraded one with prior knowledge of degradation process.
  • The sources of corruption in digital images arise during image acquisition (digitization) and transmission.

    • Imaging sensors can be affected by ambient conditions.
    • Interference can be added to an image during transmission.

2. Inverse ProblemĀ¶




  • The reconstruction is the inverse of the acquisition.
  • Inverse problems involve modeling of degradation and applying the inverse process in order to recover the original image from inadequate observations.
  • The observations contain incomplete information about the target parameter or data due to physical limitations of the measurement devices.
  • Consequently, solutions to inverse problems are non-unique.

3. Image Super-resolutionĀ¶

  • Restore High Resolution (HR) image from Low Resolution (LR) image




- There are numerous learning-based SR approaches.
InĀ [1]:
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
InĀ [2]:
train_lr = np.load('./data_files/lr_training.npy')
train_hr = np.load('./data_files/hr_training.npy')
test_lr = np.load('./data_files/lr_testing.npy')

n_train = train_lr.shape[0]
n_test = test_lr.shape[0]

print ("The number of training LR images : {}, shape : {}".format(n_train, train_lr.shape))
print ("The number of training HR images : {}, shape : {}".format(n_train, train_hr.shape))
print ("The number of testing LR images : {}, shape : {}".format(n_test, test_lr.shape))
The number of training LR images : 79, shape : (79, 112, 112, 1)
The number of training HR images : 79, shape : (79, 224, 224, 1)
The number of testing LR images : 20, shape : (20, 112, 112, 1)
InĀ [3]:
idx = np.random.randint(n_train)

plt.figure(figsize = (20,16))
plt.subplot(1,2,1)
plt.imshow(train_lr[idx][:,:,0], 'gray')
plt.title('Low-resolution image', fontsize = 20)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(train_hr[idx][:,:,0], 'gray')
plt.title('High-resolution image', fontsize = 20)
plt.axis('off')
plt.show()

3.2. Build a FCN ModelĀ¶



InĀ [4]:
inputs = tf.keras.Input(shape = (112, 112, 1))

# 3x3 convolutional layer
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(inputs)

# first residual block
x_skip = x
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Add()([x_skip, x])

# second residual block
x_skip = x
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Add()([x_skip, x])

# third residual block
x_skip = x
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Add()([x_skip, x])

# upsampling layer
x = tf.keras.layers.Conv2DTranspose(filters = 16, 
                                    kernel_size = (4,4),
                                    strides = (2,2),
                                    padding = 'SAME',
                                    activation = 'relu')(x)

# 3x3 convolutional layer
outputs = tf.keras.layers.Conv2D(filters = 1,
                                 kernel_size = (3,3),
                                 padding = 'SAME',
                                 activation = 'sigmoid')(x)

model = tf.keras.Model(inputs, outputs)

3.3. TrainingĀ¶

InĀ [5]:
model.compile(optimizer = 'adam',
              loss = 'mean_absolute_error',
              metrics = ['mean_squared_error'])
InĀ [6]:
model.fit(train_lr, train_hr, batch_size = 16, epochs = 30)
Epoch 1/30
5/5 [==============================] - 3s 522ms/step - loss: 0.1700 - mean_squared_error: 0.0460
Epoch 2/30
5/5 [==============================] - 3s 519ms/step - loss: 0.1574 - mean_squared_error: 0.0488
Epoch 3/30
5/5 [==============================] - 3s 528ms/step - loss: 0.1559 - mean_squared_error: 0.0479
Epoch 4/30
5/5 [==============================] - 3s 523ms/step - loss: 0.1539 - mean_squared_error: 0.0445
Epoch 5/30
5/5 [==============================] - 3s 523ms/step - loss: 0.1512 - mean_squared_error: 0.0451
Epoch 6/30
5/5 [==============================] - 3s 529ms/step - loss: 0.1485 - mean_squared_error: 0.0437
Epoch 7/30
5/5 [==============================] - 3s 524ms/step - loss: 0.1446 - mean_squared_error: 0.0402
Epoch 8/30
5/5 [==============================] - 3s 523ms/step - loss: 0.1387 - mean_squared_error: 0.0388
Epoch 9/30
5/5 [==============================] - 3s 520ms/step - loss: 0.1302 - mean_squared_error: 0.0334
Epoch 10/30
5/5 [==============================] - 3s 524ms/step - loss: 0.1201 - mean_squared_error: 0.0285
Epoch 11/30
5/5 [==============================] - 3s 525ms/step - loss: 0.1092 - mean_squared_error: 0.0228
Epoch 12/30
5/5 [==============================] - 4s 820ms/step - loss: 0.0999 - mean_squared_error: 0.0185
Epoch 13/30
5/5 [==============================] - 3s 564ms/step - loss: 0.0995 - mean_squared_error: 0.0177
Epoch 14/30
5/5 [==============================] - 3s 530ms/step - loss: 0.0932 - mean_squared_error: 0.0155
Epoch 15/30
5/5 [==============================] - 3s 531ms/step - loss: 0.0904 - mean_squared_error: 0.0144
Epoch 16/30
5/5 [==============================] - 3s 530ms/step - loss: 0.0868 - mean_squared_error: 0.0134
Epoch 17/30
5/5 [==============================] - 3s 527ms/step - loss: 0.0819 - mean_squared_error: 0.0121
Epoch 18/30
5/5 [==============================] - 3s 530ms/step - loss: 0.0791 - mean_squared_error: 0.0112
Epoch 19/30
5/5 [==============================] - 3s 522ms/step - loss: 0.0744 - mean_squared_error: 0.0102
Epoch 20/30
5/5 [==============================] - 3s 525ms/step - loss: 0.0726 - mean_squared_error: 0.0097
Epoch 21/30
5/5 [==============================] - 3s 525ms/step - loss: 0.0715 - mean_squared_error: 0.0094
Epoch 22/30
5/5 [==============================] - 3s 531ms/step - loss: 0.0697 - mean_squared_error: 0.0090
Epoch 23/30
5/5 [==============================] - 3s 528ms/step - loss: 0.0665 - mean_squared_error: 0.0083
Epoch 24/30
5/5 [==============================] - 3s 529ms/step - loss: 0.0652 - mean_squared_error: 0.0080
Epoch 25/30
5/5 [==============================] - 3s 528ms/step - loss: 0.0637 - mean_squared_error: 0.0077
Epoch 26/30
5/5 [==============================] - 3s 526ms/step - loss: 0.0633 - mean_squared_error: 0.0075
Epoch 27/30
5/5 [==============================] - 3s 529ms/step - loss: 0.0618 - mean_squared_error: 0.0072
Epoch 28/30
5/5 [==============================] - 3s 568ms/step - loss: 0.0626 - mean_squared_error: 0.0073
Epoch 29/30
5/5 [==============================] - 3s 527ms/step - loss: 0.0623 - mean_squared_error: 0.0073
Epoch 30/30
5/5 [==============================] - 3s 533ms/step - loss: 0.0613 - mean_squared_error: 0.0070
Out[6]:
<tensorflow.python.keras.callbacks.History at 0x168acfb49b0>

3.4. TestingĀ¶

InĀ [7]:
test_x = test_lr[[3]]
test_sr = model.predict(test_x)

plt.figure(figsize = (20,16))
plt.subplot(1,2,1)
plt.imshow(test_x[0][:,:,0], 'gray')
plt.title('Low-resolution image', fontsize = 20)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(test_sr[0][:,:,0], 'gray')
plt.title('Super-resolved image', fontsize = 20)
plt.axis('off')
plt.show()

4. Image DeblurringĀ¶

4.1. Blurred and Deblurred ImagesĀ¶

Download data from here

InĀ [8]:
train_blur = np.load('./data_files/blur_training.npy')
train_deblur = np.load('./data_files/deblur_training.npy')
test_blur = np.load('./data_files/blur_testing.npy')

n_train = train_blur.shape[0]
n_test = test_blur.shape[0]

print ("The number of training blur images : {}, shape : {}".format(n_train, train_blur.shape))
print ("The number of training deblur images : {}, shape : {}".format(n_train, train_deblur.shape))
print ("The number of testing blur images : {}, shape : {}".format(n_test, test_blur.shape))
The number of training blur images : 79, shape : (79, 224, 224, 1)
The number of training deblur images : 79, shape : (79, 224, 224, 1)
The number of testing blur images : 20, shape : (20, 224, 224, 1)
InĀ [9]:
idx = np.random.randint(n_train)

plt.figure(figsize = (20,16))
plt.subplot(1,2,1)
plt.imshow(train_blur[idx][:,:,0], 'gray')
plt.title('Blurred image', fontsize = 20)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(train_deblur[idx][:,:,0], 'gray')
plt.title('Deblurred image', fontsize = 20)
plt.axis('off')
plt.show()

4.2. Build a FCN ModelĀ¶



InĀ [10]:
inputs = tf.keras.Input(shape = (224, 224, 1))

# 3x3 convolutional layer
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(inputs)

# first residual block
x_skip = x
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Add()([x_skip, x])

# second residual block
x_skip = x
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Add()([x_skip, x])

# third residual block
x_skip = x
x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Conv2D(filters = 16,
                           kernel_size = (3,3),
                           padding = 'SAME',
                           activation = 'relu')(x)

x = tf.keras.layers.Add()([x_skip, x])

# 3x3 convolutional layer
outputs = tf.keras.layers.Conv2D(filters = 1,
                                 kernel_size = (3,3),
                                 padding = 'SAME',
                                 activation = 'sigmoid')(x)

model = tf.keras.Model(inputs, outputs)

4.3. TrainingĀ¶

InĀ [11]:
model.compile(optimizer = 'adam',
              loss ='mean_absolute_error',
              metrics = ['mean_squared_error'])
InĀ [12]:
model.fit(train_blur, train_deblur, batch_size = 16, epochs = 30)
Epoch 1/30
5/5 [==============================] - 7s 1s/step - loss: 0.1637 - mean_squared_error: 0.0458
Epoch 2/30
5/5 [==============================] - 7s 1s/step - loss: 0.1581 - mean_squared_error: 0.0508
Epoch 3/30
5/5 [==============================] - 7s 1s/step - loss: 0.1486 - mean_squared_error: 0.0430
Epoch 4/30
5/5 [==============================] - 6s 1s/step - loss: 0.1385 - mean_squared_error: 0.0379
Epoch 5/30
5/5 [==============================] - 6s 1s/step - loss: 0.1240 - mean_squared_error: 0.0301
Epoch 6/30
5/5 [==============================] - 6s 1s/step - loss: 0.1049 - mean_squared_error: 0.0224
Epoch 7/30
5/5 [==============================] - 6s 1s/step - loss: 0.0837 - mean_squared_error: 0.0147
Epoch 8/30
5/5 [==============================] - 6s 1s/step - loss: 0.0713 - mean_squared_error: 0.0098
Epoch 9/30
5/5 [==============================] - 6s 1s/step - loss: 0.0658 - mean_squared_error: 0.0081
Epoch 10/30
5/5 [==============================] - 6s 1s/step - loss: 0.0676 - mean_squared_error: 0.0083
Epoch 11/30
5/5 [==============================] - 6s 1s/step - loss: 0.0644 - mean_squared_error: 0.0077
Epoch 12/30
5/5 [==============================] - 6s 1s/step - loss: 0.0595 - mean_squared_error: 0.0068
Epoch 13/30
5/5 [==============================] - 6s 1s/step - loss: 0.0579 - mean_squared_error: 0.0064
Epoch 14/30
5/5 [==============================] - 6s 1s/step - loss: 0.0566 - mean_squared_error: 0.0062
Epoch 15/30
5/5 [==============================] - 6s 1s/step - loss: 0.0553 - mean_squared_error: 0.0059
Epoch 16/30
5/5 [==============================] - 6s 1s/step - loss: 0.0534 - mean_squared_error: 0.0055
Epoch 17/30
5/5 [==============================] - 6s 1s/step - loss: 0.0516 - mean_squared_error: 0.0052
Epoch 18/30
5/5 [==============================] - 6s 1s/step - loss: 0.0499 - mean_squared_error: 0.0049
Epoch 19/30
5/5 [==============================] - 6s 1s/step - loss: 0.0487 - mean_squared_error: 0.0046
Epoch 20/30
5/5 [==============================] - 6s 1s/step - loss: 0.0483 - mean_squared_error: 0.0045
Epoch 21/30
5/5 [==============================] - 6s 1s/step - loss: 0.0489 - mean_squared_error: 0.0045
Epoch 22/30
5/5 [==============================] - 6s 1s/step - loss: 0.0474 - mean_squared_error: 0.0043
Epoch 23/30
5/5 [==============================] - 6s 1s/step - loss: 0.0469 - mean_squared_error: 0.0042
Epoch 24/30
5/5 [==============================] - 6s 1s/step - loss: 0.0446 - mean_squared_error: 0.0039
Epoch 25/30
5/5 [==============================] - 6s 1s/step - loss: 0.0442 - mean_squared_error: 0.0038
Epoch 26/30
5/5 [==============================] - 6s 1s/step - loss: 0.0435 - mean_squared_error: 0.0037
Epoch 27/30
5/5 [==============================] - 6s 1s/step - loss: 0.0438 - mean_squared_error: 0.0037
Epoch 28/30
5/5 [==============================] - 6s 1s/step - loss: 0.0432 - mean_squared_error: 0.0036
Epoch 29/30
5/5 [==============================] - 6s 1s/step - loss: 0.0421 - mean_squared_error: 0.0035
Epoch 30/30
5/5 [==============================] - 6s 1s/step - loss: 0.0433 - mean_squared_error: 0.0036
Out[12]:
<tensorflow.python.keras.callbacks.History at 0x168b5c02630>

4.4. TestingĀ¶

InĀ [13]:
test_x = test_blur[[1]]
test_deblur = model.predict(test_x)

plt.figure(figsize = (20,16))
plt.subplot(1,2,1)
plt.imshow(test_x[0][:,:,0], 'gray')
plt.title('Blurred image', fontsize = 20)
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(test_deblur[0][:,:,0], 'gray')
plt.title('Deblurred image', fontsize = 20)
plt.axis('off')
plt.show()
InĀ [14]:
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')