Faster R-CNN 已經(jīng)過氣了嗎 | 附 PyTorch 實(shí)現(xiàn)
R-CNN 模型是為對(duì)象檢測(cè)而開發(fā)的深度學(xué)習(xí)方法之一。這種架構(gòu)被稱為基于區(qū)域的卷積神經(jīng)網(wǎng)絡(luò),通過結(jié)合卷積神經(jīng)網(wǎng)絡(luò)的力量和基于區(qū)域的方法,在對(duì)象檢測(cè)領(lǐng)域取得了重大進(jìn)展。R-CNN 用于檢測(cè)圖像中的對(duì)象類別以及這些對(duì)象的邊界框。由于直接在包含多個(gè)對(duì)象的圖像上運(yùn)行 CNN 可能很困難,因此開發(fā)了 R-CNN 架構(gòu)來克服這些問題。

R-CNN 通常使用支持向量機(jī) (SVM) 進(jìn)行分類過程。對(duì)于每個(gè)類別,訓(xùn)練一個(gè)單獨(dú)的 SVM 來確定區(qū)域提議是否包含該類別的一個(gè)實(shí)例。在訓(xùn)練期間,正例被定義為包含類別實(shí)例的區(qū)域,而負(fù)例則由不包含這些示例的區(qū)域組成。這種架構(gòu)遵循兩階段過程:第一階段識(shí)別可能的對(duì)象區(qū)域;第二階段通過分類這些區(qū)域并細(xì)化其邊界來識(shí)別對(duì)象。
在 R-CNN 模型之后,開發(fā)了 Fast R-CNN,然后是 Faster R-CNN 架構(gòu)。在本文中,我們將討論 Faster R-CNN 架構(gòu)。Ross Girshick 及其同事介紹了 Faster R-CNN 架構(gòu),并在文章 [1] 中討論了技術(shù)細(xì)節(jié)。
Faster R-CNN 使用區(qū)域提議網(wǎng)絡(luò) (RPN)。Faster R-CNN 架構(gòu)由兩層組成。
- 區(qū)域提議網(wǎng)絡(luò) (RPN):RPN 是一個(gè)深度的卷積神經(jīng)網(wǎng)絡(luò),用于推薦區(qū)域。它接受任何大小的輸入,并根據(jù)對(duì)象得分揭示可能屬于一系列對(duì)象的矩形。它通過在卷積層創(chuàng)建的特征圖上移動(dòng)一個(gè)小網(wǎng)絡(luò)來提出這一建議。RPN 層由錨框組成。錨框用于檢測(cè)圖像中的不同大小的對(duì)象。因此,它們的大小可能不同。在將圖像輸入 RPN 層之前,可以使用 VGG 或任何 CNN 層 Alexnet、Resnet、Imagenet 作為準(zhǔn)備層。
 - Fast R-CNN:RPN 生成的計(jì)算被插入到 Fast R-CNN 架構(gòu)中,并通過分類器估計(jì)對(duì)象的類別,并通過回歸器估計(jì)邊界框。
 
可以在視覺 [2] 中詳細(xì)檢查用于通用對(duì)象檢測(cè)的領(lǐng)先框架的高級(jí)圖。

在我們的工作中,我們將使用 ResNet-50 架構(gòu)。ResNet 是用于許多計(jì)算機(jī)視覺任務(wù)的經(jīng)典神經(jīng)網(wǎng)絡(luò)。它防止了網(wǎng)絡(luò)深化時(shí)的退化。為了在 ResNet 模型中實(shí)現(xiàn)更快的訓(xùn)練,使用了瓶頸塊。
如果您沒有必要的硬件,可以在 Google Colab 上更快地執(zhí)行您的工作。為了演示如何使用 Google Colab,這個(gè)項(xiàng)目是使用 Colab 進(jìn)行的。
讓我們添加 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上傳到我們將執(zhí)行對(duì)象檢測(cè)的 Google Drive。讓我們編寫將 Google Colab 連接到 Google Drive 的代碼。
from google.colab import drive
drive.mount('/gdrive')
%cd /gdrive讓我們調(diào)用我們將執(zhí)行對(duì)象檢測(cè)的圖像。
test_img = Image.open("My Drive/traffic.jpg")
test_img讓我們解釋一下我們認(rèn)為的代碼的下一個(gè)階段中兩個(gè)重要階段的概念:Compose 和 Tensor。
Compose 是一個(gè)結(jié)構(gòu),當(dāng)你想要在 Pytorch 轉(zhuǎn)換模塊中連續(xù)對(duì)圖像執(zhí)行多個(gè)工作時(shí),你可以使用它。如果你要執(zhí)行多個(gè)轉(zhuǎn)換,你可以在 Compase 中定義它。在這個(gè)階段,我們只為圖像應(yīng)用張量操作。
張量是 PyTorch 庫中使用的基本數(shù)據(jù)結(jié)構(gòu)。張量可以被認(rèn)為是向量和矩陣的更一般形式。RGB 圖像通常被表示為一個(gè) 3 通道張量,尺寸為 [3, 高度, 寬度]。例如,一個(gè) 128x128 像素的 RGB 圖像將由一個(gè)尺寸為 (3, 128, 128) 的張量表示。讓我們將我們的圖像轉(zhuǎn)換為張量。
import torchvision.transforms as transforms
#compase steps
transform = transforms.Compose([
    transforms.ToTensor(),  
])
#tensor transformation process
test_img_tensor = transform(test_img)
test_img_tensor在這些操作之后,我們將增加張量的大小。這個(gè)過程將單個(gè)圖像轉(zhuǎn)換為批量大小。unsqueeze(dim=0) 參數(shù)增加了另一個(gè)維度。
下一步,讓我們執(zhí)行批量操作。在 Pytorch 中,模型通常同時(shí)處理多個(gè)圖像,因此它們被分組到一個(gè)名為批量的圖像張量列表中。讓我們創(chuàng)建一個(gè)名為 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 架構(gòu)以及在此架構(gòu)基礎(chǔ)上的 FPN。作為參數(shù),pretrained=True 啟用了以前訓(xùn)練過的權(quán)重的加載。這樣模型就可以用 ImageNet 或 COCO 數(shù)據(jù)集進(jìn)行訓(xùn)練。我們將在研究中使用 COCO 數(shù)據(jù)集。
model.eval() 命令用于將模型置于評(píng)估模式。模型已準(zhǔn)備好對(duì)數(shù)據(jù)進(jìn)行預(yù)測(cè)。
#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 數(shù)據(jù)集由微軟開發(fā),包含 330K 張圖像。[4]。它是用于計(jì)算機(jī)視覺任務(wù)(如對(duì)象檢測(cè)、圖像分割、對(duì)象檢測(cè)和對(duì)象識(shí)別)的數(shù)據(jù)集。(https://cocodataset.org/#home)每張圖像包含多個(gè)對(duì)象,并為每個(gè)對(duì)象提供了詳細(xì)的標(biāo)簽。例如,對(duì)于對(duì)象檢測(cè),每張圖像中的所有對(duì)象都被標(biāo)記,并為每個(gè)對(duì)象確定了邊界框。
另一個(gè)可以使用的廣泛數(shù)據(jù)集是 ImagNet 數(shù)據(jù)集。與 ImageNet 不同,COCO 數(shù)據(jù)集允許用多個(gè)特征(位置、大小、形狀、環(huán)境框、標(biāo)簽)對(duì)對(duì)象進(jìn)行標(biāo)記。因此,它是更復(fù)雜的計(jì)算機(jī)視覺任務(wù)的理想數(shù)據(jù)集。
# 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'
]讓我們將張量轉(zhuǎn)換為 NumPy 數(shù)組。我們執(zhí)行這一步的原因是,在數(shù)據(jù)處理和可視化操作中,流行的可視化庫(如 matplotlib)接受 NumPy 數(shù)組格式的數(shù)據(jù)。雖然像 PyTorch 這樣的深度學(xué)習(xí)庫使用張量,但這些數(shù)據(jù)必須轉(zhuǎn)換為 NumPy 格式以進(jìn)行可視化。在轉(zhuǎn)換過程中,squeeze 函數(shù)移除了張量的 1 維并將其壓縮,而 CPU 函數(shù)將張量移動(dòng)到 CPU(如果在 GPU 中)。Numpy 只允許基于 CPU 的操作。添加了必要的代碼以在軸上顯示 numpy 數(shù)據(jù)。
#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)讓我們通過添加邊界框和圍繞檢測(cè)到的對(duì)象的相應(yīng)標(biāo)簽來可視化它。在這個(gè)階段,按順序采取以下步驟:
- 使用 Zip 處理邊界框、標(biāo)簽和分?jǐn)?shù)
 - 坐標(biāo)分離
 - 獲取標(biāo)簽名稱
 - 繪制邊界框
 - 可視化標(biāo)簽和分?jǐn)?shù)
 - 關(guān)閉軸
 - 顯示圖像
 
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()圖像:

代碼輸出:
















 
 
 











 
 
 
 