| 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 |
|
|
| |
| 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): |
| |
| 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(): |
| |
| 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 |
|
|
| |
| 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) |
|
|