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