NST / app.py
Amanprime's picture
Update app.py
64af805 verified
Raw
History Blame Contribute Delete
3.44 kB
from pathlib import Path
import gradio as gr
import torch
from PIL import Image, ImageOps
from torchvision import transforms
from utils.models import Decoder, VGGEncoder
from utils.utils import adaptive_instance_normalization
BASE_DIR = Path(__file__).resolve().parent
VGG_PATH = BASE_DIR / "weights" / "vgg_normalised.pth"
DECODER_PATH = BASE_DIR / "weights" / "decoder_final.pth"
MAX_IMAGE_SIZE = 512
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
torch.set_num_threads(min(4, max(1, torch.get_num_threads())))
def load_models():
if not VGG_PATH.exists():
raise FileNotFoundError(f"Missing VGG weights: {VGG_PATH}")
if not DECODER_PATH.exists():
raise FileNotFoundError(f"Missing decoder weights: {DECODER_PATH}")
encoder = VGGEncoder(str(VGG_PATH)).to(DEVICE).eval()
decoder = Decoder().to(DEVICE).eval()
decoder_state = torch.load(str(DECODER_PATH), map_location=DEVICE)
decoder.load_state_dict(decoder_state)
return encoder, decoder
ENCODER, DECODER = load_models()
def prepare_image(image: Image.Image) -> torch.Tensor:
image = ImageOps.exif_transpose(image).convert("RGB")
image.thumbnail((MAX_IMAGE_SIZE, MAX_IMAGE_SIZE), Image.Resampling.LANCZOS)
return transforms.ToTensor()(image).unsqueeze(0).to(DEVICE)
def tensor_to_image(tensor: torch.Tensor) -> Image.Image:
tensor = tensor.squeeze(0).detach().cpu().clamp(0, 1)
return transforms.ToPILImage()(tensor)
def stylize(content_image, style_image, alpha):
if content_image is None or style_image is None:
raise gr.Error("Upload both a content image and a style image.")
alpha = float(alpha)
content = prepare_image(content_image)
style = prepare_image(style_image)
with torch.inference_mode():
content_features = ENCODER(content, is_test=True)
style_features = ENCODER(style, is_test=True)
stylized_features = adaptive_instance_normalization(
content_features,
style_features,
)
blended_features = alpha * stylized_features + (1.0 - alpha) * content_features
output = DECODER(blended_features)
return tensor_to_image(output)
example_dir = BASE_DIR / "examples"
examples = [
[
str(example_dir / "content_lenna.jpg"),
str(example_dir / "style_sketch.png"),
1.0,
],
[
str(example_dir / "content_golden_gate.jpg"),
str(example_dir / "style_la_muse.jpg"),
0.8,
],
]
with gr.Blocks(title="AdaIN Neural Style Transfer") as demo:
gr.Markdown("# AdaIN Neural Style Transfer")
with gr.Row():
content_input = gr.Image(type="pil", label="Content image")
style_input = gr.Image(type="pil", label="Style image")
alpha_input = gr.Slider(
minimum=0.0,
maximum=1.0,
value=1.0,
step=0.05,
label="Style strength",
)
run_button = gr.Button("Transfer style", variant="primary")
output_image = gr.Image(type="pil", label="Stylized output")
run_button.click(
fn=stylize,
inputs=[content_input, style_input, alpha_input],
outputs=output_image,
)
gr.Examples(
examples=examples,
inputs=[content_input, style_input, alpha_input],
outputs=output_image,
fn=stylize,
cache_examples=False,
)
if __name__ == "__main__":
demo.queue(max_size=8).launch(ssr_mode=False)