ItqaAkhlaq's picture
Create app.py
8912244 verified
Raw
History Blame Contribute Delete
2.97 kB
import torch
import torch.nn as nn
import torchvision.transforms as transforms
import torchvision.models as models
from PIL import Image
import gradio as gr
# Device setup
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Image loader
def load_image(image, max_size=400):
transform = transforms.Compose([
transforms.Resize(max_size),
transforms.ToTensor(),
transforms.Lambda(lambda x: x[:3, :, :]), # remove alpha channel
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
image = transform(image).unsqueeze(0)
return image.to(device)
# Reconvert image
def tensor_to_pil(tensor):
image = tensor.cpu().clone().squeeze(0)
image = image * torch.tensor([0.229, 0.224, 0.225]).view(3,1,1) + torch.tensor([0.485, 0.456, 0.406]).view(3,1,1)
image = image.clamp(0, 1)
image = transforms.ToPILImage()(image)
return image
# VGG19 Model
class VGGFeatures(nn.Module):
def __init__(self):
super(VGGFeatures, self).__init__()
vgg = models.vgg19(pretrained=True).features.eval()
self.slice = nn.Sequential(*list(vgg.children())[:21])
for param in self.slice.parameters():
param.requires_grad = False
def forward(self, x):
return self.slice(x)
# Gram Matrix
def gram_matrix(tensor):
b, c, h, w = tensor.size()
features = tensor.view(b * c, h * w)
G = torch.mm(features, features.t())
return G.div(b * c * h * w)
# Style Transfer Function
def style_transfer(content_img, style_img, steps=300, style_weight=1e6, content_weight=1):
content = load_image(content_img)
style = load_image(style_img)
generated = content.clone().requires_grad_(True)
model = VGGFeatures().to(device)
optimizer = torch.optim.LBFGS([generated])
content_features = model(content)
style_features = model(style)
style_gram = gram_matrix(style_features)
def closure():
optimizer.zero_grad()
generated_features = model(generated)
generated_gram = gram_matrix(generated_features)
content_loss = content_weight * nn.functional.mse_loss(generated_features, content_features)
style_loss = style_weight * nn.functional.mse_loss(generated_gram, style_gram)
total_loss = content_loss + style_loss
total_loss.backward()
return total_loss
for i in range(steps):
optimizer.step(closure)
return tensor_to_pil(generated)
# Gradio Interface
interface = gr.Interface(
fn=style_transfer,
inputs=[
gr.Image(type="pil", label="Content Image"),
gr.Image(type="pil", label="Style Image")
],
outputs=gr.Image(type="pil", label="Stylized Output"),
title="🎨 Neural Style Transfer",
description="Upload a content image and a style image. The model will apply the style to the content!"
)
if __name__ == "__main__":
interface.launch()