StyleCast / app.py
tejas-m's picture
Disable CSRF for HuggingFace Spaces iframe
124b96c
Raw
History Blame Contribute Delete
5.7 kB
import os
import torch
from flask import Flask, render_template, request, redirect, url_for, send_from_directory
from flask_wtf import FlaskForm
from flask_bootstrap import Bootstrap
from werkzeug.utils import secure_filename
from wtforms import FileField, SubmitField, FloatField, HiddenField
from wtforms.validators import InputRequired
from PIL import Image
from torchvision import transforms
import io
# Import your existing AdaIN code
from utils.models import VGGEncoder, Decoder
from utils.utils import adaptive_instance_normalization, calc_mean_std
app = Flask(__name__)
app.config['SECRET_KEY'] = 'supersecretkey'
app.config['WTF_CSRF_ENABLED'] = False
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg'}
Bootstrap(app)
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
class UploadForm(FlaskForm):
content = FileField('Content Image')
style = FileField('Style Image')
content_path = HiddenField()
style_path = HiddenField()
alpha = FloatField('Alpha', default=1.0)
submit = SubmitField('Transfer Style')
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
encoder = VGGEncoder('vgg_normalised.pth').to(device)
decoder = Decoder().to(device)
decoder.load_state_dict(torch.load('decoder_final.pth', map_location=device))
encoder.eval()
decoder.eval()
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
def style_transfer(content_image, style_image, encoder, decoder, alpha, device):
# Limit input size to prevent slow processing
max_size = 1024
if max(content_image.size) > max_size:
content_image.thumbnail((max_size, max_size))
if max(style_image.size) > max_size:
style_image.thumbnail((max_size, max_size))
content_transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor()
])
style_transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.ToTensor()
])
content_image = content_transform(content_image).unsqueeze(0).to(device)
style_image = style_transform(style_image).unsqueeze(0).to(device)
with torch.no_grad():
content_feats = encoder(content_image, is_test=True)
style_feats = encoder(style_image, is_test=True)
stylized_feats = adaptive_instance_normalization(content_feats, style_feats)
stylized_feats = alpha * stylized_feats + (1 - alpha) * content_feats
stylized_image = decoder(stylized_feats)
if device.type == 'cuda':
torch.cuda.empty_cache()
return stylized_image
def save_image(image, path):
image = image.cpu().clone()
image = image.squeeze(0)
image = image.clamp(0, 1)
image = transforms.ToPILImage()(image)
image.save(path)
@app.route('/', methods=['GET', 'POST'])
def index():
form = UploadForm()
result_image = None
content_filename = None
style_filename = None
error = None
if form.validate_on_submit():
# Handle content image
if form.content.data and hasattr(form.content.data, 'filename') and form.content.data.filename != '':
if allowed_file(form.content.data.filename):
content_filename = secure_filename(form.content.data.filename)
form.content.data.save(os.path.join(app.config['UPLOAD_FOLDER'], content_filename))
form.content_path.data = content_filename
else:
content_filename = form.content_path.data
# Handle style image
if form.style.data and hasattr(form.style.data, 'filename') and form.style.data.filename != '':
if allowed_file(form.style.data.filename):
style_filename = secure_filename(form.style.data.filename)
form.style.data.save(os.path.join(app.config['UPLOAD_FOLDER'], style_filename))
form.style_path.data = style_filename
else:
style_filename = form.style_path.data
if content_filename and style_filename:
content_path = os.path.join(app.config['UPLOAD_FOLDER'], content_filename)
style_path = os.path.join(app.config['UPLOAD_FOLDER'], style_filename)
try:
content_image = Image.open(content_path).convert('RGB')
style_image = Image.open(style_path).convert('RGB')
alpha = float(form.alpha.data)
stylized_image = style_transfer(content_image, style_image, encoder, decoder, alpha, device)
result_filename = 'stylized_' + content_filename
result_path = os.path.join(app.config['UPLOAD_FOLDER'], result_filename)
save_image(stylized_image, result_path)
result_image = result_filename
except Exception as e:
error = str(e)
else:
if request.method == 'POST':
if not content_filename:
error = 'Please upload content image'
if not style_filename:
error = 'Please upload style image'
return render_template('index.html', form=form, result_image=result_image, content_image=content_filename,
style_image=style_filename, error=error)
@app.route('/uploads/<filename>')
def send_image(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
@app.route('/examples/<path:filename>')
def send_example(filename):
return send_from_directory('examples', filename)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860, debug=False)