LuisDarioHinojosa commited on
Commit
5fe4fb2
·
1 Parent(s): 4a2c19b

initial commit

Browse files
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: Neural Style Transfer Demo
3
- emoji: 📊
4
  colorFrom: purple
5
  colorTo: red
6
  sdk: gradio
 
1
  ---
2
  title: Neural Style Transfer Demo
3
+ emoji: 🎨
4
  colorFrom: purple
5
  colorTo: red
6
  sdk: gradio
app.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import tensorflow as tf
4
+ import gradio as gr
5
+ import random
6
+ from PIL import Image
7
+ from tensorflow.keras.preprocessing.image import load_img,img_to_array
8
+ from tensorflow.keras.optimizers import SGD
9
+ from tensorflow.keras.optimizers.schedules import ExponentialDecay
10
+ # change in the actual written file
11
+ from modules.nst_loss_functions import *
12
+ from modules.nst_models import *
13
+ from modules.preprocessing_utils import *
14
+
15
+
16
+ # get the weights
17
+ content_weight,style_weight = get_weights()
18
+ # get the content and style layer lists
19
+ content_layer,style_layers = get_layers_lists()
20
+ # instance the pretrained model
21
+ pretrained_vgg_model,feature_extractor = get_pretrained_vgg_model_fe()
22
+
23
+ # training function
24
+ @tf.function
25
+ def compute_loss_and_grads(generated_image,
26
+ base_image,
27
+ style_image,
28
+ row_cols):
29
+
30
+ with tf.GradientTape() as tape:
31
+ loss = loss_function(generated_image = generated_image,
32
+ base_image = base_image,
33
+ style_image = style_image,
34
+ content_layer = content_layer,
35
+ style_layers = style_layers,
36
+ feature_extractor = feature_extractor,
37
+ weights= (content_weight,style_weight),
38
+ rows_cols = row_cols)
39
+
40
+ grads = tape.gradient(loss, generated_image)
41
+ return loss, grads
42
+
43
+
44
+ # generate image
45
+ def generate(base_image,style_image,epochs,progress=gr.Progress()):
46
+ # instance images
47
+ base_pil_image = base_image
48
+ style_pil_image = style_image
49
+ generated_pil_image = base_pil_image.copy()
50
+
51
+ # determine the base image's dimentions
52
+ width, height = base_pil_image.size
53
+ img_nrows = 400
54
+ img_ncols = int(width * img_nrows / height)
55
+
56
+ # instance the optimizer
57
+ optimizer = SGD(
58
+ ExponentialDecay(
59
+ initial_learning_rate=100.0, decay_steps=100, decay_rate=0.96
60
+ )
61
+ )
62
+
63
+ # preprocess the images
64
+ base_image = preprocess_image(base_pil_image,(img_nrows,img_ncols))
65
+ style_image = preprocess_image(style_pil_image,(img_nrows,img_ncols))
66
+ generated_image = tf.Variable(preprocess_image(generated_pil_image,(img_nrows,img_ncols)))
67
+
68
+ for i in progress.tqdm(range(int(epochs))):
69
+ loss, grads = compute_loss_and_grads(
70
+ generated_image, base_image, style_image,(img_nrows,img_ncols)
71
+ )
72
+ optimizer.apply_gradients([(grads, generated_image)])
73
+
74
+ generated_image = generated_image.numpy()
75
+ generated_image = deprocess_image(generated_image,(img_nrows,img_ncols))
76
+
77
+ return generated_image
78
+
79
+ title = "Neural Style Transfer Demo"
80
+ description = "This is my implementation of the neural style transfer algorithm using Tensorflow2"
81
+ article = "The NST algorithm is an algorithm that allows you to replicate an image A with similar features to the ones present in an image B. In a nutshell, this is done by using a pretrained CNN to perform gradient descent on the weighted cost of a style and content cost function, which correspond to the frobenius norm across the features’ cross covariance across different layers and the simple norm respectively. The result of the loss is applied to a random generated image to get the hybrid. To use this app, select a real photo as a content image and an art piece as style image from an URL or from your PC, set the number of epochs (it is recommended to leave the default value), and run the app. THIS MAY TAKE SOME TIME, PLEASE BE PATIENT (╯°□°)╯."
82
+
83
+
84
+
85
+ example_list = list()
86
+ # change in the app
87
+ examples_path = "examples"
88
+ content_examples_path = os.path.join(examples_path,"content")
89
+ style_examples_path = os.path.join(examples_path,"style")
90
+
91
+ content_examples = [[str(content_examples_path) + "/" + example] for example in os.listdir(content_examples_path)]
92
+ style_examples = [[str(style_examples_path) + "/" + example] for example in os.listdir(style_examples_path)]
93
+
94
+
95
+ img_input_1 = gr.Image(label = "Content Image",type = "pil",value = random.choice(content_examples)[0])
96
+ img_input_2 = gr.Image(label = "Style Image",type = "pil",value = random.choice(style_examples)[0])
97
+
98
+ demo = gr.Interface(
99
+ fn = generate,
100
+ inputs = [img_input_1,img_input_2,gr.Number(value = 250,label = "Number of epochs",)],
101
+ outputs = [gr.Image(type = "pil")],
102
+ title = title,
103
+ description = description,
104
+ article = article
105
+ )
106
+
107
+ demo.queue().launch()
examples/content/P1011143.jpg ADDED
examples/content/SECRETOS-CATEDRAL-METROPOLITANA-CDMX-2.jpg ADDED
examples/content/_129303416_gettyimages-992816562-1.jpg ADDED
examples/content/b23764853d02ad4c25e0780c2cd6aa52--volcano-los.jpg ADDED
examples/content/f.elconfidencial.com_original_dae_7b7_861_dae7b7861c3285b03b9f6555878c8c53.jpg ADDED
examples/style/1200px-The_Fighting_Temeraire,_JMW_Turner,_National_Gallery.jpg ADDED
examples/style/Giotto-Di-Bondone-The-Ascension.jpg ADDED
examples/style/fenmeno-de-ingravidez.jpg ADDED
examples/style/ou_nous_allons.jpg ADDED
examples/style/starry-night-over-the-rhone-5.jpg ADDED
modules/nst_loss_functions.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import tensorflow as tf
3
+
4
+ # compute the gram matrix of the features
5
+ def gram_matrix(x):
6
+ #x = tf.convert_to_tensor(x, tf.int32)
7
+ x = tf.transpose(x,perm = (2,0,1))
8
+ features = tf.reshape(x,(tf.shape(x)[0],-1))
9
+ gram = tf.matmul(features,tf.transpose(features))
10
+ return gram
11
+
12
+ # compute the style cost function
13
+ def style_cost_function(style_image,generated_image,rows_cols):
14
+ img_nrows,img_ncols = rows_cols
15
+ S = gram_matrix(style_image)
16
+ C = gram_matrix(generated_image)
17
+ channels = 3
18
+ size = img_nrows * img_ncols
19
+ return tf.reduce_sum(tf.square(S - C)) / (4.0 * (channels ** 2) * (size ** 2))
20
+
21
+ # compute the content cost function
22
+ def content_cost_function(base_image,generated_image):
23
+ return tf.reduce_sum(tf.square(tf.subtract(generated_image,base_image)))
24
+
25
+ def loss_function(
26
+ generated_image,
27
+ base_image,
28
+ style_image,
29
+ content_layer,
30
+ style_layers,
31
+ feature_extractor,
32
+ weights,
33
+ rows_cols):
34
+
35
+ # fetch the weights
36
+ content_weight,style_weight = weights
37
+
38
+ # combine the images into a single tensor
39
+ input_tensor = tf.concat(
40
+ [base_image, style_image, generated_image], axis=0
41
+ )
42
+
43
+ # get the values in all the layers for the three images
44
+ features = feature_extractor(input_tensor)
45
+
46
+ # iinitialize the loss function
47
+ loss = tf.zeros(shape=())
48
+
49
+ # compute the content loss
50
+ layer_features = features[content_layer]
51
+ base_image_features = layer_features[0, :, :, :]
52
+ combination_features = layer_features[2, :, :, :]
53
+
54
+ loss = loss + content_weight * content_cost_function(
55
+ base_image_features, combination_features
56
+ )
57
+
58
+ # compute the style loss
59
+ for layer_name in style_layers:
60
+ layer_features = features[layer_name]
61
+ style_reference_features = layer_features[1, :, :, :]
62
+ combination_features = layer_features[2, :, :, :]
63
+ sl = style_cost_function(style_reference_features, combination_features,rows_cols)
64
+ loss += (style_weight / len(style_layers)) * sl
65
+
66
+ return loss
67
+
68
+
modules/nst_models.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from tensorflow.keras.models import Model
2
+ from tensorflow.keras.applications import VGG19
3
+
4
+ # instances a pretrained vgg19 model and creates the feature extractor
5
+ def get_pretrained_vgg_model_fe():
6
+ # instance the pretrained model
7
+ pretrained_vgg_model = VGG19(include_top = False, weights="imagenet")
8
+ # create a dictionary that maps the layers name to each feature extractor
9
+ model_outputs = {layer.name : layer.output for layer in pretrained_vgg_model.layers}
10
+ # feature extractor
11
+ feature_extractor = Model(inputs=pretrained_vgg_model.inputs, outputs=model_outputs)
12
+ return pretrained_vgg_model,feature_extractor
13
+
14
+ # get a list of the layers that will be used to style and content
15
+ def get_layers_lists():
16
+ # define the style layers
17
+ style_layers = [
18
+ "block1_conv1",
19
+ "block2_conv1",
20
+ "block3_conv1",
21
+ "block4_conv1",
22
+ "block5_conv1",
23
+ ]
24
+ # define the content layer
25
+ content_layer = "block5_conv2"
26
+ return content_layer,style_layers
27
+
28
+ # get the weights for each of the cost functions in order to computer the final cost
29
+ def get_weights():
30
+ # define the style and content weights
31
+ content_weight = 2.5e-8
32
+ style_weight = 1.0e-6
33
+ return content_weight,style_weight
modules/preprocessing_utils.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import tensorflow as tf
3
+ from tensorflow.keras.applications.vgg19 import preprocess_input
4
+ from tensorflow.keras.preprocessing.image import img_to_array
5
+
6
+ def preprocess_image(img,rows_cols):
7
+ img_nrows, img_ncols = rows_cols
8
+ # load the image into a tensot
9
+ img = img.resize((img_ncols,img_nrows))
10
+ # turn the image into a numpy array
11
+ img = img_to_array(img)
12
+ # add a batch dimention
13
+ img = np.expand_dims(img, axis=0)
14
+ # preprocess according to the vgg model's specification
15
+ img = preprocess_input(img)
16
+ return tf.convert_to_tensor(img)
17
+
18
+
19
+ def deprocess_image(x,rows_cols):
20
+ img_nrows, img_ncols = rows_cols
21
+ # Cconert to array
22
+ x = x.reshape((img_nrows, img_ncols, 3))
23
+ # mean = 0
24
+ x[:, :, 0] += 103.939
25
+ x[:, :, 1] += 116.779
26
+ x[:, :, 2] += 123.68
27
+ # convert to rgb
28
+ x = x[:, :, ::-1]
29
+ # normalize
30
+ x = np.clip(x, 0, 255).astype("uint8")
31
+ return x
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ tensorflow==2.12.0
2
+ gradio==3.34.0
3
+ numpy==1.22.4
4
+ Pillow==8.4.0