Thursday, June 10, 2021

Deep Dream

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 , -11

      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)  





Also tried on one more image https://i.imgur.com/8VcI2u0.jpg





No comments:

Post a Comment

How to check local and global angular versions

 Use the command ng version (or ng v ) to find the version of Angular CLI in the current folder. Run it outside of the Angular project, to f...