deepdream.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. # boilerplate code
  2. import numpy as np
  3. from functools import partial
  4. import PIL.Image
  5. import tensorflow as tf
  6. import matplotlib.pyplot as plt
  7. import urllib2
  8. import os
  9. import zipfile
  10. def main():
  11. # download pre-trained model by running the command below in a shell
  12. # wget https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip && unzip inception5h.zip
  13. url = 'https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip'
  14. data_dir = '../data/'
  15. model_name = os.path.split(url)[-1]
  16. local_zip_file = os.path.join(data_dir, model_name)
  17. if not os.path.exists(local_zip_file):
  18. # Download
  19. model_url = urllib2.urlopen(url)
  20. with open(local_zip_file, 'wb') as output:
  21. output.write(model_url.read())
  22. # Extract
  23. with zipfile.ZipFile(local_zip_file, 'r') as zip_ref:
  24. zip_ref.extractall(data_dir)
  25. # start with a gray image with a little noise
  26. img_noise = np.random.uniform(size=(224,224,3)) + 100.0
  27. model_fn = 'tensorflow_inception_graph.pb'
  28. # creating TensorFlow session and loading the model
  29. graph = tf.Graph()
  30. sess = tf.InteractiveSession(graph=graph)
  31. with tf.gfile.FastGFile(os.path.join(data_dir, model_fn), 'rb') as f:
  32. graph_def = tf.GraphDef()
  33. graph_def.ParseFromString(f.read())
  34. t_input = tf.placeholder(np.float32, name='input') # define the input tensor
  35. imagenet_mean = 117.0
  36. t_preprocessed = tf.expand_dims(t_input-imagenet_mean, 0)
  37. tf.import_graph_def(graph_def, {'input':t_preprocessed})
  38. layers = [op.name for op in graph.get_operations() if op.type=='Conv2D' and 'import/' in op.name]
  39. feature_nums = [int(graph.get_tensor_by_name(name+':0').get_shape()[-1]) for name in layers]
  40. print('Number of layers', len(layers))
  41. print('Total number of feature channels:', sum(feature_nums))
  42. # Helper functions for TF Graph visualization
  43. #pylint: disable=unused-variable
  44. def strip_consts(graph_def, max_const_size=32):
  45. """Strip large constant values from graph_def."""
  46. strip_def = tf.GraphDef()
  47. for n0 in graph_def.node:
  48. n = strip_def.node.add() #pylint: disable=maybe-no-member
  49. n.MergeFrom(n0)
  50. if n.op == 'Const':
  51. tensor = n.attr['value'].tensor
  52. size = len(tensor.tensor_content)
  53. if size > max_const_size:
  54. tensor.tensor_content = "<stripped %d bytes>"%size
  55. return strip_def
  56. def rename_nodes(graph_def, rename_func):
  57. res_def = tf.GraphDef()
  58. for n0 in graph_def.node:
  59. n = res_def.node.add() #pylint: disable=maybe-no-member
  60. n.MergeFrom(n0)
  61. n.name = rename_func(n.name)
  62. for i, s in enumerate(n.input):
  63. n.input[i] = rename_func(s) if s[0]!='^' else '^'+rename_func(s[1:])
  64. return res_def
  65. def showarray(a):
  66. a = np.uint8(np.clip(a, 0, 1)*255)
  67. plt.imshow(a)
  68. plt.show()
  69. def visstd(a, s=0.1):
  70. '''Normalize the image range for visualization'''
  71. return (a-a.mean())/max(a.std(), 1e-4)*s + 0.5
  72. def T(layer):
  73. '''Helper for getting layer output tensor'''
  74. return graph.get_tensor_by_name("import/%s:0"%layer)
  75. def render_naive(t_obj, img0=img_noise, iter_n=20, step=1.0):
  76. t_score = tf.reduce_mean(t_obj) # defining the optimization objective
  77. t_grad = tf.gradients(t_score, t_input)[0] # behold the power of automatic differentiation!
  78. img = img0.copy()
  79. for _ in range(iter_n):
  80. g, _ = sess.run([t_grad, t_score], {t_input:img})
  81. # normalizing the gradient, so the same step size should work
  82. g /= g.std()+1e-8 # for different layers and networks
  83. img += g*step
  84. showarray(visstd(img))
  85. def tffunc(*argtypes):
  86. '''Helper that transforms TF-graph generating function into a regular one.
  87. See "resize" function below.
  88. '''
  89. placeholders = list(map(tf.placeholder, argtypes))
  90. def wrap(f):
  91. out = f(*placeholders)
  92. def wrapper(*args, **kw):
  93. return out.eval(dict(zip(placeholders, args)), session=kw.get('session'))
  94. return wrapper
  95. return wrap
  96. # Helper function that uses TF to resize an image
  97. def resize(img, size):
  98. img = tf.expand_dims(img, 0)
  99. return tf.image.resize_bilinear(img, size)[0,:,:,:]
  100. resize = tffunc(np.float32, np.int32)(resize)
  101. def calc_grad_tiled(img, t_grad, tile_size=512):
  102. '''Compute the value of tensor t_grad over the image in a tiled way.
  103. Random shifts are applied to the image to blur tile boundaries over
  104. multiple iterations.'''
  105. sz = tile_size
  106. h, w = img.shape[:2]
  107. sx, sy = np.random.randint(sz, size=2)
  108. img_shift = np.roll(np.roll(img, sx, 1), sy, 0)
  109. grad = np.zeros_like(img)
  110. for y in range(0, max(h-sz//2, sz),sz):
  111. for x in range(0, max(w-sz//2, sz),sz):
  112. sub = img_shift[y:y+sz,x:x+sz]
  113. g = sess.run(t_grad, {t_input:sub})
  114. grad[y:y+sz,x:x+sz] = g
  115. return np.roll(np.roll(grad, -sx, 1), -sy, 0)
  116. def render_multiscale(t_obj, img0=img_noise, iter_n=10, step=1.0, octave_n=3, octave_scale=1.4):
  117. t_score = tf.reduce_mean(t_obj) # defining the optimization objective
  118. t_grad = tf.gradients(t_score, t_input)[0] # behold the power of automatic differentiation!
  119. img = img0.copy()
  120. for octave in range(octave_n):
  121. if octave>0:
  122. hw = np.float32(img.shape[:2])*octave_scale
  123. img = resize(img, np.int32(hw))
  124. for _ in range(iter_n):
  125. g = calc_grad_tiled(img, t_grad)
  126. # normalizing the gradient, so the same step size should work
  127. g /= g.std()+1e-8 # for different layers and networks
  128. img += g*step
  129. showarray(visstd(img))
  130. def lap_split(img):
  131. '''Split the image into lo and hi frequency components'''
  132. with tf.name_scope('split'):
  133. lo = tf.nn.conv2d(img, k5x5, [1,2,2,1], 'SAME')
  134. lo2 = tf.nn.conv2d_transpose(lo, k5x5*4, tf.shape(img), [1,2,2,1])
  135. hi = img-lo2
  136. return lo, hi
  137. def lap_split_n(img, n):
  138. '''Build Laplacian pyramid with n splits'''
  139. levels = []
  140. for _ in range(n):
  141. img, hi = lap_split(img)
  142. levels.append(hi)
  143. levels.append(img)
  144. return levels[::-1]
  145. def lap_merge(levels):
  146. '''Merge Laplacian pyramid'''
  147. img = levels[0]
  148. for hi in levels[1:]:
  149. with tf.name_scope('merge'):
  150. img = tf.nn.conv2d_transpose(img, k5x5*4, tf.shape(hi), [1,2,2,1]) + hi
  151. return img
  152. def normalize_std(img, eps=1e-10):
  153. '''Normalize image by making its standard deviation = 1.0'''
  154. with tf.name_scope('normalize'):
  155. std = tf.sqrt(tf.reduce_mean(tf.square(img)))
  156. return img/tf.maximum(std, eps)
  157. def lap_normalize(img, scale_n=4):
  158. '''Perform the Laplacian pyramid normalization.'''
  159. img = tf.expand_dims(img,0)
  160. tlevels = lap_split_n(img, scale_n)
  161. tlevels = list(map(normalize_std, tlevels))
  162. out = lap_merge(tlevels)
  163. return out[0,:,:,:]
  164. def render_lapnorm(t_obj, img0=img_noise, visfunc=visstd,
  165. iter_n=10, step=1.0, octave_n=3, octave_scale=1.4, lap_n=4):
  166. t_score = tf.reduce_mean(t_obj) # defining the optimization objective
  167. t_grad = tf.gradients(t_score, t_input)[0] # behold the power of automatic differentiation!
  168. # build the laplacian normalization graph
  169. lap_norm_func = tffunc(np.float32)(partial(lap_normalize, scale_n=lap_n))
  170. img = img0.copy()
  171. for octave in range(octave_n):
  172. if octave>0:
  173. hw = np.float32(img.shape[:2])*octave_scale
  174. img = resize(img, np.int32(hw))
  175. for _ in range(iter_n):
  176. g = calc_grad_tiled(img, t_grad)
  177. g = lap_norm_func(g)
  178. img += g*step
  179. showarray(visfunc(img))
  180. def render_deepdream(t_obj, img0=img_noise,
  181. iter_n=10, step=1.5, octave_n=4, octave_scale=1.4):
  182. t_score = tf.reduce_mean(t_obj) # defining the optimization objective
  183. t_grad = tf.gradients(t_score, t_input)[0] # behold the power of automatic differentiation!
  184. # split the image into a number of octaves
  185. img = img0
  186. octaves = []
  187. for _ in range(octave_n-1):
  188. hw = img.shape[:2]
  189. lo = resize(img, np.int32(np.float32(hw)/octave_scale))
  190. hi = img-resize(lo, hw)
  191. img = lo
  192. octaves.append(hi)
  193. # generate details octave by octave
  194. for octave in range(octave_n):
  195. if octave>0:
  196. hi = octaves[-octave]
  197. img = resize(img, hi.shape[:2])+hi
  198. for _ in range(iter_n):
  199. g = calc_grad_tiled(img, t_grad)
  200. img += g*(step / (np.abs(g).mean()+1e-7))
  201. showarray(img/255.0)
  202. # Picking some internal layer. Note that we use outputs before applying the ReLU nonlinearity
  203. # to have non-zero gradients for features with negative initial activations.
  204. layer = 'mixed4d_3x3_bottleneck_pre_relu'
  205. channel = 139 # picking some feature channel to visualize
  206. render_naive(T(layer)[:,:,:,channel])
  207. render_multiscale(T(layer)[:,:,:,channel])
  208. k = np.float32([1,4,6,4,1])
  209. k = np.outer(k, k)
  210. k5x5 = k[:,:,None,None]/k.sum()*np.eye(3, dtype=np.float32)
  211. render_lapnorm(T(layer)[:,:,:,channel])
  212. render_lapnorm(T(layer)[:,:,:,65])
  213. render_lapnorm(T('mixed3b_1x1_pre_relu')[:,:,:,101])
  214. render_lapnorm(T(layer)[:,:,:,65]+T(layer)[:,:,:,139], octave_n=4)
  215. img0 = PIL.Image.open('pilatus800.jpg')
  216. img0 = np.float32(img0)
  217. showarray(img0/255.0)
  218. render_deepdream(tf.square(T('mixed4c')), img0)
  219. render_deepdream(T(layer)[:,:,:,139], img0)
  220. if __name__ == '__main__':
  221. main()