13.5-13.8. 計算機視覺【2】

文章目錄

    • 13.5. 多尺度目標檢測
      • 13.5.1. 多尺度錨框
      • 13.5.2. 多尺度檢測
      • 13.5.3. 小結
    • 13.6. 目標檢測數據集
      • 13.6.2. 讀取數據集
      • 13.6.3. 演示
    • 13.7. 單發多框檢測(SSD)
      • 13.7.1. 模型
        • 13.7.1.1. 類別預測層
        • 13.7.1.2. 邊界框預測層
        • 13.7.1.3. 連結多尺度的預測
        • 13.7.1.4. 高和寬減半塊
        • 13.7.1.5. 基本網絡塊
        • 13.7.1.6. 完整的模型
      • 13.7.2. 訓練模型
        • 13.7.2.1. 讀取數據集和初始化
        • 13.7.2.2. 定義損失函數和評價函數
        • 13.7.2.3. 訓練模型
      • 13.7.3. 預測目標
      • 13.7.4. 小結
    • 13.8. 區域卷積神經網絡(R-CNN)系列
      • 13.8.1. R-CNN
      • 13.8.2. Fast R-CNN
      • 13.8.3. Faster R-CNN
      • 13.8.4. Mask R-CNN
      • 13.8.5. 小結

13.5. 多尺度目標檢測

在 13.4節中,我們以輸入圖像的每個像素為中心,生成了多個錨框。 基本而言,這些錨框代表了圖像不同區域的樣本。 然而,如果為每個像素都生成的錨框,我們最終可能會得到太多需要計算的錨框。 想象一個 (561, 728)的輸入圖像,如果以每個像素為中心生成五個形狀不同的錨框,就需要在圖像上標記和預測超過200萬個錨框(561, 728, 5)。

13.5.1. 多尺度錨框

減少圖像上的錨框數量并不困難。 比如,我們可以在輸入圖像中均勻采樣一小部分像素,并以它們為中心生成錨框。 此外,在不同尺度下,我們可以生成不同數量和不同大小的錨框。 直觀地說,比起較大的目標,較小的目標在圖像上出現的可能性更多樣。 例如, 1x1、1x2 和 2x2 的目標可以分別以4、2和1種可能的方式出現在 2x2 圖像上。 因此,當使用較小的錨框檢測較小的物體時,我們可以采樣更多的區域,而對于較大的物體,我們可以采樣較少的區域

在這里插入圖片描述
回想一下,在 6.2節中,我們將卷積圖層的二維數組輸出稱為特征圖。 通過定義特征圖的形狀,我們可以確定任何圖像上均勻采樣錨框的中心。

display_anchors函數定義如下。 我們在特征圖(fmap)上生成錨框(anchors),每個單位(像素)作為錨框的中心。 由于錨框中的 (x, y)軸坐標值(anchors)已經被除以特征圖(fmap)的寬度和高度,因此這些值介于0和1之間,表示特征圖中錨框的相對位置

由于錨框(anchors)的中心分布于特征圖(fmap)上的所有單位,因此這些中心必須根據其相對空間位置在任何輸入圖像上均勻分布。 更具體地說,給定特征圖的寬度和高度fmap_w和fmap_h,以下函數將均勻地對任何輸入圖像中fmap_h行和fmap_w列中的像素進行采樣。 以這些均勻采樣的像素為中心,將會生成大小為s(假設列表s的長度為1)且寬高比(ratios)不同的錨框。

def display_anchors(fmap_w, fmap_h, s):d2l.set_figsize()# 前兩個維度上的值不影響輸出fmap = torch.zeros((1, 10, fmap_h, fmap_w))# multibox_priors是在輸入的fmap每個像素上生成錨框,并且坐標在[0, 1]之間anchors = d2l.multibox_prior(fmap, sizes=s, ratios=[1, 2, 0.5])# 這里再*真實圖像寬高, 就變成了在真實圖像上均勻分布的錨框,并且上面fmap的寬高就是錨框在每行列上的個數bbox_scale = torch.tensor((w, h, w, h))d2l.show_bboxes(d2l.plt.imshow(img).axes,anchors[0] * bbox_scale)

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

13.5.2. 多尺度檢測

在這里插入圖片描述

13.5.3. 小結

  • 在多個尺度下,我們可以生成不同尺寸的錨框來檢測不同尺寸的目標。
  • 通過定義特征圖的形狀,我們可以決定任何圖像上均勻采樣的錨框的中心。
  • 我們使用輸入圖像在某個感受野區域內的信息,來預測輸入圖像上與該區域位置相近的錨框類別和偏移量。
  • 我們可以通過深入學習,在多個層次上的圖像分層表示進行多尺度目標檢測。

13.6. 目標檢測數據集

目標檢測領域沒有像MNIST和Fashion-MNIST那樣的小數據集。 為了快速測試目標檢測模型,我們收集并標記了一個小型數據集。 首先,我們拍攝了一組香蕉的照片,并生成了1000張不同角度和大小的香蕉圖像。 然后,我們在一些背景圖片的隨機位置上放一張香蕉的圖像。 最后,我們在圖片上為這些香蕉標記了邊界框。

13.6.2. 讀取數據集

通過read_data_bananas函數,我們讀取香蕉檢測數據集。 該數據集包括一個的CSV文件,內含目標類別標簽和位于左上角和右下角的真實邊界框坐標。

#@save
def read_data_bananas(is_train=True):"""讀取香蕉檢測數據集中的圖像和標簽"""data_dir = d2l.download_extract('banana-detection')csv_fname = os.path.join(data_dir, 'bananas_train' if is_trainelse 'bananas_val', 'label.csv')csv_data = pd.read_csv(csv_fname)csv_data = csv_data.set_index('img_name')images, targets = [], []for img_name, target in csv_data.iterrows():images.append(torchvision.io.read_image(os.path.join(data_dir, 'bananas_train' if is_train else'bananas_val', 'images', f'{img_name}')))# 這里的target包含(類別,左上角x,左上角y,右下角x,右下角y),# 其中所有圖像都具有相同的香蕉類(索引為0)targets.append(list(target))return images, torch.tensor(targets).unsqueeze(1) / 256

解釋

  1. csv_data = csv_data.set_index(‘img_name’) 和 for img_name, target in csv_data.iterrows(): 配合使用的作用:
    在這里插入圖片描述
  2. 最后返回 torch.tensor(targets).unsqueeze(1) / 256 的作用:unsqueeze 是模擬一張圖像里面有多個目標檢測框,這里為了簡單直接都設置為1個檢測框。
    在這里插入圖片描述
    在這里插入圖片描述

13.6.3. 演示

在這里插入圖片描述

13.7. 單發多框檢測(SSD)

在 13.3節— 13.6節中,我們分別介紹了邊界框、錨框、多尺度目標檢測和用于目標檢測的數據集。 現在我們已經準備好使用這樣的背景知識來設計一個目標檢測模型:單發多框檢測(SSD) (Liu et al., 2016)。 該模型簡單、快速且被廣泛使用。盡管這只是其中一種目標檢測模型,但本節中的一些設計原則和實現細節也適用于其他模型。

13.7.1. 模型

圖13.7.1描述了單發多框檢測模型的設計。 此模型主要由基礎網絡組成,其后是幾個多尺度特征塊。 基本網絡用于從輸入圖像中提取特征,因此它可以使用深度卷積神經網絡。 單發多框檢測論文中選用了在分類層之前截斷的VGG (Liu et al., 2016),現在也常用ResNet替代。 我們可以設計基礎網絡,使它輸出的高和寬較大。 這樣一來,基于該特征圖生成的錨框數量較多,可以用來檢測尺寸較小的目標。 接下來的每個多尺度特征塊將上一層提供的特征圖的高和寬縮小(如減半),并使特征圖中每個單元在輸入圖像上的感受野變得更廣闊

回想一下在 13.5節中,通過深度神經網絡分層表示圖像的多尺度目標檢測的設計。 由于接近 圖13.7.1頂部的多尺度特征圖較小,但具有較大的感受野,它們適合檢測較少但較大的物體。 簡而言之,通過多尺度特征塊,單發多框檢測生成不同大小的錨框,并通過預測邊界框的類別和偏移量來檢測大小不同的目標,因此這是一個多尺度目標檢測模型。

在這里插入圖片描述

13.7.1.1. 類別預測層

設目標類別的數量為 q 。這樣一來,錨框有 q+1 個類別,其中0類是背景。 在某個尺度下,設特征圖的高和寬分別為 h 和 w。 如果以其中每個單元為中心生成 a 個錨框,那么我們需要對 hwa 個錨框進行分類。 如果使用全連接層作為輸出,很容易導致模型參數過多。 回憶 7.3節一節介紹的使用卷積層的通道來輸出類別預測的方法, 單發多框檢測采用同樣的方法來降低模型復雜度

具體來說,類別預測層使用一個保持輸入高和寬的卷積層。 這樣一來,輸出和輸入在特征圖寬和高上的空間坐標一一對應。 考慮輸出和輸入同一空間坐標(x, y):輸出特征圖上(x, y)坐標的通道里包含了以輸入特征圖(x, y)坐標為中心生成的所有錨框的類別預測。 因此輸出通道數為 a(q+1),其中索引為 i(q+1) + j的通道代表了索引為 i 的錨框有關類別索引為 j 的預測

在下面,我們定義了這樣一個類別預測層,通過參數num_anchors和num_classes分別指定了 a 和 q。 該圖層使用填充為1的 3x3 的卷積層。此卷積層的輸入和輸出的寬度和高度保持不變。

%matplotlib inline
import torch
import torchvision
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2ldef cls_predictor(num_inputs, num_anchors, num_classes):return nn.Conv2d(num_inputs, num_anchors * (num_classes + 1),kernel_size=3, padding=1)
13.7.1.2. 邊界框預測層

邊界框預測層的設計與類別預測層的設計類似。 唯一不同的是,這里需要為每個錨框預測4個偏移量,而不是 q+1 個類別。

def bbox_predictor(num_inputs, num_anchors):return nn.Conv2d(num_inputs, num_anchors * 4, kernel_size=3, padding=1)
13.7.1.3. 連結多尺度的預測

正如我們所提到的,單發多框檢測使用多尺度特征圖來生成錨框并預測其類別和偏移量。 在不同的尺度下,特征圖的形狀或以同一單元為中心的錨框的數量可能會有所不同。 因此,不同尺度下預測輸出的形狀可能會有所不同

在以下示例中,我們為同一個小批量構建兩個不同比例(Y1和Y2)的特征圖,其中Y2的高度和寬度是Y1的一半。 以類別預測為例,假設Y1和Y2的每個單元分別生成了 5 個和 3 個錨框。 進一步假設目標類別的數量為 10,對于特征圖Y1和Y2,類別預測輸出中的通道數分別為 5x(10+1) = 55 和 3x(10+1) = 33,其中任一輸出的形狀是(批量大小,通道數,高度,寬度)

def forward(x, block):return block(x)Y1 = forward(torch.zeros((2, 8, 20, 20)), cls_predictor(8, 5, 10))
Y2 = forward(torch.zeros((2, 16, 10, 10)), cls_predictor(16, 3, 10))
Y1.shape, Y2.shape
# 打印結果:
# (torch.Size([2, 55, 20, 20]), torch.Size([2, 33, 10, 10]))

正如我們所看到的,除了批量大小這一維度外,其他三個維度都具有不同的尺寸。 為了將這兩個預測輸出鏈接起來以提高計算效率,我們將把這些張量轉換為更一致的格式

通道維包含中心相同的錨框的預測結果。我們首先將通道維移到最后一維。 因為不同尺度下批量大小仍保持不變,我們可以將預測結果轉成二維的(批量大小,高x寬x通道數)的格式,以方便之后在維度 1 上的連結

def flatten_pred(pred):return torch.flatten(pred.permute(0, 2, 3, 1), start_dim=1)def concat_preds(preds):return torch.cat([flatten_pred(p) for p in preds], dim=1)

這樣一來,盡管Y1和Y2在通道數、高度和寬度方面具有不同的大小,我們仍然可以在同一個小批量的兩個不同尺度上連接這兩個預測輸出。

concat_preds([Y1, Y2]).shape
# 打印結果
# torch.Size([2, 25300])
13.7.1.4. 高和寬減半塊

在這里插入圖片描述

13.7.1.5. 基本網絡塊

在這里插入圖片描述

13.7.1.6. 完整的模型

完整的單發多框檢測模型由五個模塊組成。每個塊生成的特征圖既用于生成錨框,又用于預測這些錨框的類別和偏移量。在這五個模塊中,第一個是基本網絡塊,第二個到第四個是高和寬減半塊,最后一個模塊使用全局最大池將高度和寬度都降到1。從技術上講,第二到第五個區塊都是 圖13.7.1中的多尺度特征塊。

def get_blk(i):if i == 0:blk = base_net()elif i == 1:blk = down_sample_blk(64, 128)elif i == 4:blk = nn.AdaptiveMaxPool2d((1,1))else:blk = down_sample_blk(128, 128)return blk

現在我們為每個塊定義前向傳播。與圖像分類任務不同,此處的輸出包括:CNN特征圖Y;在當前尺度下根據Y生成的錨框;預測的這些錨框的類別和偏移量(基于Y)

def blk_forward(X, blk, size, ratio, cls_predictor, bbox_predictor):Y = blk(X)# 基于當前的特征圖大小,生成的不同大小和寬高比的初始anchoranchors = d2l.multibox_prior(Y, sizes=size, ratios=ratio)# 基于當前特征圖,再過一層conv預測的每個anchor的類別cls_preds = cls_predictor(Y)# 基于當前特征圖,再過一層conv預測的每個anchor的偏移量bbox_preds = bbox_predictor(Y)return (Y, anchors, cls_preds, bbox_preds)

在這里插入圖片描述
疑問:較大值為什么是這么計算的?
在這里插入圖片描述

現在,我們就可以按如下方式定義完整的模型TinySSD了。

class TinySSD(nn.Module):def __init__(self, num_classes, **kwargs):super(TinySSD, self).__init__(**kwargs)self.num_classes = num_classes# 最開始的basenet輸出64通道,剩下的卷積都是輸出128通道idx_to_in_channels = [64, 128, 128, 128, 128]for i in range(5):# 即賦值語句self.blk_i=get_blk(i)setattr(self, f'blk_{i}', get_blk(i))setattr(self, f'cls_{i}', cls_predictor(idx_to_in_channels[i],num_anchors, num_classes))setattr(self, f'bbox_{i}', bbox_predictor(idx_to_in_channels[i],num_anchors))def forward(self, X):# 5個不同尺度特征圖上的輸出anchors, cls_preds, bbox_preds = [None] * 5, [None] * 5, [None] * 5for i in range(5):# getattr(self,'blk_%d'%i)即訪問self.blk_iX, anchors[i], cls_preds[i], bbox_preds[i] = blk_forward(X, getattr(self, f'blk_{i}'), sizes[i], ratios[i],getattr(self, f'cls_{i}'), getattr(self, f'bbox_{i}'))# 每個anchor: (1, N, 4), 1是unsqueeze固定為1, N是當前尺度特征圖的anchor數量anchors = torch.cat(anchors, dim=1)  # (1, N', 4)# list中每個預測: (b, c, h, w), c=4x(1+1), 4是每個像素anchor數,(1+1)是目標類別+背景類別# 最后concat_preds之后:(b, h'w'c')cls_preds = concat_preds(cls_preds)# (b, h'w', c'), 也就是不同尺度的每個像素上anchor的類別cls_preds = cls_preds.reshape(cls_preds.shape[0], -1, self.num_classes + 1)# 同上,最后是(b, h'w'x4), 4是每個anchor固定的4個坐標偏移bbox_preds = concat_preds(bbox_preds)return anchors, cls_preds, bbox_preds

我們創建一個模型實例,然后使用它對一個 256x256 像素的小批量圖像X執行前向傳播。

如本節前面部分所示,第一個模塊輸出特征圖的形狀為 32x32。 回想一下,第二到第四個模塊為高和寬減半塊,第五個模塊為全局匯聚層。 由于以特征圖的每個單元為中心有 4(size=3, ratio=2, 3+2-1)個錨框生成,因此在所有五個尺度下,每個圖像總共生成 (322 + 162 + 82 + 42 + 1) x4 = 5444個錨框。注意第五個模塊為全局匯聚層,所以直接縮小到(1x1)像素。

net = TinySSD(num_classes=1)
X = torch.zeros((32, 3, 256, 256))
anchors, cls_preds, bbox_preds = net(X)print('output anchors:', anchors.shape)
print('output class preds:', cls_preds.shape)
print('output bbox preds:', bbox_preds.shape)# 打印輸出
# output anchors: torch.Size([1, 5444, 4])
# output class preds: torch.Size([32, 5444, 2])
# output bbox preds: torch.Size([32, 21776])

13.7.2. 訓練模型

現在,我們將描述如何訓練用于目標檢測的單發多框檢測模型。

13.7.2.1. 讀取數據集和初始化

在這里插入圖片描述

13.7.2.2. 定義損失函數和評價函數

目標檢測有兩種類型的損失。 第一種有關錨框類別的損失:我們可以簡單地復用之前圖像分類問題里一直使用的交叉熵損失函數來計算; 第二種有關正類錨框偏移量的損失:預測偏移量是一個回歸問題。 但是,對于這個回歸問題,我們在這里不使用 3.1.3節中描述的平方損失,而是使用 L 1 L_1 L1? 范數損失,即預測值和真實值之差的絕對值掩碼變量bbox_masks令負類錨框和填充錨框不參與損失的計算。 最后,我們將錨框類別和偏移量的損失相加,以獲得模型的最終損失函數。

cls_loss = nn.CrossEntropyLoss(reduction='none')
bbox_loss = nn.L1Loss(reduction='none')def calc_loss(cls_preds, cls_labels, bbox_preds, bbox_labels, bbox_masks):batch_size, num_classes = cls_preds.shape[0], cls_preds.shape[2]cls = cls_loss(cls_preds.reshape(-1, num_classes),cls_labels.reshape(-1)).reshape(batch_size, -1).mean(dim=1)bbox = bbox_loss(bbox_preds * bbox_masks,bbox_labels * bbox_masks).mean(dim=1)return cls + bbox

我們可以沿用準確率評價分類結果。 由于偏移量使用了
范數損失,我們使用平均絕對誤差來評價邊界框的預測結果
。這些預測結果是從生成的錨框及其預測偏移量中獲得的。

def cls_eval(cls_preds, cls_labels):# 由于類別預測結果放在最后一維,argmax需要指定最后一維。return float((cls_preds.argmax(dim=-1).type(cls_labels.dtype) == cls_labels).sum())def bbox_eval(bbox_preds, bbox_labels, bbox_masks):return float((torch.abs((bbox_labels - bbox_preds) * bbox_masks)).sum())
13.7.2.3. 訓練模型

在訓練模型時,我們需要在模型的前向傳播過程中生成多尺度錨框(anchors),并預測其類別(cls_preds)和偏移量(bbox_preds)。 然后,我們根據標簽信息Y為生成的錨框標記類別(cls_labels)和偏移量(bbox_labels)。 最后,我們根據類別和偏移量的預測和標注值計算損失函數。為了代碼簡潔,這里沒有評價測試數據集。

num_epochs, timer = 20, d2l.Timer()
animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],legend=['class error', 'bbox mae'])
net = net.to(device)
for epoch in range(num_epochs):# 訓練精確度的和,訓練精確度的和中的示例數# 絕對誤差的和,絕對誤差的和中的示例數metric = d2l.Accumulator(4)net.train()for features, target in train_iter:timer.start()trainer.zero_grad()X, Y = features.to(device), target.to(device)# 生成多尺度的錨框,為每個錨框預測類別和偏移量anchors, cls_preds, bbox_preds = net(X)# 為每個錨框標注類別和偏移量bbox_labels, bbox_masks, cls_labels = d2l.multibox_target(anchors, Y)# 根據類別和偏移量的預測和標注值計算損失函數l = calc_loss(cls_preds, cls_labels, bbox_preds, bbox_labels,bbox_masks)l.mean().backward()trainer.step()metric.add(cls_eval(cls_preds, cls_labels), cls_labels.numel(),bbox_eval(bbox_preds, bbox_labels, bbox_masks),bbox_labels.numel())cls_err, bbox_mae = 1 - metric[0] / metric[1], metric[2] / metric[3]animator.add(epoch + 1, (cls_err, bbox_mae))
print(f'class err {cls_err:.2e}, bbox mae {bbox_mae:.2e}')
print(f'{len(train_iter.dataset) / timer.stop():.1f} examples/sec on 'f'{str(device)}')

13.7.3. 預測目標

在這里插入圖片描述
在這里插入圖片描述

13.7.4. 小結

  • 單發多框檢測是一種多尺度目標檢測模型。基于基礎網絡塊和各個多尺度特征塊,單發多框檢測生成不同數量和不同大小的錨框,并通過預測這些錨框的類別和偏移量檢測不同大小的目標。
  • 在訓練單發多框檢測模型時,損失函數是根據錨框的類別和偏移量的預測及標注值計算得出的。

13.8. 區域卷積神經網絡(R-CNN)系列

除了 13.7節中描述的單發多框檢測之外, 區域卷積神經網絡(region-based CNN或regions with CNN features,R-CNN) (Girshick et al., 2014)也是將深度模型應用于目標檢測的開創性工作之一。 本節將介紹R-CNN及其一系列改進方法:快速的R-CNN(Fast R-CNN) (Girshick, 2015)、更快的R-CNN(Faster R-CNN) (Ren et al., 2015)和掩碼R-CNN(Mask R-CNN) (He et al., 2017)。 限于篇幅,我們只著重介紹這些模型的設計思路。

13.8.1. R-CNN

R-CNN首先從輸入圖像中選取若干(例如2000個)提議區域(如錨框也是一種選取方法),并標注它們的類別和邊界框(如偏移量)。 (Girshick et al., 2014)然后,用卷積神經網絡對每個提議區域進行前向傳播以抽取其特征。 接下來,我們用每個提議區域的特征來預測類別和邊界框
在這里插入圖片描述
圖13.8.1展示了R-CNN模型。具體來說,R-CNN包括以下四個步驟:

  1. 對輸入圖像使用選擇性搜索來選取多個高質量的提議區域 (Uijlings et al., 2013)。這些提議區域通常是在多個尺度下選取的,并具有不同的形狀和大小。每個提議區域都將被標注類別和真實邊界框
  2. 選擇一個預訓練的卷積神經網絡,并將其在輸出層之前截斷。將每個提議區域變形為網絡需要的輸入尺寸,并通過前向傳播輸出抽取的提議區域特征
  3. 將每個提議區域的特征連同其標注的類別作為一個樣本。訓練多個支持向量機對目標分類,其中每個支持向量機用來判斷樣本是否屬于某一個類別
  4. 將每個提議區域的特征連同其標注的邊界框作為一個樣本,訓練線性回歸模型來預測真實邊界框

盡管R-CNN模型通過預訓練的卷積神經網絡有效地抽取了圖像特征,但它的速度很慢。 想象一下,我們可能從一張圖像中選出上千個提議區域,這需要上千次的卷積神經網絡的前向傳播來執行目標檢測。 這種龐大的計算量使得R-CNN在現實世界中難以被廣泛應用。

13.8.2. Fast R-CNN

R-CNN的主要性能瓶頸在于,對每個提議區域,卷積神經網絡的前向傳播是獨立的,而沒有共享計算。 由于這些區域通常有重疊,獨立的特征抽取會導致重復的計算。 Fast R-CNN (Girshick, 2015)對R-CNN的主要改進之一,是僅在整張圖象上執行卷積神經網絡的前向傳播
在這里插入圖片描述
圖13.8.2中描述了Fast R-CNN模型。它的主要計算如下:

  1. 與R-CNN相比,Fast R-CNN用來提取特征的卷積神經網絡的輸入是整個圖像,而不是各個提議區域。此外,這個網絡通常會參與訓練。設輸入為一張圖像,將卷積神經網絡的輸出的形狀記為 1 × c × h 1 × w 1 1 \times c \times h_1 \times w_1 1×c×h1?×w1?
  2. 假設選擇性搜索生成了 n 個提議區域。這些形狀各異的提議區域在卷積神經網絡的輸出上分別標出了形狀各異的興趣區域。然后,這些感興趣的區域需要進一步抽取出形狀相同的特征(比如指定高度 h 2 h_2 h2? 和寬度 w 2 w_2 w2?),以便于連結后輸出。為了實現這一目標,Fast R-CNN引入了興趣區域匯聚層(RoI pooling):將卷積神經網絡的輸出和提議區域作為輸入,輸出連結后的各個提議區域抽取的特征,形狀為 n × c × h 2 × w 2 n \times c \times h_2 \times w_2 n×c×h2?×w2?
  3. 通過全連接層將輸出形狀變換為 n × d n \times d n×d,其中超參數 d
    取決于模型設計;
  4. 預測 n 個提議區域中每個區域的類別和邊界框。更具體地說,在預測類別和邊界框時,將全連接層的輸出分別轉換為形狀為 n × q n \times q n×q(q是類別的數量)的輸出和形狀為 n × 4 n \times 4 n×4 的輸出。其中預測類別時使用softmax回歸。

在這里插入圖片描述
下面,我們演示了興趣區域匯聚層的計算方法。 假設卷積神經網絡抽取的特征X的高度和寬度都是4,且只有單通道。

import torch
import torchvisionX = torch.arange(16.).reshape(1, 1, 4, 4)
X
# 打印結果
# tensor([[[[ 0.,  1.,  2.,  3.],
#          [ 4.,  5.,  6.,  7.],
#          [ 8.,  9., 10., 11.],
#          [12., 13., 14., 15.]]]])

讓我們進一步假設輸入圖像的高度和寬度都是40像素,且選擇性搜索在此圖像上生成了兩個提議區域。 每個區域由5個元素表示:區域目標類別、左上角和右下角的 (x, y) 坐標。

rois = torch.Tensor([[0, 0, 0, 20, 20], [0, 0, 10, 30, 30]])

由于X的高和寬是輸入圖像高和寬的 1/10,因此,兩個提議區域的坐標先按spatial_scale乘以0.1然后,在X上分別標出這兩個興趣區域X[:, :, 0:3, 0:3]和X[:, :, 1:4, 0:4]。 最后,在 2x2 的興趣區域匯聚層中,每個興趣區域被劃分為子窗口網格,并進一步抽取相同形狀 2x2 的特征

torchvision.ops.roi_pool(X, rois, output_size=(2, 2), spatial_scale=0.1)# 打印結果
# tensor([[[[ 5.,  6.],[ 9., 10.]]],[[[ 9., 11.],[13., 15.]]]])

13.8.3. Faster R-CNN

為了較精確地檢測目標結果,Fast R-CNN模型通常需要在選擇性搜索中生成大量的提議區域。 Faster R-CNN (Ren et al., 2015)提出將選擇性搜索替換為區域提議網絡(region proposal network),從而減少提議區域的生成數量,并保證目標檢測的精度
在這里插入圖片描述
圖13.8.4描述了Faster R-CNN模型。 與Fast R-CNN相比,Faster R-CNN只將生成提議區域的方法從選擇性搜索改為了區域提議網絡,模型的其余部分保持不變。具體來說,區域提議網絡的計算步驟如下:

  1. 使用填充為1的 3x3 的卷積層變換卷積神經網絡的輸出,并將輸出通道數記為 c 。這樣,卷積神經網絡為圖像抽取的特征圖中的每個單元均得到一個長度為 c的新特征。
  2. 以特征圖的每個像素為中心,生成多個不同大小和寬高比的錨框并標注它們
  3. 使用錨框中心單元長度為 c 的特征,分別預測該錨框的二元類別(含目標還是背景)和邊界框
  4. 使用非極大值抑制,從預測類別為目標的預測邊界框中移除相似的結果。最終輸出的預測邊界框即是興趣區域匯聚層所需的提議區域。

值得一提的是,區域提議網絡作為Faster R-CNN模型的一部分,是和整個模型一起訓練得到的換句話說,Faster R-CNN的目標函數不僅包括目標檢測中的類別和邊界框預測,還包括區域提議網絡中錨框的二元類別和邊界框預測作為端到端訓練的結果,區域提議網絡能夠學習到如何生成高質量的提議區域,從而在減少了從數據中學習的提議區域的數量的情況下,仍保持目標檢測的精度

13.8.4. Mask R-CNN

如果在訓練集中還標注了每個目標在圖像上的像素級位置,那么Mask R-CNN (He et al., 2017)能夠有效地利用這些詳盡的標注信息進一步提升目標檢測的精度。

在這里插入圖片描述
如 圖13.8.5所示,Mask R-CNN是基于Faster R-CNN修改而來的。 具體來說,Mask R-CNN將興趣區域匯聚層替換為了 興趣區域對齊層,使用雙線性插值(bilinear interpolation)來保留特征圖上的空間信息,從而更適于像素級預測興趣區域對齊層的輸出包含了所有與興趣區域的形狀相同的特征圖。 它們不僅被用于預測每個興趣區域的類別和邊界框,還通過額外的全卷積網絡預測目標的像素級位置。 本章的后續章節將更詳細地介紹如何使用全卷積網絡預測圖像中像素級的語義。

13.8.5. 小結

  1. R-CNN對圖像選取若干提議區域,使用卷積神經網絡對每個提議區域執行前向傳播以抽取其特征,然后再用這些特征來預測提議區域的類別和邊界框。
  2. Fast R-CNN對R-CNN的一個主要改進:只對整個圖像做卷積神經網絡的前向傳播。它還引入了興趣區域匯聚層,從而為具有不同形狀的興趣區域抽取相同形狀的特征。
  3. Faster R-CNN將Fast R-CNN中使用的選擇性搜索替換為參與訓練的區域提議網絡,這樣后者可以在減少提議區域數量的情況下仍保證目標檢測的精度。
  4. Mask R-CNN在Faster R-CNN的基礎上引入了一個全卷積網絡,從而借助目標的像素級位置進一步提升目標檢測的精度。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86249.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86249.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86249.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

RSS解析并轉換為JSON的API集成指南

RSS解析并轉換為JSON的API集成指南 引言 隨著互聯網的發展,信息的傳播和共享變得越來越重要。RSS(簡易信息聚合)作為一種廣泛采用的格式,用于發布經常更新的內容,如博客文章、新聞頭條或播客等。它允許用戶訂閱這些內…

java數據類型詳解篇

1、8種基本數據類型 數據類型分類字節數內存位數是否最高位為符號位(0正數1負數)取值范圍(數值形式)取值說明byte整數類型18是-128 ~ 127-2^7 ~ 2^7 - 1 (冪形式)short整數類型216是-32,768 ~ 32,767-2^15…

vue 瀏覽器樣式警告:“unknown property name“

瀏覽器樣式警告:"unknown property name",但在部分電腦上的瀏覽器又是沒有問題的。 這個問題因為沒有安裝sass或者less,卻直接使用了他的語法,比如嵌套樣式: body {/* 按鈕 */.el-button {background: lin…

postgresql DDL腳本

在PostgreSQL中,數據定義語言(DDL)腳本用于定義、修改或刪除數據庫的結構。DDL 操作包括創建表、修改表結構、刪除表等。以下是幾種常見的DDL操作示例以及如何在腳本中實現它們。 1. 創建表 CREATE TABLE employees (employee_id SERIAL PR…

C#語言入門-task3 :C# 語言的面向對象技術

C# 面向對象編程技術概述 C# 是一種現代化的面向對象編程語言,提供了豐富的特性來支持面向對象的編程范式。以下是 C# 中面向對象編程的核心概念和技術: 核心概念 1. 類與對象 類是對象的藍圖,定義了對象的屬性和行為。對象是類的實例。 …

感知框2D反投是咋回事?

一、感知框:“2D 框反投” 是咋回事?(以自動駕駛識別車輛為例) 1. 核心邏輯:從圖像特征 “反推” 目標框 簡單說,先用算法在 2D 圖像里識別特征(比如車輛的輪廓、顏色、紋理)&#…

五分鐘了解@ExcelIgnoreUnannotated注解

ExcelIgnoreUnannotated 是 EasyExcel 框架中的一個注解,用于控制 Excel 導入/導出時對實體類字段的處理方式。它的作用如下: 核心功能 忽略未標注 ExcelProperty 的字段 當添加 ExcelIgnoreUnannotated 到類上時,EasyExcel 會 跳過所有未顯…

Windows電腦數據恢復終極指南:從原理到實戰

Windows電腦數據恢復終極指南:從原理到實戰 數據丟失是每個電腦用戶都可能遭遇的噩夢。本文將為您全面解析Windows平臺下的數據恢復技術,從基礎原理到高級技巧,幫助您在文件誤刪、格式化、系統崩潰等情況下找回寶貴數據。 一、數據恢復基礎…

【網絡入侵檢測】基于Suricata源碼分析應用協議識別實現

【作者主頁】只道當時是尋常 【專欄介紹】Suricata入侵檢測。專注網絡、主機安全,歡迎關注與評論。 1. 概要 👋 本文聚焦Suricata網絡安全引擎的協議解析器實現,詳細剖析HTTP、SSL/TLS、FTP、SSH、SMTP等協議的解析流程。 2. 源碼分析 2.1 H…

Nginx SSL/TLS協議棧中配置深度解析與實踐指南-優雅草卓伊凡

Nginx SSL/TLS協議棧中配置深度解析與實踐指南-優雅草卓伊凡 引言:SSL/TLS的重要性與Nginx配置挑戰 在當今互聯網環境中,SSL/TLS加密已成為網站安全的基本要求。根據Google透明度報告顯示,截至2023年,全球Chrome瀏覽器加載的網頁…

C++字符串的行輸入

1、字符串的輸入 下面用一個真實的示例來進行演示&#xff1a; #include<iostream> #include<string>int main() {using namespace std;const int ArSize 20;char name[ArSize];char dessert[ArSize];cout << "Enter your name:\n";cin >>…

征服分布式系統:阿里云 Linux 多機互聯與資源共享實戰指南

征服分布式系統&#xff1a;阿里云 Linux 多機互聯與資源共享實戰指南 文章目錄 征服分布式系統&#xff1a;阿里云 Linux 多機互聯與資源共享實戰指南一、分布式系統架構概述二、阿里云網絡基礎架構解析三、多機互聯基礎配置1. 環境準備2. 網絡連通性測試3. SSH 密鑰認證配置 …

AI三步診斷心理:比ChatGPT更懂人心

用人工智能(大語言模型)輔助心理治療的研究 解決心理治療中專業人員不足的問題,提出了一種叫“思維診斷”(DoT)的方法,讓AI通過三個步驟來識別患者的“認知扭曲”(也就是負面、不合理的思維模式)。 背景:心理治療的困境 全世界約八分之一的人有心理問題,但心理咨詢師…

C++【生存游戲】開發:荒島往事 第一期

字幕君已上線...... 副字幕君已上線...... 計數君已上線...... 彩色字幕君 ( 花了重金請來的 ) 已上線...... Doge智能系統已上線...... Doge:嗨嗨我又來了&#xff01; 觀眾們......已上線&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; OK LETS GO&am…

k8s強制刪除podpvpvc和nsnamespace

k8s如何強制刪除pod&pv&pvc和ns&namespace方法 namespace、pod、pv、pvc全部處于“Terminating”狀態時&#xff0c;此時的該名稱空間下的所有控制器都已經被刪除了&#xff0c;之所以出現pod、pvc、pv、ns無法刪除&#xff0c;那是因為kubelet 阻塞&#xff0c;有…

Python基礎--4--Python常用代碼示例

1、文件讀寫操作&#xff08;常用于日志處理、數據導入導出&#xff09; 1、代碼示例 &#xff08;1&#xff09;讀取文本文件內容 with open("data.txt", "r", encoding"utf-8") as f:content f.read()print(content)&#xff08;2&#xf…

單項循環鏈表及帶頭指針的鏈表

單項循環鏈表及其帶頭指針的鏈表 對于鏈表我們要仔細深入的學習它&#xff0c;為何呢&#xff0c;因為他是我們在后面學習非線性數據結構的基礎&#xff0c;像后面的樹&#xff0c;圖等結構都是由鏈表演變出來的&#xff0c;所以我們這篇博客繼續探究鏈表 帶頭指針的鏈表 我…

八股文——JAVA基礎:解釋下什么是面向對象?面向對象和面向過程的區別

面向對象和面向過程是編程的不同思想&#xff1a; 面向過程如c語言的編程形式&#xff0c;在編程時定義的是一個方法&#xff0c;然后后續執行只需要關注這個方法的作用&#xff0c;而不會將方法進行抽象&#xff0c;也就是只關注程序執行的過程細節。 面向對象如java&#x…

SuperMap iServer 關閉數據目錄(datacatalog)、地圖打印(webprinting)等服務

背景 漏洞掃描發現有部分低危 web 漏洞&#xff0c;項目又暫未使用數據目錄服務&#xff0c;所以最簡單的方案是直接關閉服務。 查閱文檔發現處理自動化服務可以修改webapps\iserver\WEB-INF\iserver-geoprocessing.xml 的 enable 屬性為 false 關閉&#xff0c;機器學習服務…

PyTorch 張量(Tensors)全面指南:從基礎到實戰

文章目錄 什么是張量&#xff1f;張量初始化方法1. 直接從數據創建2. 從 NumPy 數組轉換3. 基于現有張量創建4. 使用隨機值或常量 張量屬性張量操作設備轉移索引和切片連接張量算術運算單元素張量轉換 原地操作&#xff08;In-place Operations&#xff09;PyTorch 與 NumPy 互…