{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nimport matplotlib.pyplot as plt\nimport matplotlib\nimport numpy as np\nimport time\nfrom PIL import Image\n%matplotlib inline","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-04-01T18:52:37.578049Z","iopub.execute_input":"2023-04-01T18:52:37.578831Z","iopub.status.idle":"2023-04-01T18:52:37.586231Z","shell.execute_reply.started":"2023-04-01T18:52:37.578795Z","shell.execute_reply":"2023-04-01T18:52:37.585199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# A function to load the input images and set its dimensions to 1024 x 768\ndef load_image(image_path):\n    max_dim=512\n    img = tf.io.read_file(image_path)\n    img = tf.image.decode_image(img, channels=3)# decodes the image into a tensor\n    img = tf.image.convert_image_dtype(img, tf.float32)\n\n    shape = tf.cast(tf.shape(img)[:-1], tf.float32)\n    long_dim = max(shape)\n    scale = max_dim / long_dim\n    new_shape = tf.cast(shape * scale, tf.int32)\n\n    img = tf.image.resize(img, new_shape)\n    img = img[tf.newaxis, :]# broadcasting the image array so that it has a batch dimension\n\n    return img","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:52:48.664152Z","iopub.execute_input":"2023-04-01T18:52:48.665293Z","iopub.status.idle":"2023-04-01T18:52:48.673840Z","shell.execute_reply.started":"2023-04-01T18:52:48.665241Z","shell.execute_reply":"2023-04-01T18:52:48.672699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def imshow(image, title=None):\n    if(len(image.shape) > 3):# suppose dim is like 1,2,4,2,2,1... it removes the ones so that only 3 values remain W,H,c\n        image=np.squeeze(image, axis=0)\n    plt.imshow(image)\n    if(title):# if there's a title mention it\n        plt.title(title)","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:52:55.407977Z","iopub.execute_input":"2023-04-01T18:52:55.408684Z","iopub.status.idle":"2023-04-01T18:52:55.414591Z","shell.execute_reply.started":"2023-04-01T18:52:55.408637Z","shell.execute_reply":"2023-04-01T18:52:55.413424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's see the images\ncontent_img=load_image('/kaggle/input/images-styling/198737_127980307292279_127970727293237_189557_459726_n.jpg')\nstyle_img=load_image('/kaggle/input/stylingh/images (1).jpeg')\n\nplt.figure(figsize=(12,12))\nplt.subplot(1, 2, 1)\nimshow(content_img, 'Base Target Image')\nplt.subplot(1, 2, 2)\nimshow(style_img, 'Style image')","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:53:34.248583Z","iopub.execute_input":"2023-04-01T18:53:34.249661Z","iopub.status.idle":"2023-04-01T18:53:37.534699Z","shell.execute_reply.started":"2023-04-01T18:53:34.249589Z","shell.execute_reply":"2023-04-01T18:53:37.533696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(content_img.shape)\nprint(style_img.shape)","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:53:46.163184Z","iopub.execute_input":"2023-04-01T18:53:46.163557Z","iopub.status.idle":"2023-04-01T18:53:46.169651Z","shell.execute_reply.started":"2023-04-01T18:53:46.163524Z","shell.execute_reply":"2023-04-01T18:53:46.168476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the content image representation and load the model\nx=tf.keras.applications.vgg19.preprocess_input(content_img*255)# needs preprocessing for the model to be initialized\nx=tf.image.resize(x, (256,256))# the vgg19 model takes images in 256\nvgg_model=tf.keras.applications.VGG19(include_top=False, weights='imagenet')\nvgg_model.trainable=False\nvgg_model.summary()","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:53:47.489852Z","iopub.execute_input":"2023-04-01T18:53:47.490555Z","iopub.status.idle":"2023-04-01T18:53:48.495382Z","shell.execute_reply.started":"2023-04-01T18:53:47.490516Z","shell.execute_reply":"2023-04-01T18:53:48.494622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Chooose the content and style layers\ncontent_layers=['block4_conv2']\nstyle_layers = ['block1_conv1',\n                'block2_conv1',\n                'block3_conv1', \n                'block4_conv1', \n                'block5_conv1']","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:53:52.216680Z","iopub.execute_input":"2023-04-01T18:53:52.217670Z","iopub.status.idle":"2023-04-01T18:53:52.223025Z","shell.execute_reply.started":"2023-04-01T18:53:52.217625Z","shell.execute_reply":"2023-04-01T18:53:52.221670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Build the model\ndef my_model(layer_names):\n    # Retrieve the output layers corresponding to the content and style layers\n    vgg_model = tf.keras.applications.VGG19(include_top=False, weights='imagenet')\n    vgg_model.trainable = False\n    outputs = [vgg_model.get_layer(name).output for name in layer_names]\n    model=tf.keras.Model([vgg_model.input], outputs)\n    return model","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:53:53.976500Z","iopub.execute_input":"2023-04-01T18:53:53.977414Z","iopub.status.idle":"2023-04-01T18:53:53.984152Z","shell.execute_reply.started":"2023-04-01T18:53:53.977363Z","shell.execute_reply":"2023-04-01T18:53:53.983112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"style_extractor = my_model(style_layers)\nstyle_outputs = style_extractor(style_img*255)","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:53:59.789437Z","iopub.execute_input":"2023-04-01T18:53:59.790104Z","iopub.status.idle":"2023-04-01T18:54:04.718524Z","shell.execute_reply.started":"2023-04-01T18:53:59.790066Z","shell.execute_reply":"2023-04-01T18:54:04.717514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Compute the gram matrix\n# Einsum allows defining Tensors by defining their element-wise computation.\n# This computation is defined by equation, a shorthand form based on Einstein summation.\ndef gram_matrix(input_tensor): # input_tensor is of shape ch, n_H, n_W\n    result = tf.linalg.einsum('bijc,bijd->bcd', input_tensor, input_tensor)\n    input_shape = tf.shape(input_tensor)\n    num_locations = tf.cast(input_shape[1]*input_shape[2], tf.float32) # Unrolls n_H and n_W\n    return result/(num_locations)\n","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:06.830199Z","iopub.execute_input":"2023-04-01T18:54:06.831255Z","iopub.status.idle":"2023-04-01T18:54:06.837879Z","shell.execute_reply.started":"2023-04-01T18:54:06.831207Z","shell.execute_reply":"2023-04-01T18:54:06.836583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class entire_model(tf.keras.models.Model):\n    def __init__(self, style_layers, content_layers):\n        super(entire_model, self).__init__()\n        self.vgg=my_model(style_layers + content_layers)\n        self.style_layers=style_layers\n        self.content_layers=content_layers\n        self.num_style_layers=len(style_layers)\n        self.vgg.trainable=False\n\n    def call(self, inputs):\n        inputs=inputs*255.0 # Scale back the pixel values\n        preprocessed_input=tf.keras.applications.vgg19.preprocess_input(inputs)\n        outputs=self.vgg(preprocessed_input)# Pass the preprocessed input to my_model\n\n        # Separate the representations of style and content\n        style_outputs, content_outputs=(outputs[:self.num_style_layers], outputs[self.num_style_layers:])\n        # Calculate the gram matrix for each layer in the style output. This will be the final style representation\n        style_outputs=[gram_matrix(layer) for layer in style_outputs]\n\n        # Store the content and style representation in dictionaries in a layer by layer manner\n        content_dict = {content_name:value\n                    for content_name, value\n                    in zip(self.content_layers, content_outputs)}\n\n        style_dict = {style_name:value\n                  for style_name, value\n                  in zip(self.style_layers, style_outputs)}\n\n        return {'content': content_dict, 'style': style_dict}\n        # Returns a dict of dicts with content and style representations, i.e., gram matrix of the style_layers and\n        # the content of the content_layers","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:14.413208Z","iopub.execute_input":"2023-04-01T18:54:14.413576Z","iopub.status.idle":"2023-04-01T18:54:14.422811Z","shell.execute_reply.started":"2023-04-01T18:54:14.413543Z","shell.execute_reply":"2023-04-01T18:54:14.421686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Now we extract the style and content features by calling the above class\nextractor=entire_model(style_layers, content_layers)\nstyle_targets = extractor(style_img)['style']\ncontent_targets = extractor(content_img)['content']\n\nresults = extractor(tf.constant(content_img))","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:15.950106Z","iopub.execute_input":"2023-04-01T18:54:15.950815Z","iopub.status.idle":"2023-04-01T18:54:16.722407Z","shell.execute_reply.started":"2023-04-01T18:54:15.950778Z","shell.execute_reply":"2023-04-01T18:54:16.721381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"style_weight=40\ncontent_weight=10\n\n# Custom weights for different style layers\nstyle_weights = {'block1_conv1': 0.7,\n                 'block2_conv1': 0.19,\n                 'block3_conv1': 0.24,\n                 'block4_conv1': 0.11,\n                 'block5_conv1': 0.26}\n# style_weights = {'block1_conv1': 0.3,\n#                  'block2_conv1': 0.45,\n#                  'block3_conv1': 0.15,\n#                  'block4_conv1': 0.05,\n#                  'block5_conv1': 0.05}","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:17.430086Z","iopub.execute_input":"2023-04-01T18:54:17.430472Z","iopub.status.idle":"2023-04-01T18:54:17.435746Z","shell.execute_reply.started":"2023-04-01T18:54:17.430440Z","shell.execute_reply":"2023-04-01T18:54:17.434689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def total_cost(outputs):\n    style_outputs=outputs['style']\n    content_outputs=outputs['content']\n    style_loss=tf.add_n([style_weights[name]*tf.reduce_mean((style_outputs[name]-style_targets[name])**2)\n                        for name in style_outputs.keys()])\n    style_loss*=style_weight/len(style_layers)# Normalize\n\n    content_loss = tf.add_n([tf.reduce_mean((content_outputs[name]-content_targets[name])**2)\n                             for name in content_outputs.keys()])\n    content_loss*=content_weight/len(content_layers)\n    loss=style_loss+content_loss\n    return loss","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:18.808292Z","iopub.execute_input":"2023-04-01T18:54:18.808966Z","iopub.status.idle":"2023-04-01T18:54:18.817759Z","shell.execute_reply.started":"2023-04-01T18:54:18.808929Z","shell.execute_reply":"2023-04-01T18:54:18.814576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define a tf.Variable to contain the image to optimize\ngenerate_image = tf.Variable(content_img)\n# Since this is a float image, define a function to keep the pixel values between 0 and 1\ndef clip_0_1(image):\n    return tf.clip_by_value(image, clip_value_min=0.0, clip_value_max=1.0)","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:19.913115Z","iopub.execute_input":"2023-04-01T18:54:19.914120Z","iopub.status.idle":"2023-04-01T18:54:19.923328Z","shell.execute_reply.started":"2023-04-01T18:54:19.914070Z","shell.execute_reply":"2023-04-01T18:54:19.922234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"opt = tf.optimizers.Adam(learning_rate=0.02, beta_1=0.99, epsilon=1e-1)\n","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:20.891222Z","iopub.execute_input":"2023-04-01T18:54:20.891851Z","iopub.status.idle":"2023-04-01T18:54:20.902962Z","shell.execute_reply.started":"2023-04-01T18:54:20.891811Z","shell.execute_reply":"2023-04-01T18:54:20.901923Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@tf.function()\ndef train_step(image):\n    with tf.GradientTape() as tape:\n        outputs = extractor(image)\n        loss = total_cost(outputs)\n\n    grad = tape.gradient(loss, image)\n    opt.apply_gradients([(grad, image)])\n    image.assign(clip_0_1(image))","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:23.109116Z","iopub.execute_input":"2023-04-01T18:54:23.110075Z","iopub.status.idle":"2023-04-01T18:54:23.116471Z","shell.execute_reply.started":"2023-04-01T18:54:23.110023Z","shell.execute_reply":"2023-04-01T18:54:23.115418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_iterations=2500\nfor i in range(num_iterations):\n    train_step(generate_image)\n    if(i%500==0):\n        plt.figure(figsize=(12,12))\n        plt.subplot(1, 3, 1)\n        imshow(content_img, 'Original Image')\n        plt.subplot(1, 3, 2)\n        imshow(style_img, 'Style Image')\n        plt.subplot(1, 3, 3)\n        imshow(np.squeeze(generate_image.read_value(), 0), 'New Image - Step'+str(i))\n        ","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:54:25.943579Z","iopub.execute_input":"2023-04-01T18:54:25.943965Z","iopub.status.idle":"2023-04-01T18:56:07.245069Z","shell.execute_reply.started":"2023-04-01T18:54:25.943933Z","shell.execute_reply":"2023-04-01T18:56:07.244173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_step(generate_image)\nplt.imshow(np.squeeze(generate_image.read_value(), 0))\nplt.axis('off')\nfig1 = plt.gcf()\nfig1.savefig('new_image.png', bbox_inches='tight')","metadata":{"execution":{"iopub.status.busy":"2023-04-01T18:56:07.246929Z","iopub.execute_input":"2023-04-01T18:56:07.247571Z","iopub.status.idle":"2023-04-01T18:56:07.617487Z","shell.execute_reply.started":"2023-04-01T18:56:07.247534Z","shell.execute_reply":"2023-04-01T18:56:07.616509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}