天天看點

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

🔎大家好,我是Sonhhxg_柒,希望你看完之後,能對你有所幫助,不足請指正!共同學習交流🔎

📝個人首頁-Sonhhxg_柒的部落格_CSDN部落格 📃

🎁歡迎各位→點贊👍 + 收藏⭐️ + 留言📝​

📣系列專欄 - 機器學習【ML】 自然語言處理【NLP】  深度學習【DL】

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

 🖍foreword

✔說明⇢本人講解主要包括Python、機器學習(ML)、深度學習(DL)、自然語言處理(NLP)等内容。

如果你對這個系列感興趣的話,可以關注訂閱喲👋

文章目錄

物體檢測簡介

對象檢測方法

使用 YOLOv3 進行對象檢測

YOLOv3 與 OpenCV 的代碼示例

使用 Faster R-CNN 進行目标檢測

區域提案網絡

檢測網絡

使用 PyTorch 實作 Faster R-CNN

介紹圖像分割

使用 U-Net 進行語義分割

使用 Mask R-CNN 進行執行個體分割

使用 PyTorch 實作 Mask R-CNN

概括

在第 3 章,進階卷積網絡中,我們讨論了一些最流行和性能最好的卷積神經網絡(CNN) 楷模。為了關注每個網絡的架構細節,我們在分類問題的直接上下文中檢視了模型。在計算機視覺任務的領域中,分類相當簡單,因為它為圖像配置設定了一個标簽。在本章中,我們将把重點轉移到兩個更有趣的計算機視覺任務上——對象檢測和語義分割,而網絡架構将退居二線。可以說,這些任務比分類更複雜,因為模型必須對圖像有更全面的了解。它必須能夠檢測不同的對象以及它們在圖像上的位置。同時,任務的複雜性允許更多創造性的解決方案。在本章中,我們将讨論其中的一些。

本章将涵蓋以下主題:

  • 物體檢測簡介:
  • 對象檢測方法
  • YOLO
  • 更快的 R-CNN
  • 圖像分割:
  • 網絡
  • 掩碼 R-CNN

物體檢測簡介

對象檢測是在圖像或視訊中查找特定類别的對象執行個體的過程,例如人臉、汽車和樹木。與分類不同,對象檢測可以檢測多個對象以及它們在圖像中的位置。

對象檢測器将傳回檢測到的對象清單,其中包含每個對象的以下資訊:

  • 對象的類别(人、車、樹等)。
  • [0, 1] 範圍内的機率(或置信度分數),它傳達了檢測器對物體存在于該位置的置信度。這類似于正常分類器的輸出。
  • 對象所在的圖像矩形區域的坐标。這個 矩形 稱為邊界框。

我們可以在下面的照片中看到目标檢測算法的典型輸出。對象類型和置信度得分在每個邊界框上方:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

物體檢測器的輸出

接下來,讓我們概述解決對象檢測任務的不同方法。

對象檢測方法

在本節中,我們将概述 三種 方法:

  • 經典滑動視窗: 在這裡,我們将 使用 正常分類網絡(分類器)。這種方法可以用于任何類型的分類算法,但它相對較慢且容易出錯:
    1. 建構圖像金字塔:這是同一圖像的不同比例的組合(見下圖)。例如,每個縮放的圖像可以比前一個小兩倍。通過這種方式,我們将能夠檢測到物體,而不管它們在原始圖像中的大小。
    2. 在整個圖像上滑動分類器:也就是說,我們将使用圖像的每個位置作為分類器的輸入,結果将确定該位置中對象的類型。位置的邊界框就是我們用作輸入的圖像區域。
    3. 我們将為每個對象有多個重疊的邊界框:我們将使用一些啟發式方法将它們組合在一個預測中。

這是滑動視窗方法的示意圖:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

滑動視窗加圖像金字塔物體檢測

  • 兩階段檢測方法: 這些方法 非常 準确,但相對較慢。顧名思義,它們涉及兩個步驟:
    1. 一種特殊類型的 CNN,稱為區域提議網絡( RPN ),它掃描圖像并提出許多可能的邊界框,或感興趣的區域 ( RoI ),對象可能位于這些區域。但是,該網絡不檢測對象的類型,而隻檢測該區域中是否存在對象。
    2. 感興趣的區域被發送到第二階段進行對象分類,該階段确定每個邊界框中的實際對象。
  • 單階段(或單次)檢測方法: 在這裡,單個 CNN 生成對象類型和邊界框。與兩階段方法相比,這些方法通常更快,但準确性較低。

在下一節中,我們将介紹 YOLO——一種準确但高效的單階段檢測算法。

使用 YOLOv3 進行對象檢測

在本節中,我們将讨論一種最流行的檢測算法,稱為 YOLO。這個 名字 是流行格言的首字母縮寫,你隻活一次,它反映了算法的單階段性質。作者釋出 了三個 版本,對算法進行了增量改進。我們将隻讨論最新的 v3(有關更多詳細資訊,請參閱YOLOv3:增量改進,https ://arxiv.org/abs/1804.02767 )。

該算法從稱為Darknet-53的所謂骨幹網絡開始(在卷積層數之後)。它被訓練來對 ImageNet 資料集進行分類,就像第 3 章,進階卷積網絡中的網絡一樣。它是完全卷積的(沒有池化層)并使用殘差連接配接。

下圖顯示了主幹架構:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

                         Darknet-53 模型(來源:https://arxiv.org/abs/1804.02767)

一旦網絡經過訓練,它将作為接下來的目标檢測訓練階段的基礎。這是特征提取遷移學習的一個案例,我們在第 2 章“了解卷積網絡”中進行了描述。主幹的全連接配接層被新的随機初始化的卷積和全連接配接層替換。新的全連接配接層将在一次傳遞中輸出所有檢測到的對象的邊界框、對象類别和置信度分數。

例如,本節開頭的人行橫道上的人的圖像中的邊界框是使用單個網絡通道生成的。YOLOv3 預測三個不同尺度的框。該系統使用與特征金字塔網絡類似的概念從這些尺度中提取特征(有關更多資訊,請參閱用于對象檢測的特征金字塔網絡,https://arxiv.org/abs/1612.03144)。在檢測階段,網絡使用上下文中的常見對象(Microsoft COCO:Common Objects in Context,https : //arxiv.org/abs/1405.0312,http: //cocodataset.org)對象檢測資料集進行訓練。

接下來,讓我們看看 YOLO 是如何工作的:

  1. 将圖像分割成S × S單元格的網格(在下圖中,我們可以看到一個 3 × 3 的網格):
    • 網絡将每個網格單元的中心視為區域的中心,對象可能位于該區域的中心。
    • 一個對象可能完全位于一個單元格内。然後,它的邊界框将小于單元格。或者,它可以跨越多個單元格,并且邊界框會更大。YOLO 涵蓋了這兩種情況。
    • 該算法可以在錨框的幫助下檢測網格單元格中的多個對象(稍後會詳細介紹),但一個對象僅與一個單元格相關聯(一對一的關系)。也就是說,如果對象的邊界框覆寫多個單元格,我們會将對象與邊界框中心所在的單元格相關聯。例如,下圖中的兩個對象跨越多個單元格,但它們都被配置設定到中心單元格,因為它們的中心位于其中。
    • 一些單元格可能包含對象,而其他單元格可能不包含。我們隻對那些這樣做的人感興趣。

下圖顯示了一個 3 × 3 單元格網格,其中包含 2 個對象及其邊界框(虛線)。這兩個對象都與中間單元格相關聯,因為它們的邊界框的中心位于該單元格中:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

具有 3x3 單元格網格和 2 個對象的對象檢測 YOLO 示例

  1. Тhe 網絡将為每個網格單元輸出多個可能檢測到的對象。例如,如果網格是 3 × 3,那麼輸出将包含 9 個可能檢測到的對象。為了清楚起見,讓我們讨論單個網格單元/檢測到的對象的輸出資料(及其相應的标簽)。它是一個數組,其值為[b x , b y , b h , b w , p c , c 1 , c 2 , ..., c n ],其中的值如下:
    • b x , b y , b h , b w 描述物體邊界框,如果物體存在,則b x和b y是框中心的坐标。它們相對于圖像的大小在 [0, 1] 範圍内進行歸一化。也就是說,如果圖像的大小為 100 x 100 并且b x = 20和b y = 50,它們的歸一化值将是 0.2 和 0.5。基本上, b h和b w代表盒子的高度和寬度。 它們相對于網格單元進行了歸一化。如果邊界框大于單元格,則其值将大于 1。預測框參數是一個回歸任務。
    • p c 是 [0, 1] 範圍内的置信度分數。置信度分數的标簽是 0(不存在)或 1(存在),這使得這部分輸出成為分類任務。如果一個對象不存在,我們可以丢棄其餘的數組值。
    • c 1 , c 2 , ..., c n 是對象類的 one-hot 編碼。例如,如果我們有 car、person、tree、cat 和 dog 類,并且目前對象是 cat 類型,則其編碼将為[0, 0, 0, 1, 0]。如果我們有n 個可能的類别,則一個單元格的輸出數組的大小将為5 + n(在我們的示例中為 9)。

網絡輸出/标簽将包含S × S 個這樣的數組。例如,3 × 3 單元格網格和四個類别的 YOLO 輸出長度為3*3*9 = 81。

  1. 讓我們 解決在同一個單元格中有多個對象的場景。值得慶幸的是,YOLO 為這個問題提出了一個優雅的解決方案。我們将有多個候選框(稱為錨框或先驗),每個單元格的形狀略有不同。在下圖中,我們可以看到網格單元(正方形,不間斷的線)和兩個錨框——垂直和水準(虛線)。如果我們在同一個單元格中有多個對象,我們會将每個對象與一個錨框相關聯。相反,如果錨框沒有關聯的對象,則其置信度得分為零。這種安排也會改變網絡輸出。每個網格單元有多個輸出數組(每個錨框一個輸出數組)。為了擴充我們之前的示例,假設我們有一個3 × 3的單元格網格,每個單元格有 4 個類和 2 個錨框。然後,我們将有3*3*2 = 18 個輸出邊界框,總輸出長度為3*3*2*9 = 162。因為我們有固定數量的細胞(S × S ) 并且每個單元有固定數量的錨框,網絡輸出的大小不會随着檢測到的對象的數量而變化。相反,輸出将訓示對象是否存在于所有可能的錨框中。

在下圖中,我們可以看到一個帶有兩個錨框的網格單元:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

帶有兩個錨框(虛線)的網格單元(正方形,不間斷的線)

現在唯一的問題是如何在訓練期間為對象選擇合适的錨框(在推理期間,網絡将自行選擇)。我們将在Intersection over Union ( IoU ) 的幫助下做到這一點。這隻是對象邊界框/錨框的交集面積與其并集面積之間的比率:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

聯合交叉口

我們将每個對象的邊界框與所有錨框進行比較,并将對象配置設定給具有最高 IoU 的錨框。由于錨框具有不同的大小和形狀,IoU 確定将對象配置設定給與其在圖像上的足迹最相似的錨框。

  1. 現在我們(希望)知道 YOLO 是如何工作的,我們可以用它來進行預測。然而,網絡的輸出可能是有噪聲的——也就是說,輸出包括每個單元格的所有可能的錨框,無論其中是否存在 對象 。許多框将重疊并實際上預測相同的對象。我們将使用非最大抑制來消除噪聲。以下是它的工作原理:
    1. 丢棄所有置信度分數小于或等于 0.6 的邊界框。
    2. 從剩餘的邊界框中,選擇具有最高置信度分數的邊界框。
    3. 用我們在上一步中選擇的框丢棄任何 IoU >= 0.5 的框。

如果您擔心網絡輸出/groundtruth 資料會變得過于複雜或龐大,請不要擔心。CNN 與 ImageNet 資料集配合良好,該資料集有 1,000 個類别,是以有 1,000 個輸出。

有關 YOLO 的更多資訊,請檢視論文的原始序列:

  • 你隻看一次:統一的實時對象檢測( https://arxiv.org/abs/1506.02640 ) Joseph Redmon、Santosh Divvala、Ross Girshick 和 Ali Farhadi
  • YOLO9000:更好、更快、更強( https://arxiv.org/abs/1612.08242 ) 作者 Joseph Redmon 和 Ali Farhadi
  • YOLOv3: Joseph Redmon 和 Ali Farhadi的增量改進( https://arxiv.org/abs/1804.02767 )

現在我們已經介紹了 YOLO 算法的理論,在下一節中,我們将讨論如何在實踐中使用它。

YOLOv3 與 OpenCV 的代碼示例

在本節中,我們将示範如何 将 YOLOv3 對象檢測器與 OpenCV 結合使用。對于此示例,您需要opencv-python4.1.1 或更高版本以及 250 MB 的磁盤空間用于預訓練的 YOLO 網絡。讓我們從以下步驟開始:

1.從導入開始:

import os.path 

import cv2   # opencv import 
import numpy as np 
import requests
           

2.添加一些樣闆代碼,用于下載下傳和存儲多個配置和資料檔案。我們将從 YOLOv3 網絡配置yolo_config和開始weights,我們将使用它們來初始化net網絡。我們将使用 YOLO 作者的 GitHub 和個人網站來做到這一點:

# 下載下傳 YOLO 網絡配置檔案
# 我們會從 YOLO 作者的 github repo
yolo_config = 'yolov3.cfg'
if not os.path.isfile(yolo_config):
   url = 'https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg'
    r = requests.get(url)
    with open(yolo_config, 'wb') as f:
        f.write(r.content)

# 下載下傳 YOLO 淨權重
# 我們會從YOLO 作者的網站
yolo_weights = 'yolov3.weights'
if not os.path.isfile(yolo_weights):
    url = 'https://pjreddie.com/media/files/yolov3.weights'
    r = requests.get(url)
    with open(yolo_weights, 'wb') as f:
        f.write(r.content)

# 加載網絡
net = cv2.dnn.readNet(yolo_weights, yolo_config)
           

3.接下來,我們将下載下傳網絡可以檢測到的 COCO 資料集類的名稱。我們還将從檔案中加載它們。COCO 論文中提供的資料集包含 91 個類别。但是,網站上的資料集隻包含 80 個。YOLO 使用的是 80-category 版本:

# Download class names file
# Contains the names of the classes the network can detect
classes_file = 'coco.names'
if not os.path.isfile(classes_file):
    url = 'https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names'
    r = requests.get(url)
    with open(classes_file, 'wb') as f:
        f.write(r.content)

# load class names
with open(classes_file, 'r') as f:
    classes = [line.strip() for line in f.readlines()]
           

4.然後,從 Wikipedia 下載下傳測試圖像。我們還将從blob變量中的檔案加載圖像:

# Download object detection image
image_file = 'source_1.png'
if not os.path.isfile(image_file):
    url = "https://github.com/ivan-vasilev/advanced-deep-learning-with-python/blob/master/chapter04-detection-segmentation/source_1.png"
    r = requests.get(url)
    with open(image_file, 'wb') as f:
        f.write(r.content)

# read and normalize image
image = cv2.imread(image_file)
blob = cv2.dnn.blobFromImage(image, 1 / 255, (416, 416), (0, 0, 0), True, crop=False)
           

5.将圖像輸入網絡并進行推理:

# set as input to the net
net.setInput(blob)

# get network output layers
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]

# inference
# the network outputs multiple lists of anchor boxes,
# one for each detected class
outs = net.forward(output_layers)
           

6.周遊類和錨框并為下一步做準備:

# extract bounding boxes
class_ids = list()
confidences = list()
boxes = list()

# iterate over all classes
for out in outs:
    # iterate over the anchor boxes for each class
    for detection in out:
        # bounding box
        center_x = int(detection[0] * image.shape[1])
        center_y = int(detection[1] * image.shape[0])
        w, h = int(detection[2] * image.shape[1]), int(detection[3] * image.shape[0])
        x, y = center_x - w // 2, center_y - h // 2
        boxes.append([x, y, w, h])

        # confidence
        confidences.append(float(detection[4]))

        # class
        class_ids.append(np.argmax(detection[5:]))
           

7.使用非最大抑制去除噪聲。您可以嘗試使用不同的值來檢視檢測到的對象如何變化: score_threshold nms_threshold

# non-max suppression
ids = cv2.dnn.NMSBoxes(boxes, confidences, score_threshold=0.75, nms_threshold=0.5)
           

8.在圖像上繪制邊界框及其标題:

for i in ids:
    i = i[0]
    x, y, w, h = boxes[i]
    class_id = class_ids[i]

    color = colors[class_id]

    cv2.rectangle(img=image,
                  pt1=(round(x), round(y)),
                  pt2=(round(x + w), round(y + h)),
                  color=color,
                  thickness=3)

    cv2.putText(img=image,
                text=f"{classes[class_id]}: {confidences[i]:.2f}",
                org=(x - 10, y - 10),
                fontFace=cv2.FONT_HERSHEY_SIMPLEX,
                fontScale=0.8,
                color=color,
                thickness=2)
           

9.最後,我們可以使用以下代碼顯示檢測到的對象:

cv2.imshow("Object detection", image)
cv2.waitKey()
           

如果一切順利,此代碼塊将生成我們在對象檢測簡介部分開頭看到的相同圖像。

我們對 YOLO 的讨論到此結束。在下一節中,我們将介紹一個名為 Faster R-CNN 的兩階段目标檢測器(R-CNN 代表帶有 CNN 的區域)。

使用 Faster R-CNN 進行目标檢測

在本節中,我們将讨論一種稱為 Faster R-CNN 的兩階段目标檢測算法(Faster R-CNN:Towards Real-Time Object Detection with Region Proposal Networks,https://arxiv.org/abs/1506.01497)。它是早期兩階段檢測器 Fast R-CNN(https://arxiv.org/abs/1504.08083)和 R-CNN(用于準确對象檢測和語義分割的豐富特征層次結構,https://arxiv. org/abs/1311.2524)。

我們将首先概述 Faster R-CNN 的一般結構,如下圖所示:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

Faster R-CNN的結構;來源:https://arxiv.org/abs/1506.01497

在我們解釋算法時,讓我們記住這個數字。與 YOLO 一樣,Faster R-CNN 從在 ImageNet 上訓練的骨幹分類網絡開始,該網絡作為模型不同子產品的基礎。論文作者對 VGG16 和 ZF 網絡(Visualizing and Understanding Convolutional Networks , https://cs.nyu.edu/~fergus/papers/zeilerECCV2014.pdf )主幹進行了實驗。然而,最近的實作使用了更現代的架構,例如 ResNets。主幹網絡充當模型的其他兩個元件——區域提議網絡(RPN)和檢測網絡的主幹(明白嗎?)。在下一節中,我們将讨論 RPN。

區域提案網絡

在第一階段,RPN 将圖像(任意大小)作為輸入,并将輸出一組可能位于對象的矩形感興趣區域 (RoI)。RPN 本身是通過使用主幹模型的第一個p(VGG 為 13,ZF net 為 5 )卷積層建立的(參見上圖)。一旦輸入圖像傳播到最後一個共享卷積層,算法就會擷取該層的特征圖,并在特征圖的每個位置上滑動另一個小網絡。小網絡輸出對象是否存在于任何k個每個位置上的錨框(錨框的概念與 YOLO 中的相同)。下圖的左側圖像說明了這個概念,該圖顯示了RPN 的單個位置在最後一個卷積層的單個特征圖上滑動:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

 左:單個位置的 RPN 提案;右圖:使用 RPN 提議的示例檢測(标簽被人為增強)。來源: https ://arxiv.org/abs/1506.01497

小網絡完全連接配接到 所有輸入特征圖上相同位置的n × n區域(根據論文,n = 3 ) 。例如,如果最終卷積層有 512 個特征圖,那麼一個位置的小網絡輸入大小為 512 x 3 x 3 = 4,608。每個滑動視窗都映射到較低維(VGG 為 512,ZF 網絡為 256)向量。該向量本身用作以下兩個并行全連接配接層的輸入:

1.具有2k個單元的分類層,組織成k個 2 單元二進制 softmax 輸出。每個 softmax 的輸出表示對象是否位于k個錨框中的每一個中的置信度分數。論文将置信度分數稱為objectness,它衡量anchor box内容是否屬于一組對象與背景。在訓練過程中,與 YOLO 中一樣,根據 IoU 公式将對象配置設定給錨框。

2.具有4k個單元的回歸層,組織成k個 4 單元的 RoI 坐标。4個機關中的2個表示[0:1]範圍内RoI中心相對于整個圖像的坐标。其他兩個坐标代表區域的高度和寬度,相對于整個圖像(同樣,類似于 YOLO)。

該論文的作者嘗試了三種尺度和三種縱橫比,在每個位置上産生了九個可能的錨框。最終特征圖的典型 H × W 大小約為 2,400,即 2,400*9 = 21,600 個錨框。

理論上,我們将小網絡滑過最後一個卷積層的特征圖。然而,小淨重沿所有位置共享。是以,滑動可以實作為跨通道卷積。是以,網絡可以在單個圖像通道中為所有錨框生成輸出。這是對 Fast R-CNN 的改進,Fast R-CNN 需要對每個錨框進行單獨的網絡傳遞。

RPN 通過反向傳播和随機梯度下降進行訓練(真是令人驚訝!)。共享卷積層使用主幹網絡的權重進行初始化,其餘的則随機初始化。每個小批量的樣本都是從單個圖像中提取的,該圖像包含許多正(對象)和負(背景)錨框。兩種類型的采樣比例為 1:1。每個錨點都配置設定有一個二進制類标簽(是否為對象)。有兩種帶有正标簽的錨點:IoU 最高的anchor/anchors 與groundtruth box 重疊,或者與任何groundtruth box 的IoU 重疊高于0.7 的anchor。如果anchor的IoU比率低于0.3,則為該框配置設定負标簽。既不是正面也不是負面的錨不參與訓練。

由于 RPN 有兩個輸出層(分類和回歸),是以訓練使用以下複合成本函數:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

讓我們詳細讨論一下:

  • i是小批量中錨點的索引。
  • p i是分類輸出,代表anchor i作為對象的預測機率。注意p i *是相同的目标資料(0 或 1)。
  • t i是大小為 4 的回歸輸出向量,表示 RoI 參數。與 YOLO 一樣, t i *是相同的目标向量。
  • L cls是分類層的交叉熵損失。N cls 是一個歸一化項,等于小批量大小。
  • L reg是回歸損失。
    【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括
    ,其中 R 是平均絕對誤差(參見第 1 章中的成本函數部分 ,神經網絡的基本要素)。N reg是一個歸一化項,等于錨位置的總數(大約 2,400)。

 最後,在λ參數的幫助下,将成本函數的分類和回歸分量結合起來。由于N reg ~ 2400 和N cls = 256,λ設定為 10 以保持兩個損失之間的平衡。

檢測網絡

現在我們已經讨論了 RPN,讓我們關注檢測網絡。為此,我們将回到“使用 Faster R-CNN 進行對象檢測”部分開頭的圖表Faster R-CNN 的結構。讓我們回想一下,在第一階段,RPN 已經生成了 RoI 坐标。檢測網絡是一個正常分類器,它确定目前 RoI 中對象(或背景)的類型。RPN 和檢測網絡共享它們的第一個卷積層,從主幹網絡借用。但是檢測網絡還結合了來自 RPN 的建議區域,以及最後一個共享層的特征圖。

但是我們如何組合輸入呢?我們可以借助感興趣區域( RoI ) 最大池化來做到這一點,它是檢測網絡第二部分的第一層。下圖顯示了此操作的示例:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

具有 10 × 7 特征圖和 5 × 5 感興趣區域(藍色矩形)的2 × 2 RoI 最大池化示例

為了簡單起見,我們假設我們有一個10 × 7的特征圖和一個 RoI。正如我們在Region proposal network部分中了解到的,RoI 由其坐标、寬度和高度定義。該操作将這些參數轉換為特征圖上的實際坐标。在此示例中,區域大小為h × w = 5 × 5。RoI 最大池進一步由其輸出高度H和寬度W定義。在這個例子中,H × W = 2 × 2,但實際上值可能更大,例如 7 ×7. 該操作将h × w RoI 拆分為具有 ( h / H) × (w / W)子區域的網格。

正如我們從示例中看到的,子區域可能具有不同的大小。完成此操作後,通過取該區域的最大值,将每個子區域下采樣到單個輸出單元。換句話說,RoI pooling 可以将任意大小的輸入轉換為固定大小的輸出視窗。通過這種方式,轉換後的資料可以以一緻的格式在網絡中傳播。

正如我們在使用 Faster R-CNN的對象檢測部分中提到的,RPN 和檢測網絡共享它們的初始層。然而,他們以獨立的網絡開始他們的生活。教育訓練在四步過程中在兩者之間交替進行:

  1. 訓練 RPN,它使用主幹網絡的 ImageNet 權重進行初始化。
  2. 使用來自步驟 1的新訓練的 RPN 的建議來訓練檢測網絡。訓練還從 ImageNet 主幹網絡的權重開始。此時,兩個網絡不共享權重。
  3. 使用檢測網絡共享層來初始化 RPN 的權重。然後,再次訓練 RPN,但當機共享層并僅微調 RPN 特定層。這兩個網絡現在共享權重。
  4. 通過當機共享層和僅微調檢測網絡特定層來訓練檢測網絡。

現在我們已經介紹了 Faster R-CNN,在下一節中,我們将讨論如何借助預訓練的 PyTorch 模型在實踐中使用它。

使用 PyTorch 實作 Faster R-CNN

在本節中,我們将使用帶有 ResNet50 主幹的預訓練 PyTorch Faster R-CNN 進行對象檢測。此示例需要 PyTorch 1.3.1、0.4.2torchvision和python-opencv4.1.1:

1.我們将從導入開始:

import os.path

import cv2
import numpy as np
import requests
import torchvision
import torchvision.transforms as transforms
           

2.接下來,我們将繼續下載下傳輸入圖像,并在 COCO 資料集中定義類名。此步驟與我們在YOLOv3 with OpenCV 的 A 代碼示例部分中實作的步驟相同。下載下傳圖像的路徑存儲在 image_file = 'source_2.png'變量中,類名存儲在classes清單中。此實作使用完整的 91 個 COCO 類别。

3.我們将加載預訓練的 Faster R-CNN 模型,并将其設定為評估模式:

# load the pytorch model
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)

# set the model in evaluation mode
model.eval()
           

4.然後,我們将使用 OpenCV 讀取圖像檔案:

img = cv2.imread(image_file)
           

5.我們将定義 PyTorchtransform 序列,将圖像轉換為 PyTorch 相容的張量,并将其饋送到網絡。網絡輸出存儲在output變量中。正如我們在區域提議網絡部分中讨論的那樣,output它包含三個元件:boxes邊界框參數、classes對象類和scores置信度分數。模型内部應用了NMS,代碼中不需要做:

transform = transforms.Compose([transforms.ToPILImage(), transforms.ToTensor()])
nn_input = transform(img)
output = model([nn_input])
           

6.在繼續顯示檢測到的對象之前,我們将為 COCO 資料集的每個類定義一組随機顔色:

colors = np.random.uniform(0, 255, size=(len(classes), 3))
           

7.我們周遊每個邊界框并将其繪制在圖像上:

# iterate over the network output for all boxes
for box, box_class, score in zip(output[0]['boxes'].detach().numpy(),
                                 output[0]['labels'].detach().numpy(),
                                 output[0]['scores'].detach().numpy()):

    # filter the boxes by score
    if score > 0.5:
        # transform bounding box format
        box = [(box[0], box[1]), (box[2], box[3])]

        # select class color
        color = colors[box_class]

        # extract class name
        class_name = classes[box_class]

        # draw the bounding box
        cv2.rectangle(img=img, pt1=box[0], pt2=box[1], color=color, thickness=2)

        # display the box class label
        cv2.putText(img=img, text=class_name, org=box[0], 
                    fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=color, thickness=2)
           

繪制邊界框涉及以下步驟:

  • 過濾置信度分數小于 0.5 的框以防止噪聲檢測。
  • 邊界box參數(從 中提取)包含圖像上邊界框的左上角和右下角絕對(像素)坐标。它們僅在元組中進行轉換以适應 OpenCV 格式。 output['boxes']
  • 提取邊界框的類名和顔色。
  • 繪制邊界框和類名。

8.最後,我們可以用下面的代碼展示檢測結果:

cv2.imshow("Object detection", image)
cv2.waitKey()
           

此代碼将産生以下結果(還檢測到公共汽車上的乘客):

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

更快的 R-CNN 對象檢測

關于對象檢測的部分到此結束。總而言之,我們讨論了兩個最流行的檢測模型——YOLO 和 Faster R-CNN。在下一節中,我們将讨論圖像分割——您可以将其視為像素級别的分類。

介紹圖像分割

圖像 分割 是為圖像的每個像素 配置設定 類别标簽(例如人、汽車或樹)的過程。您可以将其視為分類,但在像素級别上——我們将分别對每個像素進行分類,而不是将整個圖像分類在一個标簽下。有兩種類型的分段:

  • 語義分割:這為每個像素配置設定一個類,但不區分對象執行個體。例如,以下螢幕截圖中的中間圖像顯示了一個語義分割掩碼,其中每輛車的像素具有相同的值。語義分割可以告訴我們一個像素是車輛的一部分,但不能區分兩輛車。
  • 執行個體分割:這為每個像素配置設定一個類并區分對象執行個體。例如,以下螢幕截圖中右側的圖像顯示了一個執行個體分割掩碼,其中每輛車都被分割為一個單獨的對象。

以下螢幕截圖顯示了語義和執行個體分割的示例:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

左:輸入圖像;中:語義分割;右:執行個體分割;來源:http://sceneparsing.csail.mit.edu/

為了訓練 分割 算法,我們需要一種特殊類型的真實資料,其中每張圖像的标簽都是圖像的分割版本。

分割圖像的最簡單方法是使用熟悉的滑動視窗技術,我們在“目标檢測方法”部分中對此進行了描述。也就是說,我們将使用正常分類器,并以步長 1 向任一方向滑動它。在獲得位置預測後,我們将擷取位于輸入區域中間的像素,然後我們将其配置設定給預測的類。可以預見的是,由于圖像中有大量像素(即使是 1024 × 1024 的圖像也有超過 100 萬像素),這種方法非常慢。值得慶幸的是,有更快、更準确的算法,我們将在以下部分讨論。

使用 U-Net 進行語義分割

我們将讨論的第一種分割方法稱為 U-Net(U-Net:用于生物醫學圖像分割的卷積網絡,https ://arxiv.org/abs/1505.04597 )。這個名字來源于網絡架構的可視化。U-Net 是一種全卷積網絡(FCN),之是以這麼稱呼是因為它隻包含卷積層,沒有任何全連接配接層。FCN 将整個圖像作為輸入,并一次輸出其分割圖。我們可以将 FCN 分成兩個虛拟元件(實際上,這隻是一個網絡):

  • 編碼器是網絡的第一部分。它類似于正常的 CNN,最後沒有完全連接配接的層。編碼器的作用是學習輸入圖像的高度抽象的表示(這裡沒有什麼新東西)。
  • 解碼器是網絡的第二部分。它在編碼器之後開始并将其用作輸入。解碼器的作用是将這些抽象表示轉換為分段的真實資料。為此,解碼器使用與編碼器相反的操作。這包括轉置卷積(與卷積相反)和反池化(與池化相反)。

有了這個介紹,這就是 U-Net 的所有榮耀:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

U-Net 架構;來源:https://arxiv.org/abs/1505.04597

每個藍色 框對應一個多通道特征圖。通道數在框的頂部表示,特征圖大小在框的左下角。白框代表複制的特征圖。箭頭表示不同的操作(也顯示在圖例上)。U的左邊部分是編碼器,右邊部分是解碼器。

接下來,讓我們分割(明白了嗎?)U-Net 子產品:

  • 編碼器:網絡将 572 × 572 RGB 圖像作為輸入。從那裡開始,它像正常的 CNN 一樣繼續,具有交替的卷積層和最大池化層。編碼器由以下層的四個塊組成。
    • 兩個連續的跨通道未填充的 3 × 3 卷積,步幅為 1。
    • 一個 2 × 2 最大池化層。
    • ReLU 激活。
    • 每個下采樣步驟都會使特征圖的數量翻倍。
    • 最終的編碼器卷積以 1,024 個 28 × 28 特征圖結束。
  • 解碼器:這與編碼器對稱。解碼器采用最裡面的 28 × 28 特征圖,同時上采樣并将它們轉換為 388 × 388 的分割圖。它包含四個上采樣塊:
    • 上采樣使用步長為 2 的 2 × 2 轉置卷積(第 2 章,了解卷積網絡),用綠色垂直箭頭表示。
    • 每個上采樣步驟的輸出與相應編碼器步驟的裁剪高分辨率特征圖(灰色水準箭頭)連接配接。裁剪是必要的,因為在每個卷積中都會丢失邊界像素。
    • 每個轉置卷積後跟兩個正常卷積以平滑擴充圖像。
    • 上采樣步驟将特征圖的數量減半。最終輸出使用 1×1 瓶頸卷積将 64 分量的特征圖張量映射到所需的類數。該論文的作者已經證明了細胞醫學圖像的二進制分割。
    • 網絡輸出是每個像素上的 softmax。也就是說,輸出包含與像素數一樣多的獨立 softmax 操作。一個像素的 softmax 輸出決定了像素類别。U-Net 像正常分類網絡一樣被訓練。然而,成本函數是 softmax 輸出在所有像素上的交叉熵損失的組合。

我們可以看到,由于網絡的有效(未填充)卷積,輸出分割圖小于輸入圖像(388 對 572)。但是,輸出地圖不是輸入圖像的重新縮放版本。相反,它與輸入相比具有一對一的比例,但僅覆寫輸入圖塊的中心部分。

如下圖所示:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

用于分割大圖像的重疊平鋪政策;來源: https ://arxiv.org/abs/1505.04597

未填充的卷積是必要的,是以網絡不會在分割圖的邊界處産生噪聲僞影。這使得使用所謂的重疊平鋪政策分割具有任意大尺寸的圖像成為可能。輸入圖像被分割成重疊的輸入圖塊,如上圖左側的圖塊。右圖小光區的分割圖需要左圖大光區(一瓦片)作為輸入。

下一個輸入圖塊與前一個圖塊重疊,使得它們的分割圖覆寫圖像的相鄰區域。為了預測圖像邊界區域的像素,通過鏡像輸入圖像來推斷缺失的上下文。在下一節中,我們将讨論 Mask R-CNN——一個模型,它擴充了 Faster R-CNN 的執行個體分割。

使用 Mask R-CNN 進行執行個體分割

Mask R-CNN ( https://arxiv.org/abs/1703.06870 ) 是 Faster R-CNN 用于執行個體分割的擴充。Faster R-CNN 對每個候選對象都有兩個輸出:邊界框參數和類标簽。除了這些,Mask R-CNN 添加了第三個輸出——一個 FCN,它為每個 RoI 生成一個二進制分割掩碼。下圖展示了Mask R-CNN的結構:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

掩碼 R-CNN

RPN 産生五個尺度和三個縱橫比的錨點。分割和分類路徑都使用 RPN 的 RoI 預測,但在其他方面互相獨立。分割路徑産生I m×m二進制分割掩碼,每個I類一個。在訓練或推理時,隻考慮與分類路徑的預測類相關的掩碼,其餘的被丢棄。類預測和分割是并行解耦的——分類路徑預測被分割對象的類,分割路徑決定掩碼。

Mask R-CNN 用更準确的 RoI 對齊層代替了 RoI 最大池化操作。RPN 将錨框中心及其高度和寬度輸出為四個浮點數。然後,RoI 池化層将它們轉換為整數特征圖單元坐标(量化)。此外,将 RoI 劃分為H × W bins 還涉及量化。Object detection with Faster R-CNN部分的 RoI 示例顯示 bin 具有不同的大小(3 × 3、3 × 2、2 × 3、2 ×2)。這兩個量化級别可能會在 RoI 和提取的特征之間引入錯位。下圖展示了 RoI 對齊如何解決這個問題:

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

投資回報率對齊示例;來源:https://arxiv.org/abs/1703.06870

虛線表示特征圖單元。中間有實線的區域是覆寫在特征圖上的2 × 2 RoI。請注意,它與單元格不完全比對。相反,它是根據沒有量化的RPN預測定位的。同樣,RoI 的一個單元格(黑點)與特征圖的一個特定單元格不比對。RoI 對齊操作使用相鄰單元的雙線性插值計算 RoI 單元的值。這樣,RoI align 比 RoI pooling 更準确。

在訓練時,如果 RoI 的 IoU 與 groundtruth box 至少為 0.5,則為 RoI 配置設定正标簽,否則為負标簽。掩碼目标是 RoI 與其關聯的真實掩碼之間的交集。隻有正的 RoI 參與分割路徑訓練。

使用 PyTorch 實作 Mask R-CNN

在本節中,我們将使用帶有 ResNet50 主幹的預訓練 PyTorch Mask R-CNN 進行執行個體分割。此示例需要 PyTorch 1.1.0、torchvision 0.3.0 和 OpenCV 3.4.2。此示例與我們在使用 PyTorch 實作更快的 R-CNN部分中實作的示例非常相似。是以,我們将省略部分代碼以避免重複。開始吧:

1.導入、classes和image_file與 Faster R-CNN 示例中的相同。

2.這兩個示例之間的第一個差別是我們将加載 Mask R-CNN 預訓練模型:

model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)
model.eval()
           

3.我們将輸入圖像輸入網絡并獲得output變量:

# read the image file
img = cv2.imread(image_file)

# transform the input to tensor
transform = transforms.Compose([transforms.ToPILImage(), transforms.ToTensor()])
nn_input = transform(img)
output = model([nn_input])
           

此外boxes,classes和scores,output包含預測分割掩碼的附加masks元件。

4.我們疊代蒙版并将它們覆寫在圖像上。圖像和掩碼是numpy數組,我們可以将疊加實作為矢量操作。我們将同時顯示邊界框和分割掩碼:

# iterate over the network output for all boxes
for mask, box, score in zip(output[0]['masks'].detach().numpy(),
                            output[0]['boxes'].detach().numpy(),
                            output[0]['scores'].detach().numpy()):

    # filter the boxes by score
    if score > 0.5:
        # transform bounding box format
        box = [(box[0], box[1]), (box[2], box[3])]

        # overlay the segmentation mask on the image with random color
        img[(mask > 0.5).squeeze(), :] = np.random.uniform(0, 255, size=3)

        # draw the bounding box
        cv2.rectangle(img=img,
                      pt1=box[0],
                      pt2=box[1],
                      color=(255, 255, 255),
                      thickness=2)
           

5.最後,我們可以顯示分割結果如下:

cv2.imshow("Object detection", img)
cv2.waitKey()
           

這個例子會産生右邊的圖像如下(左邊的原圖是為了對比):

【DL】第 4 章:目标檢測和圖像分割物體檢測簡介對象檢測方法使用 YOLOv3 進行對象檢測YOLOv3 與 OpenCV 的代碼示例使用 Faster R-CNN 進行目标檢測區域提案網絡檢測網絡使用 PyTorch 實作 Faster R-CNN介紹圖像分割使用 U-Net 進行語義分割使用 Mask R-CNN 進行執行個體分割使用 PyTorch 實作 Mask R-CNN概括

Mask R-CNN 執行個體分割

我們可以看到,每個分割掩碼僅在其邊界框内定義,其中分割掩碼的所有值都大于零。為了獲得屬于對象的實際像素,我們僅對分割置信度分數大于 0.5 的像素應用掩碼(此代碼片段是 Mask R-CNN 代碼示例的第 4 步的一部分):

img[(mask > 0.5).squeeze(), :] = np.random.uniform(0, 255, size=3)
           

本章專門讨論圖像分割的部分到此結束(實際上,它結束了本章本身)。

概括

在本章中,我們讨論了對象檢測和圖像分割。我們從 one-shot 檢測算法 YOLO 開始,然後我們繼續使用兩階段 Faster R-CNN 算法。接下來,我們讨論了語義分割網絡架構 U-Net。最後,我們讨論了 Mask R-CNN——Faster R-CNN 的擴充,用于執行個體分割。

在下一章中,我們将探索稱為生成模型的新型ML 算法。我們可以使用它們來生成新的内容,例如圖像。請繼續關注——它會很有趣!

繼續閱讀