Deep Dreaming in Keras.

Run the script with:

  1. python deep_dream.py path_to_your_base_image.jpg prefix_for_results

e.g.:

  1. python deep_dream.py img/mypic.jpg results/dream
  1. from __future__ import print_function
  2. from keras.preprocessing.image import load_img, save_img, img_to_array
  3. import numpy as np
  4. import scipy
  5. import argparse
  6. from keras.applications import inception_v3
  7. from keras import backend as K
  8. parser = argparse.ArgumentParser(description='Deep Dreams with Keras.')
  9. parser.add_argument('base_image_path', metavar='base', type=str,
  10. help='Path to the image to transform.')
  11. parser.add_argument('result_prefix', metavar='res_prefix', type=str,
  12. help='Prefix for the saved results.')
  13. args = parser.parse_args()
  14. base_image_path = args.base_image_path
  15. result_prefix = args.result_prefix
  16. # These are the names of the layers
  17. # for which we try to maximize activation,
  18. # as well as their weight in the final loss
  19. # we try to maximize.
  20. # You can tweak these setting to obtain new visual effects.
  21. settings = {
  22. 'features': {
  23. 'mixed2': 0.2,
  24. 'mixed3': 0.5,
  25. 'mixed4': 2.,
  26. 'mixed5': 1.5,
  27. },
  28. }
  29. def preprocess_image(image_path):
  30. # Util function to open, resize and format pictures
  31. # into appropriate tensors.
  32. img = load_img(image_path)
  33. img = img_to_array(img)
  34. img = np.expand_dims(img, axis=0)
  35. img = inception_v3.preprocess_input(img)
  36. return img
  37. def deprocess_image(x):
  38. # Util function to convert a tensor into a valid image.
  39. if K.image_data_format() == 'channels_first':
  40. x = x.reshape((3, x.shape[2], x.shape[3]))
  41. x = x.transpose((1, 2, 0))
  42. else:
  43. x = x.reshape((x.shape[1], x.shape[2], 3))
  44. x /= 2.
  45. x += 0.5
  46. x *= 255.
  47. x = np.clip(x, 0, 255).astype('uint8')
  48. return x
  49. K.set_learning_phase(0)
  50. # Build the InceptionV3 network with our placeholder.
  51. # The model will be loaded with pre-trained ImageNet weights.
  52. model = inception_v3.InceptionV3(weights='imagenet',
  53. include_top=False)
  54. dream = model.input
  55. print('Model loaded.')
  56. # Get the symbolic outputs of each "key" layer (we gave them unique names).
  57. layer_dict = dict([(layer.name, layer) for layer in model.layers])
  58. # Define the loss.
  59. loss = K.variable(0.)
  60. for layer_name in settings['features']:
  61. # Add the L2 norm of the features of a layer to the loss.
  62. if layer_name not in layer_dict:
  63. raise ValueError('Layer ' + layer_name + ' not found in model.')
  64. coeff = settings['features'][layer_name]
  65. x = layer_dict[layer_name].output
  66. # We avoid border artifacts by only involving non-border pixels in the loss.
  67. scaling = K.prod(K.cast(K.shape(x), 'float32'))
  68. if K.image_data_format() == 'channels_first':
  69. loss = loss + coeff * K.sum(K.square(x[:, :, 2: -2, 2: -2])) / scaling
  70. else:
  71. loss = loss + coeff * K.sum(K.square(x[:, 2: -2, 2: -2, :])) / scaling
  72. # Compute the gradients of the dream wrt the loss.
  73. grads = K.gradients(loss, dream)[0]
  74. # Normalize gradients.
  75. grads /= K.maximum(K.mean(K.abs(grads)), K.epsilon())
  76. # Set up function to retrieve the value
  77. # of the loss and gradients given an input image.
  78. outputs = [loss, grads]
  79. fetch_loss_and_grads = K.function([dream], outputs)
  80. def eval_loss_and_grads(x):
  81. outs = fetch_loss_and_grads([x])
  82. loss_value = outs[0]
  83. grad_values = outs[1]
  84. return loss_value, grad_values
  85. def resize_img(img, size):
  86. img = np.copy(img)
  87. if K.image_data_format() == 'channels_first':
  88. factors = (1, 1,
  89. float(size[0]) / img.shape[2],
  90. float(size[1]) / img.shape[3])
  91. else:
  92. factors = (1,
  93. float(size[0]) / img.shape[1],
  94. float(size[1]) / img.shape[2],
  95. 1)
  96. return scipy.ndimage.zoom(img, factors, order=1)
  97. def gradient_ascent(x, iterations, step, max_loss=None):
  98. for i in range(iterations):
  99. loss_value, grad_values = eval_loss_and_grads(x)
  100. if max_loss is not None and loss_value > max_loss:
  101. break
  102. print('..Loss value at', i, ':', loss_value)
  103. x += step * grad_values
  104. return x
  105. """Process:
  106. - Load the original image.
  107. - Define a number of processing scales (i.e. image shapes),
  108. from smallest to largest.
  109. - Resize the original image to the smallest scale.
  110. - For every scale, starting with the smallest (i.e. current one):
  111. - Run gradient ascent
  112. - Upscale image to the next scale
  113. - Reinject the detail that was lost at upscaling time
  114. - Stop when we are back to the original size.
  115. To obtain the detail lost during upscaling, we simply
  116. take the original image, shrink it down, upscale it,
  117. and compare the result to the (resized) original image.
  118. """
  119. # Playing with these hyperparameters will also allow you to achieve new effects
  120. step = 0.01 # Gradient ascent step size
  121. num_octave = 3 # Number of scales at which to run gradient ascent
  122. octave_scale = 1.4 # Size ratio between scales
  123. iterations = 20 # Number of ascent steps per scale
  124. max_loss = 10.
  125. img = preprocess_image(base_image_path)
  126. if K.image_data_format() == 'channels_first':
  127. original_shape = img.shape[2:]
  128. else:
  129. original_shape = img.shape[1:3]
  130. successive_shapes = [original_shape]
  131. for i in range(1, num_octave):
  132. shape = tuple([int(dim / (octave_scale ** i)) for dim in original_shape])
  133. successive_shapes.append(shape)
  134. successive_shapes = successive_shapes[::-1]
  135. original_img = np.copy(img)
  136. shrunk_original_img = resize_img(img, successive_shapes[0])
  137. for shape in successive_shapes:
  138. print('Processing image shape', shape)
  139. img = resize_img(img, shape)
  140. img = gradient_ascent(img,
  141. iterations=iterations,
  142. step=step,
  143. max_loss=max_loss)
  144. upscaled_shrunk_original_img = resize_img(shrunk_original_img, shape)
  145. same_size_original = resize_img(original_img, shape)
  146. lost_detail = same_size_original - upscaled_shrunk_original_img
  147. img += lost_detail
  148. shrunk_original_img = resize_img(original_img, shape)
  149. save_img(result_prefix + '.png', deprocess_image(np.copy(img)))