Семантична сегментація з U-Net

Глибоке навчання для зображень із PyTorch

Michal Oleszak

Machine Learning Engineer

Семантична сегментація

  • Без розрізнення різних екземплярів одного класу
  • Корисно для медичних зображень і супутникової зйомки
  • Популярна архітектура: U-Net
Глибоке навчання для зображень із PyTorch

Архітектура U-Net

Схема архітектури U-Net

Кодувальник:

  • Згорткові та пулінгові шари
  • Даунсемплінг: зменшує просторові розміри та збільшує глибину
Глибоке навчання для зображень із PyTorch

Архітектура U-Net

Схема архітектури U-Net

Декодувальник:

  • Симетричний до кодувальника
  • Апсемплить карти ознак транспонованими згортками
Глибоке навчання для зображень із PyTorch

Архітектура U-Net

Схема архітектури U-Net

Пропуски (skip connections):

  • Зв'язки від кодувальника до декодувальника
  • Зберігають деталі, втрачені під час даунсемплінгу
Глибоке навчання для зображень із PyTorch

Транспонована згортка

Схема транспонованої згортки

  • Апсемплить карти ознак у декодері: збільшує висоту й ширину, зменшуючи глибину
  • Процес транспонованої згортки:
    1. Вставте нулі між елементами або навколо вхідної карти ознак
    2. Виконайте звичайну згортку на вході з нульовим заповненням
Глибоке навчання для зображень із PyTorch

Транспонована згортка в PyTorch

import torch.nn as nn

upsample = nn.ConvTranspose2d(
    in_channels=in_channels,
    out_channels=out_channels,
    kernel_size=2,
    stride=2,
)
Глибоке навчання для зображень із PyTorch

U-Net: визначення шарів

class UNet(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(UNet, self).__init__()


self.enc1 = self.conv_block(in_channels, 64) self.enc2 = self.conv_block(64, 128) self.enc3 = self.conv_block(128, 256) self.enc4 = self.conv_block(256, 512) self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.upconv3 = nn.ConvTranspose2d(512, 256, kernel_size=2, stride=2) self.upconv2 = nn.ConvTranspose2d(256, 128, kernel_size=2, stride=2) self.upconv1 = nn.ConvTranspose2d(128, 64, kernel_size=2, stride=2)
self.dec1 = self.conv_block(512, 256) self.dec2 = self.conv_block(256, 128) self.dec3 = self.conv_block(128, 64) self.out = nn.Conv2d(64, out_channels, kernel_size=1)
  • Кодувальник:
    • Згорткові блоки
      def conv_block(self, in_channels, out_channels):
      return nn.Sequential(
        nn.Conv2d(in_channels, out_channels),
        nn.ReLU(inplace=True),
        nn.Conv2d(out_channels, out_channels),
        nn.ReLU(inplace=True)
      )
      
    • Пулінговий шар
  • Декодувальник:
    • Транспоновані згортки
    • Згорткові блоки
Глибоке навчання для зображень із PyTorch

U-Net: метод forward

def forward(self, x):

x1 = self.enc1(x) x2 = self.enc2(self.pool(x1)) x3 = self.enc3(self.pool(x2)) x4 = self.enc4(self.pool(x3))
x = self.upconv3(x4)
x = torch.cat([x, x3], dim=1)
x = self.dec1(x)
x = self.upconv2(x) x = torch.cat([x, x2], dim=1) x = self.dec2(x) x = self.upconv1(x) x = torch.cat([x, x1], dim=1) x = self.dec3(x)
return self.out(x)
  • Пропустіть вхід через згорткові блоки кодувальника та пулінгові шари
  • Декодувальник і пропуски:
    • Пропустіть закодований вхід через транспоновану згортку
    • Конкатенуйте з відповідним виходом кодувальника
    • Пропустіть через згортковий блок
    • Повторіть для всіх кроків декодувальника
  • Поверніть вихід останнього кроку декодувальника
Глибоке навчання для зображень із PyTorch

Запуск інференсу

model = UNet()
model.eval()


image = Image.open("car.jpg") transform = transforms.Compose([transforms.ToTensor()]) image_tensor = transform(image).unsqueeze(0)
with torch.no_grad(): prediction = model(image_tensor).squeeze(0)
plt.imshow(prediction[1, :, :]) plt.show()

Оригінальне фото авто

Семантична маска, накладена на зображення авто

Глибоке навчання для зображень із PyTorch

Давайте потренуємось!

Глибоке навчання для зображень із PyTorch

Preparing Video For Download...