Spaces:
Sleeping
title: StyleXfer - Adaptive Neural Style Transfer
emoji: π¨
colorFrom: indigo
colorTo: purple
sdk: docker
sdk_version: 0.0.1
app_file: StyleXfer_NST_code/app.py
pinned: false
python_version: '3.12'
tags:
- neural-style-transfer
- computer-vision
- deep-learning
- huggingface-spaces
StyleXfer: Adaptive Neural Style Transfer
StyleXfer is a Flask-based web application for Adaptive Neural Style Transfer using AdaIN. It lets a user upload a content image and a style image, choose the style strength, and generate a new image that preserves the structure of the content image while adopting the color, texture, and artistic statistics of the style image.
The project combines a pretrained VGG encoder, a trained decoder network, PyTorch image processing, and a responsive Bootstrap/Jinja web interface. It also includes the training script used to train the decoder and sample content/style/example images for demonstration.
π Live Demo
Try StyleXfer Online: https://arpit16112-stylexfer.hf.space/
The application is deployed on Hugging Face Spaces using Docker. Upload your images and generate stylized outputs instantly!
Overview
StyleXfer provides an end-to-end neural style transfer workflow:
- upload a content image that provides the subject and structure
- upload a style image that provides artistic texture and color statistics
- control the transfer strength with an
alphaslider - run AdaIN-based inference through a Flask backend
- preview uploaded images before submission
- view and download the stylized output
- browse static examples inside the web app
The application is useful as:
- a computer vision portfolio project
- a practical implementation of AdaIN neural style transfer
- a Flask plus PyTorch deployment example
- a training and inference pipeline for encoder-decoder image generation
AdaIN Architecture
Adaptive Instance Normalization transfers style by aligning channel-wise feature statistics between content and style representations.
Example Images
The app includes example files in StyleXfer_NST_code/examples/ that are served through the Flask route:
@app.route('/examples/<path:filename>')
def send_example(filename):
return send_from_directory('examples', filename)
Note: The example images displayed on the home page are sourced from a Hugging Face dataset repository where they have been uploaded for easy access and demonstration purposes.
brad_pitt.jpgas a sample content imagesketch.pngas a sample sketch stylepicasso_seated_nude_hr.jpgas a sample painting style- Generated stylized outputs
Why This Project
Traditional neural style transfer methods can be slow because they optimize a generated image for every new content-style pair. AdaIN makes style transfer much faster by directly aligning feature statistics between content and style representations.
StyleXfer demonstrates this idea in a usable web app:
- VGG extracts visual feature representations
- AdaIN transfers style by matching mean and standard deviation
- the decoder reconstructs a final RGB image
- Flask provides an interactive interface for non-technical users
Problem Statement
Artists, learners, and computer vision developers often need a simple way to experiment with neural style transfer without running notebooks or command-line scripts every time.
StyleXfer solves this by providing:
- a browser-based upload workflow
- an adjustable style strength control
- trained model inference through Flask
- reusable model and utility code
- a separate training script for improving or retraining the decoder
What The Project Does
The application supports:
- content & style image upload
- file validation for
png,jpg, andjpeg - AdaIN feature transformation
- trained decoder-based image generation
- output saving into the upload folder
- result display inside the web page
- result download
- static example gallery
- loading configuration from
.env - local development server through Flask/Werkzeug
- production deployment through Docker on Hugging Face Spaces
Key Features
- Flask web app with Jinja templates
- Bootstrap-based responsive UI
- Flask-WTF form handling with CSRF support
- PyTorch VGG encoder for feature extraction
- custom decoder network for image reconstruction
- Adaptive Instance Normalization implementation
- style strength control through
alpha
Tech Stack
- Python
- Flask
- Jinja2
- Bootstrap
- Flask-WTF
- WTForms
- Flask-Bootstrap
- PyTorch
- Torchvision
- Pillow
- NumPy
- tqdm
- python-dotenv
Project Structure
StyleXfer/
|-- README.md
|-- requirements.txt
|-- Dockerfile
|-- .gitignore
|-- .env (optional for local development)
|-- assets/
| |-- home.png
| |-- examples.png
| |-- stylized_image.png
|-- StyleXfer_NST_code/
| |-- app.py # Flask web app (main entry point)
| |-- train.py # Training script for decoder
| |-- vgg_normalised.pth # Pretrained VGG encoder weights
| |-- adain_algorithm.png # AdaIN algorithm visualization
| |-- templates/
| | |-- index.html # Web interface (HTML, CSS, JS)
| |-- utils/
| | |-- models.py # VGG encoder and decoder architectures
| | |-- utils.py # AdaIN, dataset loaders, utility functions
| |-- static/
| | |-- uploads/ # User uploads and generated outputs
| |-- examples/ # Static example images
| |-- experiment/
| | |-- experiment1/ # First training run checkpoints
| | |-- experiment2/ # Second training run checkpoints
| | |-- final_training/ # Final production model
| | |-- decoder_final.pth # Final trained decoder
| | |-- args.txt # Training configuration
| |-- content_data_examples/ # Example content images
| |-- style_data_examples/ # Example style images
| |-- content_dataset/ # Training content dataset
| |-- style_dataset/ # Training style dataset
Important Files
| File/Folder | Purpose |
|---|---|
Dockerfile |
Container configuration for Hugging Face Spaces deployment |
README.md |
Project documentation and deployment guide |
requirements.txt |
Python dependencies (Flask, PyTorch, Pillow, etc.) |
assets/ |
Demo screenshots (home.png, examples.png, stylized_image.png) |
StyleXfer_NST_code/app.py |
Flask web application - main entry point, routes, and inference |
StyleXfer_NST_code/train.py |
Training script for the AdaIN decoder network |
StyleXfer_NST_code/templates/index.html |
Web interface with upload form, image previews, and output display |
StyleXfer_NST_code/utils/models.py |
VGG encoder and decoder neural network architectures |
StyleXfer_NST_code/utils/utils.py |
AdaIN implementation, dataset loaders, and utility functions |
StyleXfer_NST_code/vgg_normalised.pth |
Pretrained VGG-19 encoder weights (frozen during inference) |
StyleXfer_NST_code/experiment/final_training/decoder_final.pth |
Trained decoder model used for style transfer inference |
StyleXfer_NST_code/experiment/final_training/args.txt |
Training configuration and hyperparameters for final model |
StyleXfer_NST_code/examples/ |
Static example images for demonstration |
StyleXfer_NST_code/static/uploads/ |
Runtime directory for user uploads and generated outputs |
.env |
Local environment variables (not pushed to repository) |
How It Works
- The user opens the Flask web app.
- The user uploads a content image and a style image.
- The browser previews both selected images with JavaScript.
- Flask validates the file extensions and saves files into
static/uploads/. - Pillow opens both files and converts them to RGB.
- Torchvision resizes each image and converts it to tensors.
- The VGG encoder extracts content and style feature maps.
- AdaIN normalizes content features and applies style feature statistics.
- The
alphavalue blends stylized features with original content features. - The trained decoder reconstructs the stylized RGB image.
- The output image is saved as
stylized_<content_filename>. - The result appears in the web page with a download button.
AdaIN Pipeline
Adaptive Instance Normalization transfers style by aligning channel-wise feature statistics.
At a high level:
- extract content features from the content image
- extract style features from the style image
- calculate per-channel mean and standard deviation for both
- normalize content features
- rescale normalized content features with style statistics
- decode the transformed feature map into an image
The core function is implemented in StyleXfer_NST_code/utils/utils.py:
def adaptive_instance_normalization(content_feat, style_feat):
size = content_feat.size()
style_mean, style_std = calc_mean_std(style_feat)
content_mean, content_std = calc_mean_std(content_feat)
normalized_content_feat = (content_feat - content_mean.expand(size)) / content_std.expand(size)
return normalized_content_feat * style_std.expand(size) + style_mean.expand(size)
Model Architecture
VGG Encoder
The encoder is a pretrained VGG-style network loaded from vgg_normalised.pth.
It is used only for feature extraction:
- encoder parameters are frozen
- features are extracted up to
relu4_1 - shallow layers help measure style
- deeper features preserve content structure
During training, the encoder returns multiple feature maps:
h1h2h3h4
During inference, the app uses the deepest feature map for AdaIN transformation.
Decoder
The decoder is a trainable network that reconstructs an RGB image from AdaIN-transformed features.
It uses:
- reflection padding
- convolution layers
- ReLU activations
- nearest-neighbor upsampling
The trained inference checkpoint is:
StyleXfer_NST_code/experiment/final_training/decoder_final.pth
Training Pipeline
The training workflow is implemented in StyleXfer_NST_code/train.py.
At a high level, training performs:
- parse command-line arguments
- load content and style image datasets
- create PyTorch dataloaders
- load pretrained VGG encoder
- initialize decoder
- optionally resume from saved decoder and optimizer checkpoints
- extract content and style features
- apply AdaIN to create target features
- decode generated image
- calculate content loss
- calculate style loss using feature mean and standard deviation
- update decoder weights with Adam
- save decoder checkpoints, optimizer checkpoints, and output grids
Losses
The training script uses:
- content loss between generated features and AdaIN target features
- style loss between generated and style feature statistics
- weighted total loss:
total_loss = content_loss * content_weight + style_loss * style_weight
Final Training Configuration
The saved final training arguments are stored in:
StyleXfer_NST_code/experiment/final_training/args.txt
The final recorded configuration includes:
| Setting | Value |
|---|---|
| Content dataset | ./content_dataset |
| Style dataset | ./style_dataset |
| VGG weights | vgg_normalised.pth |
| Experiment | final_training |
| Final image size | 512 |
| Content size | 512 |
| Style size | 512 |
| Batch size | 8 |
| Epochs | 200 |
| Learning rate | 0.0001 |
| LR decay | 0.00005 |
| Content weight | 1.0 |
| Style weight | 10 |
| Resume training | True |
| Save interval | 20 |
Training Commands
Basic Training
From inside StyleXfer_NST_code/:
python train.py --batch_size 16 --epochs 160 --experiment final_training
Resume Training
python train.py
--batch_size 8
--epochs 200
--experiment final_training
--final_size 512
--style_weight 10
--resume
--decoder_path experiment/final_training/decoder_160.pth
--optimizer_path experiment/final_training/optimizer_160.pth
Setup Instructions
1. Clone The Repository
git clone https://github.com/your-username/StyleXfer.git
cd StyleXfer
2. Create A Virtual Environment
On Windows:
python -m venv venv
venv\Scripts\activate
On Linux or macOS:
python3 -m venv venv
source venv/bin/activate
3. Install Dependencies
pip install -r requirements.txt
4. Create .env
Create a .env file in the project root:
SECRET_KEY=your-secret-key
UPLOAD_FOLDER=static/uploads
FLASK_HOST=localhost
FLASK_PORT=5000
Notes:
SECRET_KEYis used by Flask-WTF for CSRF/session protection.UPLOAD_FOLDERdefaults tostatic/uploadsif not provided.FLASK_HOSTandFLASK_PORTare used when runningpython app.py.- Do not commit
.envto GitHub.
5. Confirm Required Model Files
The Flask app expects these files to exist:
StyleXfer_NST_code/vgg_normalised.pth
StyleXfer_NST_code/experiment/final_training/decoder_final.pth
Without these files, inference will fail during model loading.
6. Run The Web App
From the project root:
cd StyleXfer_NST_code
python app.py
Then open:
http://localhost:5000
You can also run with Flask:
cd StyleXfer_NST_code
flask --app app run
Routes
| Method | Route | Description |
|---|---|---|
GET |
/ |
Render the upload page |
POST |
/ |
Process uploaded content/style images and generate output |
GET |
/uploads/<filename> |
Serve uploaded or generated images |
GET |
/examples/<path:filename> |
Serve static example images |
Strengths
- Implements the real AdaIN algorithm instead of only using a library wrapper
- Includes both training and inference code
- Uses a frozen pretrained VGG encoder and trainable decoder architecture
- Provides a complete Flask web app around the ML pipeline
- Has a clean user workflow with previews, slider control, output display, and download
- Includes sample examples for quick demonstration
- Supports local development with Flask/Werkzeug
- Production-ready Docker deployment on Hugging Face Spaces
- Easily portable to other Docker-compatible platforms
Limitations
- Inference speed depends heavily on CPU/GPU availability
- Large images may take longer to process
- The app currently saves uploads and outputs to local disk
- There is no database or user account system
- Uploaded files are not automatically cleaned up
- Only image files with
png,jpg, andjpegextensions are accepted - Model files must be present locally before running the app
- Docker deployment requires sufficient resource quotas on Hugging Face Spaces
Deployment
Docker Deployment (Hugging Face Spaces)
The project is deployed on Hugging Face Spaces using Docker:
# Build the Docker image
docker build -t stylexfer .
# Run the container
docker run -p 7860:7860 stylexfer
The Dockerfile uses Python 3.12-slim and runs the Flask app on port 7860, which is the standard port for Hugging Face Spaces.
Live URL: https://arpit16112-stylexfer.hf.space/
Future Improvements
- Add automatic cleanup for old uploaded/generated images
- Add image size limits and better upload validation
- Add drag-and-drop upload UI
- Add before/after comparison slider
- Add multiple predefined style presets
- Add download options for different output sizes
- Add WebGL-based client-side inference for faster processing
- Add style presets and favorites system
Learning Outcomes
This project demonstrates:
- building a Flask web application for ML inference
- using Flask-WTF for secure file upload forms
- serving generated images through Flask routes
- implementing Adaptive Instance Normalization in PyTorch
- building a VGG encoder and decoder architecture
- training a decoder for neural style transfer
- using feature statistics for style representation
- managing model checkpoints
