1. Below is the code of the Deep Dream tutorial based on this.
2. It builds further upon the minimal code posted earlier.
3. The new code starts with "first octave trial"
import tensorflow as tf
from tensorflow import keras
import numpy as np
import PIL
import IPython.display as display
url = "https://storage.googleapis.com/download.tensorflow.org/example_images" +\
"/YellowLabradorLooking_new.jpg"
def download(url , max_dim = None) :
name = url.split("/")[-1]
image_file = tf.keras.utils.get_file(name , origin = url )
image = PIL.Image.open(image_file)
if max_dim :
image.thumbnail((max_dim , max_dim))
return np.array(image)
def deprocess(image) :
image = 255 * (image + 1.0 ) /2.0
image = tf.cast(image , tf.uint8)
return image
def show(image) :
display.display(PIL.Image.fromarray(np.array(image)))
original_image = download(url , max_dim = 500)
show(original_image)
display.display(display.HTML("image"))
base_model = tf.keras.applications.InceptionV3(
include_top = False ,
weights = "imagenet"
)
names = ["mixed3", "mixed5"]
layers = [base_model.get_layer(name).output for name in names]
deepdreambasemodel = tf.keras.Model(inputs = base_model.inputs,outputs = layers)
def loss_func(img , model) :
img_batch = tf.expand_dims(img , axis = 0 )
activations = model(img_batch)
if len(activations) == 1 :
activations = [activations]
losses = []
for act in activations :
loss = tf.reduce_mean(act)
losses.append(loss)
return tf.reduce_sum(losses)
class DeepDream(tf.Module ) :
def __init__ (self , model) :
self.model = model
@tf.function(
input_signature = (
tf.TensorSpec(shape=[None , None , 3], dtype = tf.float32),
tf.TensorSpec(shape=[], dtype = tf.int32),
tf.TensorSpec(shape=[], dtype = tf.float32)
)
)
def __call__(self , img , steps = 100 , step_size = 0.01) :
loss = tf.constant(0.0)
for n in range(steps) :
with tf.GradientTape() as tape :
tape.watch(img)
loss = loss_func(img , self.model)
gradient = tape.gradient(loss , img)
gradient /= tf.math.reduce_std(gradient) + 1e-8
img = img + gradient * step_size
img = tf.clip_by_value(img , -1 , 1)
return loss , img
deepdreammodel = DeepDream(deepdreambasemodel)
def run_deep_dream_simple(img , steps , step_size) :
img = tf.keras.applications.inception_v3.preprocess_input(img)
img = tf.convert_to_tensor(img)
step_size= tf.convert_to_tensor(step_size)
steps_remaining = steps
step = 0
while steps_remaining :
if steps_remaining > 100 :
run_step = tf.constant(100)
else :
run_step = tf.constant(steps_remaining)
steps_remaining -= run_step
step += run_step
loss , img = deepdreammodel(img , run_step , tf.constant(step_size))
show(deprocess(img))
show(deprocess(img))
return(deprocess(img))
run_deep_dream_simple(img = original_image , steps = 100 , step_size= 0.01)
###########################FIRST OCTAVE TRIAL##################################
import time
starttime = time.time()
img = tf.constant ( np.array(original_image))
base_shape = tf.shape(img)[:-1]
float_shape = tf.cast(base_shape , tf.float32)
OCTAVE_SCALE = 1.30
for n in range(-2,3) :
new_shape = tf.cast( float_shape * (OCTAVE_SCALE ** n), tf.int32)
img = tf.image.resize(img , new_shape).numpy()
img = run_deep_dream_simple(img , steps = 100 , step_size = 0.01)
img = tf.image.resize(img , base_shape)
img = tf.image.convert_image_dtype(img /255 , dtype = tf.uint8)
show(img)
print ("time taken {} ".format(time.time() - starttime))
################################################################################
##NOW DEEP DREAM WITH OCTAVES
#THIS ADDS ROLL FUNCTION.
#ALSO NOTICE THAT THE CLASS IS NOW LIMITED ONLY TO CALCULATE
#GRADIENTS, NEW IMAGE FORMATION USING GRADIENTS IS DONE IN run FUNCTION
def random_roll(img , maxroll):
#NOTICE minval = -maxroll ,
#NOT minval = maxroll, IT WILL GIVE YOU ERROR minval < maxval
shift = tf.random.uniform(
shape=[2] ,
minval = -maxroll ,
maxval = maxroll,
dtype = tf.int32
)
rolled_image = tf.roll(img , shift = shift , axis = [0,1])
return shift, rolled_image
shift, rolled_image = random_roll(np.array(original_image) , maxroll = 512)
show(rolled_image)
class TiledGradient(tf.Module) :
def __init__ ( self , model) :
self.model = model
@tf.function(
input_signature = (
tf.TensorSpec(shape=[None,None , 3] , dtype = tf.float32),
tf.TensorSpec(shape=[] , dtype = tf.int32)
)
)
def __call__(self , img , tile_size = 512) :
shift , rolled_img = random_roll(img , 512)
gradients = tf.zeros_like(rolled_img)
xs = tf.range(0 , rolled_img.shape[0] , tile_size)[:-1]
if not tf.cast(len(xs) , tf.bool) :
xs = tf.constant([0])
ys = tf.range(0 , rolled_img.shape[1] , tile_size) [:-1]
if not tf.cast(len(ys) , tf.bool) :
ys = tf.constant([0])
for x in xs :
for y in ys:
with tf.GradientTape() as tape :
tape.watch(rolled_img)
loss = loss_func(rolled_img[x:x+tile_size,y:y+tile_size],self.model)
gradients = gradients + tape.gradient(loss , rolled_img)
#NOTICE THE -shift BELOW shift = - shift. ####
gradients = tf.roll(gradients,shift = -shift , axis = [0,1])
gradients /= tf.math.reduce_std(gradients) + 1e-8
return gradients
get_tiled_gradients = TiledGradient(deepdreambasemodel)
def run_deep_dream_with_octaves(img,steps_per_octave = 100 , step_size = 0.01 ,
octaves = range(-2,3),
octave_scale = 1.30) :
base_shape = tf.shape(img)
img = tf.keras.preprocessing.image.img_to_array(img)
img = tf.keras.applications.inception_v3.preprocess_input(img)
initial_shape = img.shape[:-1]
img = tf.image.resize(img , initial_shape)
for octave in octaves :
new_shape = (tf.cast(tf.convert_to_tensor(base_shape[:-1]) , tf.float32)) \
*(octave_scale ** octave)
img = tf.image.resize(img, tf.cast(new_shape , tf.int32))
for step in range(steps_per_octave) :
gradient = get_tiled_gradients(img)
img = img + gradient * step_size
img = tf.clip_by_value(img , -1, 1)
if step % 10 == 0:
show(deprocess(img))
print ("Octave {}, Step {}".format(octave, step))
return deprocess(img)
img = run_deep_dream_with_octaves(img=original_image, step_size=0.01)
img = tf.image.resize(img, base_shape)
img = tf.image.convert_image_dtype(img/255.0, dtype=tf.uint8)
show(img)
No comments:
Post a Comment