cervenaraketa's picture
Update app.py
18b8b6a verified
Raw
History Blame Contribute Delete
4.56 kB
import gradio as gr
import torch
from torchvision import transforms
from PIL import Image
import torch.nn as nn
# ==========================
# Konfigurace modelu
# ==========================
model_path = "models/frUn_OR_13k0050_512.pth" # Model bude nahrán do složky "models" na Hugging Face
target_width = 1500
# ==========================
# Definice U-Net modelu
# ==========================
class UNet(nn.Module):
def __init__(self, n_channels=3, n_classes=3, bilinear=True):
super(UNet, self).__init__()
self.n_channels = n_channels
self.n_classes = n_classes
self.bilinear = bilinear
self.inc = double_conv(n_channels, 64)
self.down1 = nn.Sequential(
nn.MaxPool2d(2),
double_conv(64, 128)
)
self.down2 = nn.Sequential(
nn.MaxPool2d(2),
double_conv(128, 256)
)
self.down3 = nn.Sequential(
nn.MaxPool2d(2),
double_conv(256, 512)
)
self.down4 = nn.Sequential(
nn.MaxPool2d(2),
double_conv(512, 512)
)
self.up1 = Up(512 + 512, 256, bilinear)
self.up2 = Up(256 + 256, 128, bilinear)
self.up3 = Up(128 + 128, 64, bilinear)
self.up4 = Up(64 + 64, 64, bilinear)
self.outc = nn.Conv2d(64, n_classes, kernel_size=1)
self.final_activation = nn.Sigmoid()
def forward(self, x):
x1 = self.inc(x)
x2 = self.down1(x1)
x3 = self.down2(x2)
x4 = self.down3(x3)
x5 = self.down4(x4)
x = self.up1(x5, x4)
x = self.up2(x, x3)
x = self.up3(x, x2)
x = self.up4(x, x1)
x = self.outc(x)
x = self.final_activation(x)
return x
def double_conv(in_channels, out_channels):
return nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True),
nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True),
)
class Up(nn.Module):
def __init__(self, in_channels, out_channels, bilinear=True):
super(Up, self).__init__()
if bilinear:
self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
self.conv = double_conv(in_channels, out_channels)
else:
self.up = nn.ConvTranspose2d(in_channels // 2, in_channels // 2, kernel_size=2, stride=2)
self.conv = double_conv(in_channels, out_channels)
def forward(self, x1, x2):
x1 = self.up(x1)
diffY = x2.size()[2] - x1.size()[2]
diffX = x2.size()[3] - x1.size()[3]
x1 = nn.functional.pad(x1, [diffX // 2, diffX - diffX // 2,
diffY // 2, diffY - diffY // 2])
x = torch.cat([x2, x1], dim=1)
return self.conv(x)
# ==========================
# Načtení modelu
# ==========================
device = torch.device("cpu") # Vždy používáme CPU
model = UNet(n_channels=3, n_classes=3, bilinear=True).to(device)
model.load_state_dict(torch.load(model_path, map_location=device), strict=False)
model.eval()
# ==========================
# Pomocná funkce pro změnu velikosti s zachováním poměru stran
# ==========================
def resize_keeping_aspect_ratio(image, target_width):
aspect_ratio = image.height / image.width
target_height = int(target_width * aspect_ratio)
return image.resize((target_width, target_height), Image.LANCZOS)
# ==========================
# Funkce pro převod obrázku modelem
# ==========================
def generate_sketch(input_image):
# Změna velikosti na požadovanou šířku
resized_image = resize_keeping_aspect_ratio(input_image, target_width=target_width)
# Převod obrázku na tensor
transform = transforms.ToTensor()
image_tensor = transform(resized_image).unsqueeze(0).to(device)
# Provedení převodu modelem
with torch.no_grad():
output = model(image_tensor).squeeze(0).cpu()
# Převod výsledného tensoru zpět na PIL Image
output_image = transforms.ToPILImage()(output)
return output_image
# ==========================
# Rozhraní Gradio
# ==========================
interface = gr.Interface(
fn=generate_sketch,
inputs=gr.Image(type="pil", label="Vstupní obrázek"),
outputs=gr.Image(type="pil", format="jpeg"),
title="U-Net Image2draw",
description=""
)
interface.launch()