這一節將從代碼庫裡面的demo.ipynb筆記本入手,來整體理解一下Mask RCNN的網絡架構。
2. Mask RCNN總覽下面的Figure1展示了這個工程中Mask RCNN的網絡結構示意圖,來自博主疊加態的貓:
Mask RCNN總覽,來自疊加態的貓博主這個結構圖裡面包含了很多細節,我們先大概理一下,後面在源碼詳解中會更詳細的說明:
首先是BackBone,可以看到原始圖片輸入後首先經過一個以ResNet101為基礎的FPN特徵金字塔網絡進行特徵的提取,並且可以發現這裡的實現和原始的FPN不完全相同,它在up-down的特徵上又做了一次rpn_class:[batch, num_rois, 2]
rpn_bbox:[batch, num_rois, (dy, dx, log(dh), log(dw))]
獲得了大量的候選區域之後,就可以將其送入Proposal篩選部分了,首先會根據前景得分對候選框排序,然後結合配置文件中指定的保留框數目來確定哪些框需要保留,為後面的NMS(非極大值抑制)做準備。再利用RPN的回歸結果來修正Anchors,需要注意的是這裡的anchors都是歸一化後的這就意味著修正之後還需要做邊界限制以防止越界。最後做一個NMS,刪減太多的話直接補上以達到配置文件要求的候選框數目即可。最終,這部分的輸出為rpn_rois: rpn_rois:[IMAGES_PER_GPU, num_rois, (y1, x1, y2, x2)]
接下來根據候選框的實際大小(歸一化的候選框需要映射回原圖大小)為候選框選擇合適的RPN特徵層,再利用ROI Align處理得到我們最終需要的大小相等一系列子圖。再對這些子圖進行獨立的分類和回歸,獲得的結果為mrcnn_class和mrcnn_bbox(偏移量):mrcnn_class: [batch, num_rois, NUM_CLASSES] classifier probabilities
mrcnn_bbox(deltas): [batch, num_rois, NUM_CLASSES, (dy, dx, log(dh), log(dw))]
最後,在分類回歸之後使用回歸結果對候選框進行修正,然後重新進行FPN特徵層選擇和ROI Align特徵提取,最後送入Mask分支,進行Mask生成。總的來說,最後網絡會輸出以下的張量:
# num_anchors, 每張圖片上生成的錨框數量
# num_rois, 每張圖片上由錨框篩選出的推薦區數量,
# # 由 POST_NMS_ROIS_TRAINING 或 POST_NMS_ROIS_INFERENCE 規定
# num_detections, 每張圖片上最終檢測輸出框,
# # 由 DETECTION_MAX_INSTANCES 規定
# detections, [batch, num_detections, (y1, x1, y2, x2, class_id, score)]
# mrcnn_class, [batch, num_rois, NUM_CLASSES] classifier probabilities
# mrcnn_bbox, [batch, num_rois, NUM_CLASSES, (dy, dx, log(dh), log(dw))]
# mrcnn_mask, [batch, num_detections, MASK_POOL_SIZE, MASK_POOL_SIZE, NUM_CLASSES]
# rpn_rois, [batch, num_rois, (y1, x1, y2, x2, class_id, score)]
# rpn_class, [batch, num_anchors, 2]
# rpn_bbox [batch, num_anchors, 4]
3. 代碼理解3.1 基礎設置首先導入需要用到的包,然後設置COCO數據集相關文件所在的根目錄,加載模型的路徑以及執行檢測的圖片路徑,代碼如下:
import os
import sys
import random
import math
import numpy as np
import skimage.io
import matplotlib
import matplotlib.pyplot as plt
# Root directory of the project
ROOT_DIR = os.path.abspath("../")
# Import Mask RCNN
sys.path.append(ROOT_DIR) # To find local version of the library
from mrcnn import utils
import mrcnn.model as modellib
from mrcnn import visualize
# 導入COCO數據集的配置
# 當我們導入一個模塊時:import xxx,默認情況下python解析器會搜索當前目錄、已安# 裝的內置模塊和第三方模塊,搜索路徑存放在sys模塊的path中.
sys.path.append(os.path.join(ROOT_DIR, "samples/coco/")) # To find local version
import coco
# 使用%matplotlib命令可以將matplotlib的圖表直接嵌入到Notebook之中,或者使用指定# 的界面庫顯示圖表,它有一個參數指定matplotlib圖表的顯示方式
%matplotlib inline
# Directory to save logs and trained model
MODEL_DIR = os.path.join(ROOT_DIR, "logs")
# Local path to trained weights file
COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5")
# Download COCO trained weights from Releases if needed
if not os.path.exists(COCO_MODEL_PATH):
utils.download_trained_weights(COCO_MODEL_PATH)
# Directory of images to run detection on
IMAGE_DIR = os.path.join(ROOT_DIR, "images")
3.2 網絡配置接下來需要進行配置設定,新定義了一個Class名為InferenceConfig繼承了coco.CocoConfig類,在demo.ipynb中我們直接使用COCO的預訓練模型所以使用它的設置就可以了。又因為我們這裡需要檢測的是單張圖片,所以需要重寫幾個配置參數,具體如下:
# 父類繼承了Config類,目的就是記錄配置,並在其基礎上添加了幾個新的屬性
class InferenceConfig(coco.CocoConfig):
# Set batch size to 1 since we'll be running inference on
# one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU
GPU_COUNT = 1
IMAGES_PER_GPU = 1
config = InferenceConfig()
config.display()再列印出配置看一下:
Configurations:
BACKBONE_SHAPES [[256 256]
[128 128]
[ 64 64]
[ 32 32]
[ 16 16]]
BACKBONE_STRIDES [4, 8, 16, 32, 64]
BATCH_SIZE 1
BBOX_STD_DEV [ 0.1 0.1 0.2 0.2]
DETECTION_MAX_INSTANCES 100
DETECTION_MIN_CONFIDENCE 0.5
DETECTION_NMS_THRESHOLD 0.3
GPU_COUNT 1
IMAGES_PER_GPU 1
IMAGE_MAX_DIM 1024
IMAGE_MIN_DIM 800
IMAGE_PADDING True
IMAGE_SHAPE [1024 1024 3]
LEARNING_MOMENTUM 0.9
LEARNING_RATE 0.002
MASK_POOL_SIZE 14
MASK_SHAPE [28, 28]
MAX_GT_INSTANCES 100
MEAN_PIXEL [ 123.7 116.8 103.9]
MINI_MASK_SHAPE (56, 56)
NAME coco
NUM_CLASSES 81
POOL_SIZE 7
POST_NMS_ROIS_INFERENCE 1000
POST_NMS_ROIS_TRAINING 2000
ROI_POSITIVE_RATIO 0.33
RPN_ANCHOR_RATIOS [0.5, 1, 2]
RPN_ANCHOR_SCALES (32, 64, 128, 256, 512)
RPN_ANCHOR_STRIDE 2
RPN_BBOX_STD_DEV [ 0.1 0.1 0.2 0.2]
RPN_TRAIN_ANCHORS_PER_IMAGE 256
STEPS_PER_EPOCH 1000
TRAIN_ROIS_PER_IMAGE 128
USE_MINI_MASK True
USE_RPN_ROIS True
VALIDATION_STEPS 50
WEIGHT_DECAY 0.0001
3.3 模型初始化接下來初始化模型,然後載入預訓練參數文件,代碼如下:
# 創建前向推理的模型對象
model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
# 加載在MS-COCO數據集上訓練的模型權重
model.load_weights(COCO_MODEL_PATH, by_name=True)注意,這裡模型設置為了inference 模式。然後下面定義了以下COCO的每個類別的目標的名字,太長了這裡就不貼了,可以自己查看代碼。
3.4 檢測單張圖片接下來就是加載單張圖片,調用模型的detect方法,即可輸出結果,最後使用輔助方法可視化結果,代碼如下:
# Load a random image from the images folder
file_names = next(os.walk(IMAGE_DIR))[2]
image = skimage.io.imread(os.path.join(IMAGE_DIR, random.choice(file_names)))
# Run detection
results = model.detect([image], verbose=1)
# Visualize results
r = results[0]
visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'],
class_names, r['scores'])獲得的結果圖展示:
示意圖的實例分割結果4. 小結這一節講了一些這個項目中Mask RCNN的整體架構,再通過demo.ipynb展示了如何加載一個COCO數據集上預訓練的模型預測一張示意圖片並將結果可視化出來。下一節,我們將從網絡結構看起,逐漸深入到項目的細節中。
5. 參考https://www.cnblogs.com/hellcat/p/9789879.html歡迎關注GiantPandaCV, 在這裡你將看到獨家的深度學習分享,堅持原創,每天分享我們學習到的新鮮知識。( • ̀ω•́ )✧
有對文章相關的問題,或者想要加入交流群,歡迎添加BBuf微信:
為了方便讀者獲取資料以及我們公眾號的作者發布一些Github工程的更新,我們成立了一個QQ群,二維碼如下,感興趣可以加入。
公眾號QQ交流群