Spaces:
Sleeping
Sleeping
Upload 10 files
Browse files- .gitattributes +4 -0
- app.py +220 -0
- content/images/content1.jpg +3 -0
- content/images/content2.jpg +3 -0
- content/images/content3.jpg +3 -0
- content/styles/style1.jpg +0 -0
- content/styles/style2.jpg +0 -0
- content/styles/style3.jpg +3 -0
- notebook/final_styled_image1.jpg +0 -0
- notebook/neural_style_transfer.ipynb +0 -0
- requirements.txt +5 -0
.gitattributes
CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
content/images/content1.jpg filter=lfs diff=lfs merge=lfs -text
|
37 |
+
content/images/content2.jpg filter=lfs diff=lfs merge=lfs -text
|
38 |
+
content/images/content3.jpg filter=lfs diff=lfs merge=lfs -text
|
39 |
+
content/styles/style3.jpg filter=lfs diff=lfs merge=lfs -text
|
app.py
ADDED
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import tensorflow as tf
|
3 |
+
import numpy as np
|
4 |
+
from PIL import Image
|
5 |
+
|
6 |
+
from tensorflow.keras.applications.vgg19 import VGG19, preprocess_input
|
7 |
+
from tensorflow.keras.preprocessing.image import img_to_array
|
8 |
+
from tensorflow.keras.models import Model
|
9 |
+
|
10 |
+
# Load VGG19 model
|
11 |
+
model = VGG19(include_top=False, weights='imagenet')
|
12 |
+
model.trainable = False
|
13 |
+
|
14 |
+
# Define content and style layers
|
15 |
+
content_layer = 'block5_conv2'
|
16 |
+
content_model = Model(inputs=model.input,
|
17 |
+
outputs=model.get_layer(content_layer).output)
|
18 |
+
|
19 |
+
style_layers = ['block1_conv1', 'block3_conv1', 'block5_conv1']
|
20 |
+
style_models = [Model(inputs=model.input, outputs=model.get_layer(
|
21 |
+
layer).output) for layer in style_layers]
|
22 |
+
weight_of_layer = 1. / len(style_models)
|
23 |
+
|
24 |
+
|
25 |
+
def process_image(img):
|
26 |
+
# Convert to array and preprocess
|
27 |
+
img = img_to_array(img)
|
28 |
+
img = preprocess_input(img)
|
29 |
+
img = np.expand_dims(img, axis=0)
|
30 |
+
return img
|
31 |
+
|
32 |
+
|
33 |
+
def deprocess(img):
|
34 |
+
# Perform the inverse of the preprocessing step
|
35 |
+
img = img.copy() # Create a copy to avoid modifying the original
|
36 |
+
img[:, :, 0] += 103.939
|
37 |
+
img[:, :, 1] += 116.779
|
38 |
+
img[:, :, 2] += 123.68
|
39 |
+
# Convert BGR to RGB
|
40 |
+
img = img[:, :, ::-1]
|
41 |
+
img = np.clip(img, 0, 255).astype('uint8')
|
42 |
+
return img
|
43 |
+
|
44 |
+
# Gram matrix
|
45 |
+
def gram_matrix(A):
|
46 |
+
channels = int(A.shape[-1])
|
47 |
+
a = tf.reshape(A, [-1, channels])
|
48 |
+
n = tf.shape(a)[0]
|
49 |
+
gram = tf.matmul(a, a, transpose_a=True)
|
50 |
+
return gram / tf.cast(n, tf.float32)
|
51 |
+
|
52 |
+
# Content loss
|
53 |
+
def content_loss(content, generated):
|
54 |
+
a_C = content_model(content)
|
55 |
+
a_G = content_model(generated)
|
56 |
+
loss = tf.reduce_mean(tf.square(a_C - a_G))
|
57 |
+
return loss
|
58 |
+
|
59 |
+
# Style loss
|
60 |
+
def style_cost(style, generated):
|
61 |
+
J_style = 0
|
62 |
+
for style_model in style_models:
|
63 |
+
a_S = style_model(style)
|
64 |
+
a_G = style_model(generated)
|
65 |
+
GS = gram_matrix(a_S)
|
66 |
+
GG = gram_matrix(a_G)
|
67 |
+
current_cost = tf.reduce_mean(tf.square(GS - GG))
|
68 |
+
J_style += current_cost * weight_of_layer
|
69 |
+
return J_style
|
70 |
+
|
71 |
+
# Total Loss Function
|
72 |
+
def compute_total_loss(content, style, generated, alpha=10, beta=1000):
|
73 |
+
J_content = content_loss(content, generated)
|
74 |
+
J_style = style_cost(style, generated)
|
75 |
+
return alpha * J_content + beta * J_style
|
76 |
+
|
77 |
+
|
78 |
+
def ensure_pil_image(img):
|
79 |
+
if isinstance(img, np.ndarray):
|
80 |
+
return Image.fromarray(img.astype('uint8'))
|
81 |
+
return img
|
82 |
+
|
83 |
+
|
84 |
+
def neural_style_transfer(content_img, style_img, iterations=50, alpha=10, beta=1000):
|
85 |
+
try:
|
86 |
+
# Ensure we have PIL images
|
87 |
+
content_img_pil = ensure_pil_image(content_img)
|
88 |
+
style_img_pil = ensure_pil_image(style_img)
|
89 |
+
|
90 |
+
# Resize images to a manageable size
|
91 |
+
content_img_pil = content_img_pil.resize((300, 300), Image.LANCZOS)
|
92 |
+
style_img_pil = style_img_pil.resize((300, 300), Image.LANCZOS)
|
93 |
+
|
94 |
+
# Process images
|
95 |
+
content = process_image(content_img_pil)
|
96 |
+
style = process_image(style_img_pil)
|
97 |
+
|
98 |
+
# Initialize with content image
|
99 |
+
generated = tf.Variable(content, dtype=tf.float32)
|
100 |
+
|
101 |
+
# Optimizer
|
102 |
+
opt = tf.keras.optimizers.Adam(learning_rate=0.7)
|
103 |
+
|
104 |
+
progress_images = []
|
105 |
+
|
106 |
+
for i in range(iterations):
|
107 |
+
with tf.GradientTape() as tape:
|
108 |
+
total_loss = compute_total_loss(
|
109 |
+
content, style, generated, alpha, beta)
|
110 |
+
|
111 |
+
# Get gradients and apply
|
112 |
+
grads = tape.gradient(total_loss, generated)
|
113 |
+
opt.apply_gradients([(grads, generated)])
|
114 |
+
|
115 |
+
if i % 10 == 0 or i == iterations - 1:
|
116 |
+
# Save progress image
|
117 |
+
current_img = generated.numpy()
|
118 |
+
img_squeezed = np.squeeze(current_img, axis=0)
|
119 |
+
img_deprocessed = deprocess(img_squeezed)
|
120 |
+
progress_images.append(Image.fromarray(img_deprocessed))
|
121 |
+
|
122 |
+
print(f"Iteration {i}, Loss: {total_loss.numpy()}")
|
123 |
+
|
124 |
+
# Get final image
|
125 |
+
final_img = generated.numpy()
|
126 |
+
final_img = np.squeeze(final_img, axis=0)
|
127 |
+
final_img = deprocess(final_img)
|
128 |
+
|
129 |
+
return Image.fromarray(final_img), progress_images
|
130 |
+
except Exception as e:
|
131 |
+
print(f"Error in neural_style_transfer: {e}")
|
132 |
+
# Return a default error image
|
133 |
+
error_img = Image.new('RGB', (300, 300), color='red')
|
134 |
+
return error_img, []
|
135 |
+
|
136 |
+
|
137 |
+
def style_transfer_interface(content_img, style_img, iterations=50, content_weight=10, style_weight=1000):
|
138 |
+
# Check if images are provided
|
139 |
+
if content_img is None or style_img is None:
|
140 |
+
return None
|
141 |
+
|
142 |
+
# Perform style transfer
|
143 |
+
result_img, _ = neural_style_transfer(
|
144 |
+
content_img,
|
145 |
+
style_img,
|
146 |
+
iterations=iterations,
|
147 |
+
alpha=content_weight,
|
148 |
+
beta=style_weight
|
149 |
+
)
|
150 |
+
|
151 |
+
return result_img
|
152 |
+
|
153 |
+
|
154 |
+
# Example images
|
155 |
+
content_path = "content/images/content"
|
156 |
+
style_path = "content/styles/style"
|
157 |
+
|
158 |
+
example_content_1 = f"{content_path}1.jpg"
|
159 |
+
example_content_2 = f"{content_path}2.jpg"
|
160 |
+
example_content_3 = f"{content_path}3.jpg"
|
161 |
+
example_style_1 = f"{style_path}1.jpg"
|
162 |
+
example_style_2 = f"{style_path}2.jpg"
|
163 |
+
example_style_3 = f"{style_path}3.jpg"
|
164 |
+
|
165 |
+
examples = [
|
166 |
+
[example_content_1, example_style_1, 10, 5, 1000],
|
167 |
+
[example_content_2, example_style_2, 20, 10, 1500],
|
168 |
+
[example_content_3, example_style_3, 50, 15, 2000],
|
169 |
+
]
|
170 |
+
|
171 |
+
with gr.Blocks(title="Neural Style Transfer") as app:
|
172 |
+
gr.Markdown("# Neural Style Transfer App")
|
173 |
+
gr.Markdown(
|
174 |
+
"Upload a content image and a style image to generate a stylized result")
|
175 |
+
|
176 |
+
with gr.Row():
|
177 |
+
with gr.Column():
|
178 |
+
content_input = gr.Image(label="Content Image", type="pil")
|
179 |
+
style_input = gr.Image(label="Style Image", type="pil")
|
180 |
+
|
181 |
+
with gr.Row():
|
182 |
+
iterations_slider = gr.Slider(
|
183 |
+
minimum=10, maximum=100, value=50, step=10,
|
184 |
+
label="Iterations"
|
185 |
+
)
|
186 |
+
|
187 |
+
with gr.Row():
|
188 |
+
content_weight_slider = gr.Slider(
|
189 |
+
minimum=1, maximum=20, value=10, step=1,
|
190 |
+
label="Content Weight"
|
191 |
+
)
|
192 |
+
style_weight_slider = gr.Slider(
|
193 |
+
minimum=500, maximum=2000, value=1000, step=100,
|
194 |
+
label="Style Weight"
|
195 |
+
)
|
196 |
+
|
197 |
+
submit_btn = gr.Button("Generate Stylized Image")
|
198 |
+
|
199 |
+
with gr.Column():
|
200 |
+
output_image = gr.Image(label="Stylized Result")
|
201 |
+
|
202 |
+
gr.Examples(
|
203 |
+
examples=examples,
|
204 |
+
inputs=[content_input, style_input, iterations_slider,
|
205 |
+
content_weight_slider, style_weight_slider],
|
206 |
+
outputs=output_image,
|
207 |
+
fn=style_transfer_interface,
|
208 |
+
cache_examples=False,
|
209 |
+
)
|
210 |
+
|
211 |
+
submit_btn.click(
|
212 |
+
fn=style_transfer_interface,
|
213 |
+
inputs=[content_input, style_input, iterations_slider,
|
214 |
+
content_weight_slider, style_weight_slider],
|
215 |
+
outputs=output_image
|
216 |
+
)
|
217 |
+
|
218 |
+
# Launch the app
|
219 |
+
if __name__ == "__main__":
|
220 |
+
app.launch(share=True, debug=True)
|
content/images/content1.jpg
ADDED
![]() |
Git LFS Details
|
content/images/content2.jpg
ADDED
![]() |
Git LFS Details
|
content/images/content3.jpg
ADDED
![]() |
Git LFS Details
|
content/styles/style1.jpg
ADDED
![]() |
content/styles/style2.jpg
ADDED
![]() |
content/styles/style3.jpg
ADDED
![]() |
Git LFS Details
|
notebook/final_styled_image1.jpg
ADDED
![]() |
notebook/neural_style_transfer.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
tensorflow
|
2 |
+
numpy
|
3 |
+
matplotlib
|
4 |
+
pillow
|
5 |
+
gradio
|