選單

三個優秀的語義分割框架 PyTorch實現

【導語】

本文基於動手深度學習專案講解了FCN進行自然影象語義分割的流程,並對U-Net和Deeplab網路進行了實驗,在Github和谷歌網盤上開源了程式碼和預訓練模型,訓練和預測的指令碼已經做好封裝,讀者可以自行下載使用。

1 前言

使用的VOC資料集連結開放在文章中,預訓練模型已上傳Github,環境我使用,大家下載模型做預測即可。

程式碼連結:

https://github。com/lixiang007666/segmentation-learning-experiment-pytorch

使用方法:

下載VOC資料集,將 兩個資料夾放入到data資料夾下。

終端切換到目標目錄,執行檢視訓練

(torch) qust116-jq@qustx-X299-WU8:~/語義分割$ python train。py -h

usage: train。py [-h] [-m ] [-g GPU]

choose the model

optional arguments:

-h, ——help            show this help message and exit

-m , ——model

輸入模型名字

-g GPU, ——gpu GPU     輸入所需GPU

選擇模型和GPU編號進行訓練,例如執行

預測需要手動修改中的模型

如果對FCN非常瞭解的,可以直接跳過(動手學深度學習)的講解到最後一部分。

2 資料集

VOC資料集一般是用來做目標檢測,在2012版本中,加入了語義分割任務。

基礎資料集中包括:含有1464張圖片的訓練集,1449的驗證集和1456的測試集。一共有21類物體。

PASCAL VOC分割任務中,共有20個類別的物件,其他內容作為背景類,其中紅色代表飛機類,黑色是背景,飛機邊界部分用米黃色(看著像白色)線條描繪,表示分割模糊區。

其中,分割標籤都是png格式的影象,該影象其實是單通道的顏色索引影象,該影象除了有一個單通道和影象大小一樣的索引影象外,還儲存了256個顏色值列表(調色盤),每一個索引值對應調色盤裡一個RGB顏色值,因此,一個單通道的索引圖+調色盤就能表示彩色圖。

原圖:

三個優秀的語義分割框架 PyTorch實現

在這裡插入圖片描述

標籤:

三個優秀的語義分割框架 PyTorch實現

在這裡插入圖片描述

挑選一張影象可以發現,單張影象分割類別不只兩類,且每張影象類別不固定。

三個優秀的語義分割框架 PyTorch實現

3 全卷積神經網路

語義分割能對影象中的每個畫素分類。全卷積網路 (fully convolutional network,FCN) 採用卷積神經網路實現了從影象畫素到畫素類別的變換 。與我們之前在影象分類或目標檢測部分介紹的卷積神經網路不同,:這是透過中引入的轉置卷積(transposed convolution)層實現的。因此,輸出的類別預測與輸入影象在畫素級別上具有一一對應關係:給定空間維上的位置,通道維的輸出即該位置對應畫素的類別預測。

%matplotlib inline

import torch

import torchvision

from torch import nn

from torch。nn import functional as F

from d2l import torch as d2l

3。1 網路結構

全卷積網路先使用卷積神經網路抽取影象特徵,然後透過

卷積層將通道數變換為類別個數,最後再透過轉置卷積層將特徵圖的高和寬變換為輸入影象的尺寸。因此,模型輸出與輸入影象的高和寬相同,且最終輸出的通道包含了該空間位置畫素的類別預測。

下面,我們使用在ImageNet資料集上預訓練的ResNet-18模型來提取影象特徵,並將該網路例項記為。該模型的最後幾層包括全域性平均匯聚層和全連線層,然而全卷積網路中不需要它們。

三個優秀的語義分割框架 PyTorch實現

建立一個全卷積網路例項。它複製了Resnet-18中大部分的預訓練層,但除去最終的全域性平均匯聚層和最接近輸出的全連線層。

net = nn。Sequential(*list(pretrained_net。children())[:-2])

給定高度和寬度分別為320和480的輸入,的前向計算將輸入的高和寬減小至原來的

,即10和15。

X = torch。rand(size=(1, 3, 320, 480))

net(X)。shape

使用

卷積層將輸出通道數轉換為Pascal VOC2012資料集的類數(21類)。最後,我們需要將要素地圖的高度和寬度增加32倍,從而將其變回輸入影象的高和寬。

回想一下卷積層輸出形狀的計算方法:

由於

,我們構造一個步幅為

的轉置卷積層,並將卷積核的高和寬設為

,填充為

我們可以看到如果步幅為

,填充為

(假設

是整數)且卷積核的高和寬為

,轉置卷積核會將輸入的高和寬分別放大

倍。

num_classes = 21

net。add_module(‘final_conv’, nn。Conv2d(512, num_classes, kernel_size=1))

net。add_module(‘transpose_conv’, nn。ConvTranspose2d(num_classes, num_classes,

kernel_size=64, padding=16, stride=32))

3。2 初始化轉置卷積層

將影象放大通常使用上取樣(upsampling)方法。雙線性插值(bilinear interpolation) 是常用的上取樣方法之一,它也經常用於初始化轉置卷積層。

為了解釋雙線性插值,假設給定輸入影象,我們想要計算上取樣輸出影象上的每個畫素。

首先,將輸出影象的座標 (,) 對映到輸入影象的座標 (′,′) 上。例如,根據輸入與輸出的尺寸之比來對映。請注意,對映後的 ′ 和 ′ 是實數。

然後,在輸入影象上找到離座標 (′,′) 最近的4個畫素。

最後,輸出影象在座標 (,) 上的畫素依據輸入影象上這4個畫素及其與 (′,′) 的相對距離來計算。

雙線性插值的上取樣可以透過轉置卷積層實現,核心由以下bilinear_kernel函式構造。限於篇幅,我們只給出bilinear_kernel函式的實現,不討論演算法的原理。

def bilinear_kernel(in_channels, out_channels, kernel_size):

factor = (kernel_size + 1) // 2

if kernel_size % 2 == 1:

center = factor - 1

else:

center = factor - 0。5

og = (torch。arange(kernel_size)。reshape(-1, 1),

torch。arange(kernel_size)。reshape(1, -1))

filt = (1 - torch。abs(og[] - center) / factor) * \

(1 - torch。abs(og[1] - center) / factor)

weight = torch。zeros((in_channels, out_channels,

kernel_size, kernel_size))

weight[range(in_channels), range(out_channels), :, :] = filt

return weight

用雙線性插值的上取樣實驗它由轉置卷積層實現。我們構造一個將輸入的高和寬放大2倍的轉置卷積層,並將其卷積核用bilinear_kernel函式初始化。

在全卷積網路中,我們用雙線性插值的上取樣初始化轉置卷積層。對於 1×1卷積層,我們使用Xavier初始化引數。

3。3 訓練

損失函式和準確率計算與影象分類中的並沒有本質上的不同,因為我們使用轉置卷積層的通道來預測畫素的類別,所以在損失計算中通道維是指定的。此外,模型基於每個畫素的預測類別是否正確來計算準確率。

def loss(inputs, targets):

return F。cross_entropy(inputs, targets, reduction=‘none’)。mean(1)。mean(1)

num_epochs, lr, wd, devices = 5, 0。001, 1e-3, d2l。try_all_gpus()

trainer = torch。optim。SGD(net。parameters(), lr=lr, weight_decay=wd)

d2l。train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs, devices)

4 開原始碼和Dataset

資料集下載地址:http://host。robots。ox。ac。uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012。tar

輸入樣本:

三個優秀的語義分割框架 PyTorch實現

輸出樣本:

三個優秀的語義分割框架 PyTorch實現

執行Segmentat_pytorch.ipynp:

三個優秀的語義分割框架 PyTorch實現

訓練:

!python3 train。py -m Unet -g

預測:

三個優秀的語義分割框架 PyTorch實現

模型程式碼包括FCN、U-Net和Deeplab的實現,大家可以更方便的更換模型訓練和預測。

三個優秀的語義分割框架 PyTorch實現

DeeplabV3分割結果:

三個優秀的語義分割框架 PyTorch實現

FCN分割結果:

三個優秀的語義分割框架 PyTorch實現

在這裡插入圖片描述

U-Net分割結果:

三個優秀的語義分割框架 PyTorch實現

記得點個Star哦!

5 總結

透過與分割標準影象的對比,可以發現該模型的輸出分割影象與分割標準影象幾乎一致,同時模型的輸出分割影象與原圖也較好的融合,說明該模型具有較好的準確性。

此外,從輸入影象大小來看,該模型可以輸入任意大小的影象,並輸出相同大小的已經標籤好的分割影象。由於是針對PASCAL VOC資料集影象進行的分割,PASCAL VOC資料集中只支援20個類別(背景為第21個類別),所以在分割時,遇到不在20個類別中的事物都將其標為背景。

但總體來說,該模型對PASCAL VOC資料集的影象分割達到了較高準確率。

6 參考

[1]。https://zh-v2。d2l。ai/index。html

個人簡介:李響Superb,CSDN百萬訪問量博主,普普通通男大學生,深度學習演算法、醫學影象處理專攻,偶爾也搞全棧開發,沒事就寫文章。

本文僅做學術分享,如有侵權,請聯絡刪文。