<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你知道Deeplab那些事兒?jiǎn)幔?/h1>

          共 31122字,需瀏覽 63分鐘

           ·

          2021-05-31 20:45

          DeepLab系列網(wǎng)絡(luò)

          DeepLab系列論文一共有四篇,分別對(duì)應(yīng)DeepLab V1,DeepLab V2,DeepLab V3,DeepLab V3+。

          DeepLab V1

          DCNNs因?yàn)榫哂泻芎玫钠揭撇蛔冃裕臻g信息細(xì)節(jié)已被高度抽象化)能夠很好的處理圖像分類(lèi)問(wèn)題,但是DCNNs的最后一層的輸出不足以準(zhǔn)確的定位物體進(jìn)行像素級(jí)分類(lèi)。DeepLab V1通過(guò)將最終DCNN層的輸出與完全連接的條件隨機(jī)場(chǎng)(CRF)結(jié)合起來(lái),克服了DCNNs平移不變性的問(wèn)題。

          DCNNs有兩個(gè)問(wèn)題需要處理:

          1. 池化和下采樣多次,導(dǎo)致分辨率下降,空間位置信息難以恢復(fù)
          2. 高層特征具有空間不變性,且細(xì)節(jié)信息丟失嚴(yán)重

          解決方案:

          1. 減少下采樣次數(shù),保證特征圖的分辨率,同時(shí)使用空洞卷積,擴(kuò)大感受野,獲取更多的上下文信息
          2. DeepLab采用完全連接的條件隨機(jī)場(chǎng)(CRF)提高模型捕獲細(xì)節(jié)的能力。

          DeepLab V1是基于VGG16網(wǎng)絡(luò)改寫(xiě)的,一共做了三件事。

          1. 將全連接層改為卷積層;
          2. 將最后最后兩個(gè)池化的步長(zhǎng)改為1(保證特征圖的分辨率,只下采樣8倍)
          3. 把VGG16中最后三個(gè)卷積層(conv5_1、conv5_2、conv5_3)的采樣率設(shè)置為2,且第一個(gè)全連接層的dilate rate設(shè)置為4(保持感受野)

          池化層作用:縮小特征圖的尺寸;快速擴(kuò)大感受野。

          為什么要擴(kuò)大感受野呢?為了利用更多的上下文信息進(jìn)行分析。既然pooling這么好用,為什么要去掉倆呢?這個(gè)問(wèn)題需要從頭捋。先說(shuō)傳統(tǒng)(早期)DCNN,主要用來(lái)解決圖片的分類(lèi)問(wèn)題,舉個(gè)栗子,對(duì)于分類(lèi)任務(wù),傳統(tǒng)模型只需要指出圖片是不是有小轎車(chē),至于小轎車(chē)在哪兒,不care。這就需要網(wǎng)絡(luò)網(wǎng)絡(luò)具有平移不變性。我們都知道,卷積本身就具有平移不變性,而pooling可以進(jìn)一步增強(qiáng)網(wǎng)絡(luò)的這一特性,因?yàn)閜ooling本身就是一個(gè)模糊位置的過(guò)程。所以pooling對(duì)于傳統(tǒng)DCNN可以說(shuō)非常nice了。

          再來(lái)說(shuō)語(yǔ)義分割。語(yǔ)義分割是一個(gè)end-to-end的問(wèn)題,需要對(duì)每個(gè)像素進(jìn)行精確的分類(lèi),對(duì)像素的位置很敏感,是個(gè)精細(xì)活兒。這就很尷尬了,pooling是一個(gè)不斷丟失位置信息的過(guò)程,而語(yǔ)義分割又需要這些信息,矛盾就產(chǎn)生了。沒(méi)辦法,只好去掉pooling嘍。全去掉行不行,理論上是可行的,實(shí)際使用嘛,一來(lái)顯卡沒(méi)那么大的內(nèi)存,二來(lái)費(fèi)時(shí)間。所以只去掉了兩層。(PS:在DeepLab V1原文中,作者還指出一個(gè)問(wèn)題,使用太多的pooling,特征層尺寸太小,包含的特征太稀疏了,不利于語(yǔ)義分割。)

          去了兩個(gè)pooling,感受野又不夠了怎么辦?沒(méi)關(guān)系,把a(bǔ)trous convolution借來(lái)用一下,這也是對(duì)VGG16的最后一個(gè)修改。atrous convolution人稱(chēng)空洞卷積,相比于傳統(tǒng)卷積,可以在不增加計(jì)算量的情況下擴(kuò)大感受野,如下圖:

          空洞卷積與傳統(tǒng)卷積的區(qū)別在于,傳統(tǒng)卷積是三連抽,感受野是3,如果是input_stride=2的空洞卷積是隔著抽,感受野一下擴(kuò)大到了5(rate=2),相當(dāng)于兩個(gè)傳統(tǒng)卷積的感受野,通過(guò)調(diào)整rate可以自由選擇感受野,感受野的問(wèn)題就解決了。

          另外,論文指出空洞卷積還可以增加特征的密度。

          DeepLab V1的另一個(gè)貢獻(xiàn)是使用條件隨機(jī)場(chǎng)CRF提高分類(lèi)精度。效果如下圖,可以看到提升是非常明顯的。

          之前的論文中提到:更深的CNN可以得到更加準(zhǔn)確的分類(lèi)結(jié)果,但是定位精度會(huì)更低。解決這個(gè)問(wèn)題有2種主要的方法:

          1. 將low level和high level的feature map進(jìn)行融合,F(xiàn)CN就是這樣做的。
          2. 引入super-pixel representation,用low level segmentation method來(lái)進(jìn)行定位任務(wù)。DeepLab v1中中使用全連接的條件隨機(jī)場(chǎng)方法來(lái)對(duì)定位做finetune,這比當(dāng)前的方法都要更好。

          DeepLab v1中也嘗試使用了多尺度預(yù)測(cè),來(lái)提高邊界定位精度:將輸入圖像通過(guò)2層的感知機(jī),與前四層的pooling layer輸出進(jìn)行concatenate,再輸入到softmax激活函數(shù)中,相當(dāng)于softmax的輸入channel是640。但是這種方式增加了參數(shù)量和存儲(chǔ)空間,而且性能比不上CRF。

          DeepLab v2

          文章總結(jié)起來(lái)就是:空洞卷積+全連接CRF+ASPP模塊, 主干網(wǎng)絡(luò)從預(yù)訓(xùn)練的VGG變成了ResNet,是DeepLab v1的加強(qiáng)版本。

          DCNNs中語(yǔ)義分割存在三個(gè)挑戰(zhàn):

          • 連續(xù)下采樣和池化操作,導(dǎo)致最后特征圖分辨率低。
          • 圖像中存在多尺度的物體(相比V1而言提出的新的挑戰(zhàn))
          • 空間不變性導(dǎo)致細(xì)節(jié)信息丟失

          應(yīng)對(duì)策略:

          • 移除部分池化操作,使用空洞卷積??刂铺卣鲌D的分辨率,保證較大感受野,得到較多的上下文信息,而不增加參數(shù)量
          • 利用不同膨脹率的空洞卷積融合多尺度信息—atrous spatial pyramid pooling(ASPP)(新的創(chuàng)新點(diǎn))。以多尺度的信息得到更精確的分割結(jié)果。ASPP并行的采用多個(gè)采樣率的空洞卷積層來(lái)探測(cè),以多個(gè)比例捕捉對(duì)象以及圖像上下文。
          • 全連接CRF。通過(guò)組合DCNN和概率圖模型(CRF),改進(jìn)分割邊界結(jié)果。在DCNN中最大池化和下采樣組合實(shí)現(xiàn)可平移不變性,但這對(duì)精度是有影響的。通過(guò)將最終的DCNN層響應(yīng)與全連接的CRF結(jié)合來(lái)克服這個(gè)問(wèn)題。

          提取密集特征的兩種方式:

          1. 上采樣
          2. 空洞卷積
          上采樣 vs. 空洞卷積
          • U型操作:首先下采樣將分辨率降低2倍 → 做卷積 → 上采樣得到結(jié)果。本質(zhì)上這只是在原圖片面積的1/4的內(nèi)容上做卷積響應(yīng)。
          • 空洞卷積:如果我們將全分辨率圖像做空洞卷積(采樣率為2,核大小與上面卷積核相同),直接得到結(jié)果。這樣可以計(jì)算出整張圖像的響應(yīng),效果更加平滑,特征更加密集。

          ASPP

          多尺度主要是為了解決目標(biāo)在圖像中表現(xiàn)為不同大小時(shí)仍能夠有很好的分割結(jié)果,比如同樣的物體,在近處拍攝時(shí)物體顯得大,遠(yuǎn)處拍攝時(shí)顯得小。并行采用多個(gè)采樣率的空洞卷積提取特征,再將特征進(jìn)行融合,該結(jié)構(gòu)稱(chēng)為空洞空間金字塔池化(atrous spatial pyramid pooling)。如下圖所示

          至于ASPP如何融合到VGG16中,將VGG16的conv6,換成不同rate的空洞卷積,再跟上conv7,8,最后做個(gè)大融合(對(duì)應(yīng)相加或1*1卷積)就OK了。

          CRF

          crf同deeplab v1

          DeepLab v3

          在文章開(kāi)頭提出幾種常見(jiàn)的捕獲multi-scale context的方法。

          1. 圖像金字塔。輸入圖像進(jìn)行尺度變換得到不同分辨率input,然后將所有尺度的圖像放入CNN中得到不同尺度的分割結(jié)果,最后將不同分辨率的分割結(jié)果融合得到原始分辨率的分割結(jié)果,類(lèi)似的方法為DeepMedic;
          2. 編碼-解碼結(jié)構(gòu)。FCN和UNet等結(jié)構(gòu);
          3. 本文提出的串聯(lián)結(jié)構(gòu)。
          4. 本文提出的并聯(lián)結(jié)構(gòu),Deeplab v3結(jié)構(gòu)。
          幾種常見(jiàn)的捕獲multi-scale context的方法

          空洞卷積的串行結(jié)構(gòu)

          空洞卷積的串行結(jié)構(gòu)會(huì)使網(wǎng)絡(luò)加深,對(duì)應(yīng)論文Sec 3.2。使用multi-grid的方法,修改了resnet的block4~block7,使得他們的output_stride都是16,這樣就可以保證空間位置信息不會(huì)損失太嚴(yán)重,而且論文中也發(fā)現(xiàn)如果一直進(jìn)行下采樣,將整體信息聚合到非常小的特征圖上,會(huì)降低語(yǔ)義分割結(jié)果的準(zhǔn)確度,如圖(a)所示。加入atrous convolution的級(jí)聯(lián)模塊如下,主要是使用了不同rate的atrous convolution進(jìn)行操作,增大filter的感受野。

          使用串行結(jié)構(gòu)加深網(wǎng)絡(luò)

          受到了采用不同大小網(wǎng)格層次結(jié)構(gòu)的多重網(wǎng)格方法的啟發(fā),我們提出的模型在block4和block7中采用了不同的空洞率。

          特別的,我們定義 Multi_Grid = 為block4到block7內(nèi)三個(gè)卷積層的unit rates。卷積層的最終空洞率等于unit rate和corresponding rate的乘積。例如,當(dāng)output_stride = 16,Multi_Grid = (1, 2, 4),block4中的三個(gè)卷積的rates = 2×(1, 2, 4) = (2, 4, 8) 。

          但是實(shí)驗(yàn)表明,相比并行結(jié)構(gòu),這種串行的結(jié)構(gòu)并不能得到一個(gè)很好的結(jié)果

          空洞卷積的并行結(jié)構(gòu)

          在并行結(jié)構(gòu)中,改進(jìn)內(nèi)容包括:

          1. 在ASPP中加入BN層。
          2. 當(dāng)采樣率變大,圖像邊界響應(yīng)無(wú)法捕捉遠(yuǎn)距離信息,導(dǎo)致卷積核的有效權(quán)重變小。只有中心的權(quán)重是有效的,3×3退化為1×1卷積核。為了解決該問(wèn)題需要整合全局上下文信息,對(duì)最后的feature map采用全局池化,并經(jīng)過(guò)256個(gè)1×1的卷積核+BN,然后雙線性插值到所需空間維度。

          最終并行結(jié)構(gòu)包含

          • ASPP:一個(gè)1×1的卷積和三個(gè)3×3、rates=(6,12,18)、output_stride=16的空洞卷積(256+BN)。
          • 圖像級(jí)特征。將特征做全局平均池化,后卷積,再上采樣。

          ASPP中不同rates的空洞卷積通過(guò)控制不同的padding輸出相同的尺寸,圖像級(jí)特征中上采樣后與ASPP尺寸一致。所有分支的結(jié)果被拼接起來(lái)并經(jīng)過(guò)1×1的卷積(256+BN),最后經(jīng)過(guò)1×1卷積生成分割結(jié)果。

          DeepLab v3+

          改進(jìn):

          1. BackBone:Xception
          2. Encoder-Decoder Structure

          由于BackBone可以隨意替換,Xception以后會(huì)講,并且都2121年了,有很多更強(qiáng)更快的BackBone可供使用,EfficientNet0~7等等。

          DeepLabV1、2、3都是backbone(or ASPP)輸出的結(jié)果直接雙線性上采樣到原始分辨率,非常簡(jiǎn)單粗暴的方法,如下圖中的(a)。DeepLab v3+吸取Encoder-Deconder的結(jié)構(gòu)(圖中的(b)為編碼器-解碼器結(jié)構(gòu)),增加了一個(gè)淺層到輸出的skip層,如下圖中的(c)。

          完整的DeepLab v3+的網(wǎng)絡(luò)結(jié)構(gòu):

          • encoder輸出的feature的output_stride=16,經(jīng)過(guò)雙線性上采樣4倍得到,,
          • 再取encoder中對(duì)應(yīng)著相同分辨率(即)的特征層,經(jīng)過(guò) 卷積降通道,此時(shí)輸出的feature記為。這里為什么要經(jīng)過(guò) 卷積降通道,是因?yàn)榇朔直媛实奶卣魍ǖ垒^多(256或512),而 輸出只有256,故降通道值,保持比 通道數(shù),利于模型學(xué)習(xí)。
          • 做concat,再經(jīng)過(guò)一個(gè) 卷積細(xì)化feature,最終再雙線性上采樣4倍得到預(yù)測(cè)結(jié)果。

          在實(shí)驗(yàn)部分展示了 是在速度和精度上最佳的平衡點(diǎn),使用 能夠進(jìn)一步提升精度,伴隨著是更大的計(jì)算消耗。

          總結(jié)

          DeepLab v1:空洞卷積+CRF

          • 減少下采樣次數(shù),盡可能的保留空間位置信息;
          • 使用空洞卷積,擴(kuò)大感受野,獲取更多的上下文信息;
          • 采用完全連接的條件隨機(jī)場(chǎng)(CRF)這種后處理方式,提高模型捕獲細(xì)節(jié)的能力。

          DeepLab v2:空洞卷積+ASPP+CRF

          • 在DeepLab v1的基礎(chǔ)上提出了圖像多尺度的問(wèn)題,并提出ASPP模塊來(lái)捕捉圖像多個(gè)尺度的上下文信息。
          • 仍然使用CRF后處理方式,處理邊緣細(xì)節(jié)信息。

          DeepLab v3:

          • 改進(jìn)了ASPP模塊:加入了BN層,
          • 探討了ASPP模塊的構(gòu)建方式:并行的方式精度更好。
          • 由于大采樣率的空洞卷積的權(quán)重變小,只有中心權(quán)重起作用,退化成卷積。所以將圖像級(jí)特征和ASPP特征進(jìn)行融合。

          DeepLab v3+: deeplabv3 + encoder-decoder

          • 使用了encoder-decoder(高層特征提供語(yǔ)義,decoder逐步回復(fù)邊界信息):提升了分割效果的同時(shí),關(guān)注了邊界的信息
          • encoder結(jié)構(gòu)中:采用Xception做為 BackBone,并將深度可分離卷積(depthwise deparable conv)應(yīng)用在了ASPP 和 encoder 模塊中,使網(wǎng)絡(luò)更快。

          DeepLab v3+ 代碼

          1. 主干網(wǎng)絡(luò)采用ResNet
          import math
          import torch.nn as nn
          import torch.utils.model_zoo as model_zoo


          class Bottleneck(nn.Module):
              expansion = 4

              def __init__(self, inplanes, planes, stride=1, dilation=1, downsample=None, BatchNorm=None):
                  super(Bottleneck, self).__init__()
                  self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
                  self.bn1 = BatchNorm(planes)
                  self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
                                         dilation=dilation, padding=dilation, bias=False)
                  self.bn2 = BatchNorm(planes)
                  self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
                  self.bn3 = BatchNorm(planes * 4)
                  self.relu = nn.ReLU(inplace=True)
                  self.downsample = downsample
                  self.stride = stride
                  self.dilation = dilation

              def forward(self, x):
                  residual = x

                  out = self.conv1(x)
                  out = self.bn1(out)
                  out = self.relu(out)

                  out = self.conv2(out)
                  out = self.bn2(out)
                  out = self.relu(out)

                  out = self.conv3(out)
                  out = self.bn3(out)

                  if self.downsample is not None:
                      residual = self.downsample(x)

                  out += residual
                  out = self.relu(out)

                  return out

          class ResNet(nn.Module):

              def __init__(self, block, layers, output_stride, BatchNorm, pretrained=True):
                  self.inplanes = 64
                  super(ResNet, self).__init__()
                  blocks = [124]
                  if output_stride == 16:
                      strides = [1221]
                      dilations = [1112]
                  elif output_stride == 8:
                      strides = [1211]
                      dilations = [1124]
                  else:
                      raise NotImplementedError

                  # Modules
                  self.conv1 = nn.Conv2d(364, kernel_size=7, stride=2, padding=3,
                                          bias=False)
                  self.bn1 = BatchNorm(64)
                  self.relu = nn.ReLU(inplace=True)
                  self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

                  self.layer1 = self._make_layer(block, 64, layers[0], stride=strides[0], dilation=dilations[0], BatchNorm=BatchNorm)
                  self.layer2 = self._make_layer(block, 128, layers[1], stride=strides[1], dilation=dilations[1], BatchNorm=BatchNorm)
                  self.layer3 = self._make_layer(block, 256, layers[2], stride=strides[2], dilation=dilations[2], BatchNorm=BatchNorm)
                  self.layer4 = self._make_MG_unit(block, 512, blocks=blocks, stride=strides[3], dilation=dilations[3], BatchNorm=BatchNorm)
                  # self.layer4 = self._make_layer(block, 512, layers[3], stride=strides[3], dilation=dilations[3], BatchNorm=BatchNorm)
                  self._init_weight()

                  if pretrained:
                      self._load_pretrained_model()

              def _make_layer(self, block, planes, blocks, stride=1, dilation=1, BatchNorm=None):
                  downsample = None
                  if stride != 1 or self.inplanes != planes * block.expansion:
                      downsample = nn.Sequential(
                          nn.Conv2d(self.inplanes, planes * block.expansion,
                                    kernel_size=1, stride=stride, bias=False),
                          BatchNorm(planes * block.expansion),
                      )

                  layers = []
                  layers.append(block(self.inplanes, planes, stride, dilation, downsample, BatchNorm))
                  self.inplanes = planes * block.expansion
                  for i in range(1, blocks):
                      layers.append(block(self.inplanes, planes, dilation=dilation, BatchNorm=BatchNorm))

                  return nn.Sequential(*layers)

              def _make_MG_unit(self, block, planes, blocks, stride=1, dilation=1, BatchNorm=None):
                  downsample = None
                  if stride != 1 or self.inplanes != planes * block.expansion:
                      downsample = nn.Sequential(
                          nn.Conv2d(self.inplanes, planes * block.expansion,
                                    kernel_size=1, stride=stride, bias=False),
                          BatchNorm(planes * block.expansion),
                      )

                  layers = []
                  layers.append(block(self.inplanes, planes, stride, dilation=blocks[0]*dilation,
                                      downsample=downsample, BatchNorm=BatchNorm))
                  self.inplanes = planes * block.expansion
                  for i in range(1, len(blocks)):
                      layers.append(block(self.inplanes, planes, stride=1,
                                          dilation=blocks[i]*dilation, BatchNorm=BatchNorm))

                  return nn.Sequential(*layers)

              def forward(self, input):
                  x = self.conv1(input)
                  x = self.bn1(x)
                  x = self.relu(x)
                  x = self.maxpool(x)

                  x = self.layer1(x)
                  low_level_feat = x
                  x = self.layer2(x)
                  x = self.layer3(x)
                  x = self.layer4(x)
                  return x, low_level_feat

              def _init_weight(self):
                  for m in self.modules():
                      if isinstance(m, nn.Conv2d):
                          n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                          m.weight.data.normal_(0, math.sqrt(2. / n))
          #             elif isinstance(m, SynchronizedBatchNorm2d):
          #                 m.weight.data.fill_(1)
          #                 m.bias.data.zero_()
                      elif isinstance(m, nn.BatchNorm2d):
                          m.weight.data.fill_(1)
                          m.bias.data.zero_()

              def _load_pretrained_model(self):
                  pretrain_dict = model_zoo.load_url('https://download.pytorch.org/models/resnet101-5d3b4d8f.pth')
                  model_dict = {}
                  state_dict = self.state_dict()
                  for k, v in pretrain_dict.items():
                      if k in state_dict:
                          model_dict[k] = v
                  state_dict.update(model_dict)
                  self.load_state_dict(state_dict)

          def ResNet101(output_stride=16, BatchNorm=nn.BatchNorm2d, pretrained=False):
              """Constructs a ResNet-101 model.
              Args:
                  pretrained (bool): If True, returns a model pre-trained on ImageNet
              """

              model = ResNet(Bottleneck, [34233], output_stride, BatchNorm, pretrained=pretrained)
              return model

          if __name__ == "__main__":
              import torch
              model = ResNet101(BatchNorm=nn.BatchNorm2d, pretrained=True, output_stride=8)
              input = torch.rand(13512512)
              output, low_level_feat = model(input)
              print(output.size())
              print(low_level_feat.size())

          1. DeepLab v3+
          import torch
          import torch.nn as nn
          from PIL import Image
          from IPython import display

          from torch.nn import functional as F
          import numpy as np
          import math

          from resnet import ResNet101


          net = ResNet101()


          ### ASPP
          class _ASPPModule(nn.Module):
              def __init__(self, inplanes, planes, kernel_size, padding, dilation):
                  super(_ASPPModule, self).__init__()
                  self.atrous_conv = nn.Conv2d(inplanes, planes, 
                                               kernel_size=kernel_size,
                                               padding=padding, 
                                               dilation=dilation,
                                               stride=1
                                               bias=False)
                  self.bn = nn.BatchNorm2d(planes)
                  self.relu = nn.ReLU()

              def forward(self, x):
                  x = self.atrous_conv(x)
                  x = self.bn(x)

                  return self.relu(x)

          class ASPP(nn.Module):
              def __init__(self):
                  super(ASPP, self).__init__()
                  inplanes = 2048  # resnet101 encoder
                  dilations = [161218]

                  self.aspp1 = _ASPPModule(inplanes, 2561, dilation=dilations[0], padding=0)  # padding=dilation使得輸出的4個(gè)特征圖尺寸保持一致
                  self.aspp2 = _ASPPModule(inplanes, 2563, dilation=dilations[1], padding=dilations[1])
                  self.aspp3 = _ASPPModule(inplanes, 2563, dilation=dilations[2], padding=dilations[2])
                  self.aspp4 = _ASPPModule(inplanes, 2563, dilation=dilations[3], padding=dilations[3])

                  self.global_avg_pool = nn.Sequential(nn.AdaptiveAvgPool2d((11)),
                                                       nn.Conv2d(inplanes, 2561, stride=1, bias=False),
                                                       nn.BatchNorm2d(256),
                                                       nn.ReLU())
                  self.conv1 = nn.Conv2d(12802561, bias=False)
                  self.bn1 = nn.BatchNorm2d(256)
                  self.relu = nn.ReLU()
                  self.dropout = nn.Dropout(0.5)

              def forward(self, x):
                  x1 = self.aspp1(x)
                  x2 = self.aspp2(x)
                  x3 = self.aspp3(x)
                  x4 = self.aspp4(x)
                  x5 = self.global_avg_pool(x)
                  x5 = F.interpolate(x5, size=x4.size()[2:], mode='bilinear', align_corners=True)
                  x = torch.cat((x1, x2, x3, x4, x5), dim=1)

                  x = self.conv1(x)
                  x = self.bn1(x)
                  x = self.relu(x)

                  return self.dropout(x)

          ### Decoder模塊
          class Decoder(nn.Module):
              def __init__(self, num_classes):
                  super(Decoder, self).__init__()
                  
                  low_level_inplanes = 256 #for resnet101 backbone

                  self.conv1 = nn.Conv2d(low_level_inplanes, 481, bias=False)
                  self.bn1 = nn.BatchNorm2d(48)
                  self.relu = nn.ReLU()
                  self.last_conv = nn.Sequential(nn.Conv2d(304256, kernel_size=3, stride=1, padding=1, bias=False),
                                                 nn.BatchNorm2d(256),
                                                 nn.ReLU(),
                                                 nn.Dropout(0.5),
                                                 nn.Conv2d(256256, kernel_size=3, stride=1, padding=1, bias=False),
                                                 nn.BatchNorm2d(256),
                                                 nn.ReLU(),
                                                 nn.Dropout(0.1),
                                                 nn.Conv2d(256, num_classes, kernel_size=1, stride=1))


              def forward(self, x, low_level_feat):
                  low_level_feat = self.conv1(low_level_feat)
                  low_level_feat = self.bn1(low_level_feat)
                  low_level_feat = self.relu(low_level_feat)

                  x = F.interpolate(x, size=low_level_feat.size()[2:], mode='bilinear', align_corners=True)
                  x = torch.cat((x, low_level_feat), dim=1)
                  x = self.last_conv(x)

                  return x

          ### DeepLab v3+
          class DeepLabv3p(nn.Module):
              def __init__(self, num_classes=2):
                  super(DeepLabv3p, self).__init__()

                  self.backbone = ResNet101()
                  self.aspp = ASPP()
                  self.decoder = Decoder(num_classes)

              def forward(self, input):
                  x, low_level_feat = self.backbone(input)
                  print('backbone----x, low_level_feat: ', x.size(), low_level_feat.size())
                  x = self.aspp(x)
                  print('ASPP output: ', x.size())
                  x = self.decoder(x, low_level_feat)
                  print('decoder output: ', x.size())
                  x = F.interpolate(x, size=input.size()[2:], mode='bilinear', align_corners=True)

                  return x

          ### 測(cè)試代碼
          deeplabv3p = DeepLabv3p()
          for k,v in net.named_parameters():
              print(k)

          image = torch.rand((43128128))
          mask = net(image)
          mask.size()

          參考

          1. https://arxiv.org/abs/1412.7062v2
          2. http://arxiv.org/abs/1606.00915
          3. https://arxiv.org/abs/1706.05587
          4. https://arxiv.org/abs/1802.02611
          5. https://blog.csdn.net/fanxuelian/article/details/85145558
          6. https://zhuanlan.zhihu.com/p/38474698
          7. https://blog.csdn.net/Dlyldxwl/article/details/81148810
          8. https://www.dazhuanlan.com/2020/04/19/5e9bc2dbb7640/
          9. https://zhuanlan.zhihu.com/p/196491750
          10. https://www.cnblogs.com/vincent1997/p/10889430.html
          11. https://zhuanlan.zhihu.com/p/75333140
          12. https://zhuanlan.zhihu.com/p/139187977
          13. https://blog.csdn.net/fanxuelian/article/details/85145558
          14. https://blog.csdn.net/u011974639/article/details/79148719
          15. https://blog.csdn.net/u011974639/article/details/79144773
          16. https://blog.csdn.net/u011974639/article/details/79518175
          17. https://blog.csdn.net/u011974639/article/details/79134409
          18. https://www.jianshu.com/p/295dcc4008b4
          19. https://zhuanlan.zhihu.com/p/34929725
          20. https://blog.csdn.net/magic_ll/article/details/109731491
          21. https://github.com/DarrenmondZhang/U_Net-DeepLabV3_Plus


          瀏覽 145
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)

          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.青娱乐 | 午夜福利视频日本一区二区欲望 | 囯产精品久久久久久久久久辛辛 | 4438欧美日韩 | 国产精品色综合 |