Faster R-CNN 已經過氣了嗎 | 附 PyTorch 實現
R-CNN 模型是為對象檢測而開發的深度學習方法之一。這種架構被稱為基于區域的卷積神經網絡,通過結合卷積神經網絡的力量和基于區域的方法,在對象檢測領域取得了重大進展。R-CNN 用于檢測圖像中的對象類別以及這些對象的邊界框。由于直接在包含多個對象的圖像上運行 CNN 可能很困難,因此開發了 R-CNN 架構來克服這些問題。
R-CNN 通常使用支持向量機 (SVM) 進行分類過程。對于每個類別,訓練一個單獨的 SVM 來確定區域提議是否包含該類別的一個實例。在訓練期間,正例被定義為包含類別實例的區域,而負例則由不包含這些示例的區域組成。這種架構遵循兩階段過程:第一階段識別可能的對象區域;第二階段通過分類這些區域并細化其邊界來識別對象。
在 R-CNN 模型之后,開發了 Fast R-CNN,然后是 Faster R-CNN 架構。在本文中,我們將討論 Faster R-CNN 架構。Ross Girshick 及其同事介紹了 Faster R-CNN 架構,并在文章 [1] 中討論了技術細節。
Faster R-CNN 使用區域提議網絡 (RPN)。Faster R-CNN 架構由兩層組成。
- 區域提議網絡 (RPN):RPN 是一個深度的卷積神經網絡,用于推薦區域。它接受任何大小的輸入,并根據對象得分揭示可能屬于一系列對象的矩形。它通過在卷積層創建的特征圖上移動一個小網絡來提出這一建議。RPN 層由錨框組成。錨框用于檢測圖像中的不同大小的對象。因此,它們的大小可能不同。在將圖像輸入 RPN 層之前,可以使用 VGG 或任何 CNN 層 Alexnet、Resnet、Imagenet 作為準備層。
- Fast R-CNN:RPN 生成的計算被插入到 Fast R-CNN 架構中,并通過分類器估計對象的類別,并通過回歸器估計邊界框。
可以在視覺 [2] 中詳細檢查用于通用對象檢測的領先框架的高級圖。
在我們的工作中,我們將使用 ResNet-50 架構。ResNet 是用于許多計算機視覺任務的經典神經網絡。它防止了網絡深化時的退化。為了在 ResNet 模型中實現更快的訓練,使用了瓶頸塊。
如果您沒有必要的硬件,可以在 Google Colab 上更快地執行您的工作。為了演示如何使用 Google Colab,這個項目是使用 Colab 進行的。
讓我們添加 PyTorch 庫以及 torchvision 和任何其他所需庫等必要的庫。[3]
import torch
import torchvision
from torchvision.models.detection import fasterrcnn_resnet50_fpn
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
上傳到我們將執行對象檢測的 Google Drive。讓我們編寫將 Google Colab 連接到 Google Drive 的代碼。
from google.colab import drive
drive.mount('/gdrive')
%cd /gdrive
讓我們調用我們將執行對象檢測的圖像。
test_img = Image.open("My Drive/traffic.jpg")
test_img
讓我們解釋一下我們認為的代碼的下一個階段中兩個重要階段的概念:Compose 和 Tensor。
Compose 是一個結構,當你想要在 Pytorch 轉換模塊中連續對圖像執行多個工作時,你可以使用它。如果你要執行多個轉換,你可以在 Compase 中定義它。在這個階段,我們只為圖像應用張量操作。
張量是 PyTorch 庫中使用的基本數據結構。張量可以被認為是向量和矩陣的更一般形式。RGB 圖像通常被表示為一個 3 通道張量,尺寸為 [3, 高度, 寬度]。例如,一個 128x128 像素的 RGB 圖像將由一個尺寸為 (3, 128, 128) 的張量表示。讓我們將我們的圖像轉換為張量。
import torchvision.transforms as transforms
#compase steps
transform = transforms.Compose([
transforms.ToTensor(),
])
#tensor transformation process
test_img_tensor = transform(test_img)
test_img_tensor
在這些操作之后,我們將增加張量的大小。這個過程將單個圖像轉換為批量大小。unsqueeze(dim=0) 參數增加了另一個維度。
下一步,讓我們執行批量操作。在 Pytorch 中,模型通常同時處理多個圖像,因此它們被分組到一個名為批量的圖像張量列表中。讓我們創建一個名為 images 變量的批量。
#Increasing tensor dimensions
test_img_tensor = test_img_tensor.unsqueeze(dim=0)
test_img_tensor.shape
#batch steps
images = [test_img_tensor]
在我們的工作中,我們將使用 Faster R-CNN 模型、Resnet-50 架構以及在此架構基礎上的 FPN。作為參數,pretrained=True 啟用了以前訓練過的權重的加載。這樣模型就可以用 ImageNet 或 COCO 數據集進行訓練。我們將在研究中使用 COCO 數據集。
model.eval() 命令用于將模型置于評估模式。模型已準備好對數據進行預測。
#Let's load the pre-trained model
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
model.eval()
preds = object_detection_model(test_img_tensor)
print(preds)
COCO 數據集由微軟開發,包含 330K 張圖像。[4]。它是用于計算機視覺任務(如對象檢測、圖像分割、對象檢測和對象識別)的數據集。(https://cocodataset.org/#home)每張圖像包含多個對象,并為每個對象提供了詳細的標簽。例如,對于對象檢測,每張圖像中的所有對象都被標記,并為每個對象確定了邊界框。
另一個可以使用的廣泛數據集是 ImagNet 數據集。與 ImageNet 不同,COCO 數據集允許用多個特征(位置、大小、形狀、環境框、標簽)對對象進行標記。因此,它是更復雜的計算機視覺任務的理想數據集。
# COCO dataset
COCO_INSTANCE_CATEGORY_NAMES = [
'','person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'boat',
'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',
'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella',
'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite',
'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle',
'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich',
'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
'potted plant', 'bed', 'dining table', 'laptop', 'mouse', 'remote',
'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book',
'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'
]
讓我們將張量轉換為 NumPy 數組。我們執行這一步的原因是,在數據處理和可視化操作中,流行的可視化庫(如 matplotlib)接受 NumPy 數組格式的數據。雖然像 PyTorch 這樣的深度學習庫使用張量,但這些數據必須轉換為 NumPy 格式以進行可視化。在轉換過程中,squeeze 函數移除了張量的 1 維并將其壓縮,而 CPU 函數將張量移動到 CPU(如果在 GPU 中)。Numpy 只允許基于 CPU 的操作。添加了必要的代碼以在軸上顯示 numpy 數據。
#Numpy conversion and image generation processes
img = test_img_tensor.squeeze().detach().cpu().numpy()
img = img.transpose(1, 2, 0)
fig, ax = plt.subplots(1, figsize=(12, 9))
ax.imshow(img)
讓我們通過添加邊界框和圍繞檢測到的對象的相應標簽來可視化它。在這個階段,按順序采取以下步驟:
- 使用 Zip 處理邊界框、標簽和分數
- 坐標分離
- 獲取標簽名稱
- 繪制邊界框
- 可視化標簽和分數
- 關閉軸
- 顯示圖像
for box, label, score in zip(preds[0]['boxes'].detach().cpu().numpy(),
preds[0]['labels'].detach().cpu().numpy(),
preds[0]['scores'].detach().cpu().numpy()):
x1, y1, x2, y2 = box
label_name = COCO_INSTANCE_CATEGORY_NAMES[label]
ax.add_patch(patches.Rectangle((x1, y1), x2 - x1, y2 - y1, linewidth=1, edgecolor='r', facecolor='none'))
plt.text(x1, y1, f'{label_name} {score:.2f}', color='white', fontsize=8, bbox=dict(facecolor='red', alpha=0.5))
plt.axis('off')
plt.show()
圖像:
代碼輸出: