Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
keras-team
GitHub Repository: keras-team/keras-io
Path: blob/master/examples/generative/deep_dream.py
3507 views
1
"""
2
Title: Deep Dream
3
Author: [fchollet](https://twitter.com/fchollet)
4
Date created: 2016/01/13
5
Last modified: 2020/05/02
6
Description: Generating Deep Dreams with Keras.
7
Accelerator: GPU
8
"""
9
10
"""
11
## Introduction
12
13
"Deep dream" is an image-filtering technique which consists of taking an image
14
classification model, and running gradient ascent over an input image to
15
try to maximize the activations of specific layers (and sometimes, specific units in
16
specific layers) for this input. It produces hallucination-like visuals.
17
18
It was first introduced by Alexander Mordvintsev from Google in July 2015.
19
20
Process:
21
22
- Load the original image.
23
- Define a number of processing scales ("octaves"),
24
from smallest to largest.
25
- Resize the original image to the smallest scale.
26
- For every scale, starting with the smallest (i.e. current one):
27
- Run gradient ascent
28
- Upscale image to the next scale
29
- Reinject the detail that was lost at upscaling time
30
- Stop when we are back to the original size.
31
To obtain the detail lost during upscaling, we simply
32
take the original image, shrink it down, upscale it,
33
and compare the result to the (resized) original image.
34
"""
35
36
"""
37
## Setup
38
"""
39
import os
40
41
os.environ["KERAS_BACKEND"] = "tensorflow"
42
43
import numpy as np
44
import tensorflow as tf
45
import keras
46
from keras.applications import inception_v3
47
48
base_image_path = keras.utils.get_file("sky.jpg", "https://i.imgur.com/aGBdQyK.jpg")
49
result_prefix = "sky_dream"
50
51
# These are the names of the layers
52
# for which we try to maximize activation,
53
# as well as their weight in the final loss
54
# we try to maximize.
55
# You can tweak these setting to obtain new visual effects.
56
layer_settings = {
57
"mixed4": 1.0,
58
"mixed5": 1.5,
59
"mixed6": 2.0,
60
"mixed7": 2.5,
61
}
62
63
# Playing with these hyperparameters will also allow you to achieve new effects
64
step = 0.01 # Gradient ascent step size
65
num_octave = 3 # Number of scales at which to run gradient ascent
66
octave_scale = 1.4 # Size ratio between scales
67
iterations = 20 # Number of ascent steps per scale
68
max_loss = 15.0
69
70
"""
71
This is our base image:
72
"""
73
74
from IPython.display import Image, display
75
76
display(Image(base_image_path))
77
78
"""
79
Let's set up some image preprocessing/deprocessing utilities:
80
"""
81
82
83
def preprocess_image(image_path):
84
# Util function to open, resize and format pictures
85
# into appropriate arrays.
86
img = keras.utils.load_img(image_path)
87
img = keras.utils.img_to_array(img)
88
img = np.expand_dims(img, axis=0)
89
img = inception_v3.preprocess_input(img)
90
return img
91
92
93
def deprocess_image(x):
94
# Util function to convert a NumPy array into a valid image.
95
x = x.reshape((x.shape[1], x.shape[2], 3))
96
# Undo inception v3 preprocessing
97
x /= 2.0
98
x += 0.5
99
x *= 255.0
100
# Convert to uint8 and clip to the valid range [0, 255]
101
x = np.clip(x, 0, 255).astype("uint8")
102
return x
103
104
105
"""
106
## Compute the Deep Dream loss
107
108
First, build a feature extraction model to retrieve the activations of our target layers
109
given an input image.
110
"""
111
112
# Build an InceptionV3 model loaded with pre-trained ImageNet weights
113
model = inception_v3.InceptionV3(weights="imagenet", include_top=False)
114
115
# Get the symbolic outputs of each "key" layer (we gave them unique names).
116
outputs_dict = dict(
117
[
118
(layer.name, layer.output)
119
for layer in [model.get_layer(name) for name in layer_settings.keys()]
120
]
121
)
122
123
# Set up a model that returns the activation values for every target layer
124
# (as a dict)
125
feature_extractor = keras.Model(inputs=model.inputs, outputs=outputs_dict)
126
127
"""
128
The actual loss computation is very simple:
129
"""
130
131
132
def compute_loss(input_image):
133
features = feature_extractor(input_image)
134
# Initialize the loss
135
loss = tf.zeros(shape=())
136
for name in features.keys():
137
coeff = layer_settings[name]
138
activation = features[name]
139
# We avoid border artifacts by only involving non-border pixels in the loss.
140
scaling = tf.reduce_prod(tf.cast(tf.shape(activation), "float32"))
141
loss += coeff * tf.reduce_sum(tf.square(activation[:, 2:-2, 2:-2, :])) / scaling
142
return loss
143
144
145
"""
146
## Set up the gradient ascent loop for one octave
147
"""
148
149
150
@tf.function
151
def gradient_ascent_step(img, learning_rate):
152
with tf.GradientTape() as tape:
153
tape.watch(img)
154
loss = compute_loss(img)
155
# Compute gradients.
156
grads = tape.gradient(loss, img)
157
# Normalize gradients.
158
grads /= tf.maximum(tf.reduce_mean(tf.abs(grads)), 1e-6)
159
img += learning_rate * grads
160
return loss, img
161
162
163
def gradient_ascent_loop(img, iterations, learning_rate, max_loss=None):
164
for i in range(iterations):
165
loss, img = gradient_ascent_step(img, learning_rate)
166
if max_loss is not None and loss > max_loss:
167
break
168
print("... Loss value at step %d: %.2f" % (i, loss))
169
return img
170
171
172
"""
173
## Run the training loop, iterating over different octaves
174
"""
175
176
original_img = preprocess_image(base_image_path)
177
original_shape = original_img.shape[1:3]
178
179
successive_shapes = [original_shape]
180
for i in range(1, num_octave):
181
shape = tuple([int(dim / (octave_scale**i)) for dim in original_shape])
182
successive_shapes.append(shape)
183
successive_shapes = successive_shapes[::-1]
184
shrunk_original_img = tf.image.resize(original_img, successive_shapes[0])
185
186
img = tf.identity(original_img) # Make a copy
187
for i, shape in enumerate(successive_shapes):
188
print("Processing octave %d with shape %s" % (i, shape))
189
img = tf.image.resize(img, shape)
190
img = gradient_ascent_loop(
191
img, iterations=iterations, learning_rate=step, max_loss=max_loss
192
)
193
upscaled_shrunk_original_img = tf.image.resize(shrunk_original_img, shape)
194
same_size_original = tf.image.resize(original_img, shape)
195
lost_detail = same_size_original - upscaled_shrunk_original_img
196
197
img += lost_detail
198
shrunk_original_img = tf.image.resize(original_img, shape)
199
200
keras.utils.save_img(result_prefix + ".png", deprocess_image(img.numpy()))
201
202
"""
203
Display the result.
204
205
You can use the trained model hosted on [Hugging Face Hub](https://huggingface.co/keras-io/deep-dream)
206
and try the demo on [Hugging Face Spaces](https://huggingface.co/spaces/keras-io/deep-dream).
207
"""
208
209
display(Image(result_prefix + ".png"))
210
211