ターゲット検出の解析を高速化 R-CNN

序章

Faster R-CNN は、2016 年に Ross B. Girshick によって提案された 2 段階のターゲット検出アルゴリズムです。より高速な R-CNN は、特徴抽出、関心領域抽出のための領域提案ネットワーク、最終境界ボックス回帰と分類を 1 つのネットワークに統合し、ネットワーク全体のパフォーマンスを大幅に向上させます。
この記事では、Faster R-CNN を次の 4 つの側面から分析します。

  1. Conv 層: 高速化された R-CNN は、まず単純な conv+relu+pooling 層のセットを使用して、入力画像の特徴マップを抽出します。この機能マップは、後続の RPN 層と完全接続層で共有されます。
  2. 地域提案ネットワーク。有効領域提案の生成には RPN ネットワークが使用され、この層はソフトマックスによってアンカーが正 (背景) に属するか負 (前景) に属するかを判断し、バウンディング ボックス回帰を使用してアンカーを修正して正確な提案を取得します。
  3. ロイ・プーリング。この層は入力特徴マップと提案を収集し、これらの情報を合成した後、提案特徴マップを抽出して後続の完全に接続された層に送信します。
  4. 分類と回帰: 提案特徴マップを使用して提案のカテゴリを計算し、境界ボックス回帰を再度実行して最終的な正確な位置を取得します。

背骨

VGG16 を例として、Faster R-CNN のバックボーン構成を紹介します。バックボーンには conv、relu、pooling の 3 層があり、下図のように conv 層が 13 層、relu 層が 13 層、pooling 層が 4 層あります。
画像.png
すべての畳み込み層のパラメーター設定は同じです (kernel_size=3、pad=1、stride=1)。つまり、出力および入力の特徴マップ サイズは同じで、プーリング層のパラメーターは次のように設定されます。 kernel_size= 2、パッド = 0、ストライド = 2、つまり、出力サイズは入力サイズの 1/2 のみです。
バックボーン全体には 4 つのプーリング層が含まれているため、入力画像のサイズはM ∗ NM *Nであると想定されます。MNの場合、バックボーン推論後の出力特徴マップのサイズはM 16 ∗ N 16 \frac{M}{16}*\frac{N}{16} になり16M16N

地域提案ネットワーク(RPN)

画像特徴がバックボーンによって提供された後、入力画像は RPN ネットワークに入ります。具体的な結果は次の図に示されています: RPN ネットワークは分類と
画像.png
回帰の 2 つのブランチに分割されます。分類ブランチは sotfmax を使用してデフォルトの画像を分類します候補フレーム アンカーは正または負です。回帰分岐は、デフォルトの候補ボックスに対する実際のターゲット ボックスのオフセットを予測します。最後に、提案レイヤーはポジティブアンカーと対応する回帰オフセットを組み合わせて提案を取得します。
次の入力画像サイズはC = 3、H = 576、W = 1024 C=3、H = 576、W = 1024C=3 H=576 W=1024 の場合、バックボーンによって特徴が抽出された後の特徴マップのサイズは1x512x36x64(NCHW 配置) になります。

アンカー

Faster R-CNN では、異なるサイズと異なるアスペクト比の 9 つのアンカーが提供され、4 つの値(x 1 , y 1 , x 2 , y 2 ) (x_1,y_1,x_2,y_2) が含まれます。( ×1y1バツ2y2) は長方形の左上隅と右下隅の座標を表し、アンカーは次の図に示されています。

注意すべき点の 1 つは、Faster R-CNN のアンカーのサイズはネットワーク入力サイズに相対していること入力画像サイズをC = 3、H = 576、W = 1024 C=3、H = 576、W = 1024 とC=3 H=576 W=1024ケース、Faster R-CNN には合計が含まれます:
ceil ( 1024 / 16 ) ∗ ceil ( 576 / 16 ) ∗ 9 = 64 ∗ 36 ∗ 9 = 20736 ceil(1024/16)*ceil(576/16)*9 =64*36*9=20736セイル( 1024/16 ) _ _セイル( 576/16 ) _ _9=64369=20,736 個の
アンカー。以下の図に示すように、これらのアンカーはネットワーク入力に反映されます。アンカーごとに、オブジェクトが含まれているかどうかを判断するために分類ブランチが必要です。オブジェクトが含まれている場合は肯定的で、そうでない場合は否定的です。同時に、ターゲットとアンカーの実際の位置の間にオフセットがあるため、オフセットを予測するために回帰分岐が必要になります。
画像.png

ソフトマックスブランチ

バックボーンの後、特徴マップのサイズは です1x512x36x64。最初に 1×1 畳み込みを介して得られる特徴マップのサイズは です。1x18x36x64そのうち18=2*9、アンカーは 9 つあり、各アンカーは正または負の場合があります。
画像.png
次に、再形成操作が行われます。取得された特徴マップの次元は1x2x36*9x64主にソフトマックス分類の便宜のためであり、元の状態に戻すために再形成されます。分類ブランチの実装コード スニペットは次のとおりです。

# define bg/fg classifcation score layer
self.nc_score_out = len(self.anchor_scales) * len(self.anchor_ratios) * 2 # 2(bg/fg) * 9 (anchors)
self.RPN_cls_score = nn.Conv2d(512, self.nc_score_out, 1, 1, 0)		# 1×1卷积

def forward():		# 前向推理
	# get rpn classification score
    rpn_cls_score = self.RPN_cls_score(rpn_conv1)
	# reshape + softmax + reshape
    rpn_cls_score_reshape = self.reshape(rpn_cls_score, 2)
    rpn_cls_prob_reshape = F.softmax(rpn_cls_score_reshape, 1)
    rpn_cls_prob = self.reshape(rpn_cls_prob_reshape, self.nc_score_out)

sotfmax分類はポジティブアンカーを求めるものであり、最初に検出対象候補領域を抽出することに相当する。

回帰ブランチ

回帰分岐回帰では、アンカーとグランド トゥルースの間のオフセットが取得されるため、トレーニング フェーズでは、監視信号はアンカーと実際のフレーム ( tx 、 ty 、 tw 、 th ) (t_x、t_y、t_w 、 t_h)( t×tはいtt),その中tx , ty t_x,t_yt×tはいは中心点の平行移動値tw , th t_w,t_htt幅と高さのスケーリング値です。( tx 、 ty 、 tw 、 th ) (t_x,t_y,t_w,t_h)( t×tはいtt)は次のように計算されます:
tx = ( x − xa ) / wa ; ty = ( y − ya ) / ha t_x = (x - x_a)/w_a; t_y=(y-y_a)/h_at×=( ×バツ) / w;tはい=( yy) /時間
tw = log (w/wa) ; th = log ( h / ha ) t_w=log(w/w_a);t_h=log(h/h_a)t=l o g ( w / w) ;t=l o g ( h / h)
其中 x a , y a , w a , h a x_a,y_a,w_a,h_a バツywhアンカーの座標値です。回帰ブランチのコード スニペットは次のとおりです。

# define anchor box offset prediction layer
self.nc_bbox_out = len(self.anchor_scales) * len(self.anchor_ratios) * 4 # 4(coords) * 9 (anchors)
self.RPN_bbox_pred = nn.Conv2d(512, self.nc_bbox_out, 1, 1, 0)

def forward():
    # get rpn offsets to the anchor boxes
    rpn_bbox_pred = self.RPN_bbox_pred(rpn_conv1)

提案レイヤー

プロポーザル層は、ポジティブアンカーとそれに対応する回帰オフセットを通じて正確なプロポーザルを計算し、それを後続の RoI プーリング層に送信します。プロポーザルレイヤーの定義は次のとおりです。

# define proposal layer
self.RPN_proposal = _ProposalLayer(self.feat_stride, self.anchor_scales, self.anchor_ratios)
def forward():
    rois = self.RPN_proposal((rpn_cls_prob.data, rpn_bbox_pred.data, im_info, 
                              cfg_key))

プロポーザル層には、ソフトマックス ブランチと回帰ブランチの出力、および im_info の 3 つの入力があります。ここで、im_info=[M,N,scale_factor]、M と N はネットワークの入力次元、scale_factor は元のイメージ PxQ のスケーリング情報であり、MxN にサイズ変更されます。
プロポーザルレイヤーの実行プロセスは次のとおりです。

  1. 予備的なターゲット フレームを取得し、予測されたオフセットに従ってすべてのアンカーを回帰して予備的なターゲット フレームを取得します。
anchors = self._anchors.view(1, A, 4) + shifts.view(K, 1, 4)
anchors = anchors.view(1, K * A, 4).expand(batch_size, K * A, 4)

# Transpose and reshape predicted bbox transformations to get them
# into the same order as the anchors:

bbox_deltas = bbox_deltas.permute(0, 2, 3, 1).contiguous()
bbox_deltas = bbox_deltas.view(batch_size, -1, 4)
# Convert anchors into proposals via bbox transformations
proposals = bbox_transform_inv(anchors, bbox_deltas, batch_size)
  1. 画像の境界を超えるポジティブアンカーを削除します。
 # 2. clip predicted boxes to image
proposals = clip_boxes(proposals, im_info, batch_size)
  1. 入力された正のソフトマックス スコアを並べ替えて、最初の RPN_PRE_NMS_TOP_N アンカーを選択します。
# # 4. sort all (proposal, score) pairs by score from highest to lowest
_, order = torch.sort(scores_keep, 1, True)
if pre_nms_topN > 0 and pre_nms_topN < scores_keep.numel():
    order_single = order_single[:pre_nms_topN]
proposals_single = proposals_single[order_single, :]
scores_single = scores_single[order_single].view(-1,1)
  1. サイズが非常に小さいポジティブ アンカーを削除します。
  2. 残りのポジティブアンカーに対して NMS を実行します。
# 6. apply nms (e.g. threshold = 0.7)
# 7. take after_nms_topN (e.g. 300)
# 8. return the top proposals (-> RoIs top)

keep_idx_i = nms(torch.cat((proposals_single, scores_single), 1), nms_thresh, force_cpu=not cfg.USE_GPU_NMS)
keep_idx_i = keep_idx_i.long().view(-1)

if post_nms_topN > 0:
    keep_idx_i = keep_idx_i[:post_nms_topN]
proposals_single = proposals_single[keep_idx_i, :]
scores_single = scores_single[keep_idx_i, :]

提案層が出力する提案のターゲット情報は、入力画像 M×N に対して相対的なものとなります。

ROI プーリング

RoI プーリング層は、提案を収集し、提案に対応する特徴マップを計算して、後続のネットワークに入力する役割を果たします。2 つの入力があります。

  • 共有機能マップ。
  • RPN によって出力された提案ボックス (ネットワーク入力 M×N に対して)
# define anchor target layer
self.RPN_anchor_target = _AnchorTargetLayer(self.feat_stride, self.anchor_scales, self.anchor_ratios)
def forward():
    rpn_data = self.RPN_anchor_target((rpn_cls_score.data, gt_boxes, im_info, num_boxes))

RoI プーリングを使用する理由:
RPN によって出力される提案ボックスのサイズと形状が異なるため、トレーニング済みモデルの場合、入力と出力は固定サイズである必要があります。さまざまな形状のボックスの場合、Faster R-CNN は、RoI プーリングを使用してこの問題を解決することを提案しています。
RoI プーリングのワークフロー:
入力特徴マップが次の図に示されていると仮定します。
画像.png
特徴マップに投影された提案ボックスの位置は図に示されているとおりです。
画像.png
出力が 2×2 特徴マップであると仮定し、次に、投影領域が 2×2 セクションに分割され、取得:
画像.png
次に、各セクションに対して最大プーリングを実行し、取得:
画像.png
したがって、RoI プーリングは、異なるサイズの特徴マップを同じサイズの特徴マップにプールすることであり、これは、ネットワークの次の層。
通常、提案の位置はモデル回帰によって取得されるため、通常は浮動小数点数であり、プーリング後の特徴マップには固定サイズが必要です。このプロセスには 2 つの量子化があります。

  • 提案の境界を整数値の座標に量子化します。
  • 量子化された境界領域を平均して kxk 個のセクションに分割し、各セクションの境界を量子化します。

上記の 2 つの量子化の後、この時点で候補フレームは初期回帰位置から一定の偏差を持ち、この偏差は検出精度に影響します

分類と回帰

RoI プーリングによって出力された 7×7 特徴マップは分類子モジュールに送信され、各提案の特定のカテゴリが線形層とソフトマックスを通じて計算され、ターゲットの信頼度が出力され、提案の位置オフセットが計算されます。さらに、より正確なターゲット ボックスを回帰するための回帰数量を使用して取得されます。以下の図に示すように、
画像.png
Classifier モジュールのコードを以下に示します。これは VGG モデルの一部です。

self.classifier = nn.Sequential(
    nn.Linear(512 * 7 * 7, 4096),
    nn.ReLU(True),
    nn.Dropout(p=dropout),
    nn.Linear(4096, 4096),
    nn.ReLU(True),
    nn.Dropout(p=dropout),
)

全結合層とソフトマックス層は提案のカテゴリを決定し、対応する信頼度を出力します。

self.RCNN_cls_score = nn.Linear(4096, self.n_classes)
cls_prob = F.softmax(cls_score, 1)

完全に接続されたレイヤーを使用してオフセットを取得し、ターゲットの位置をさらに調整します。

self.RCNN_bbox_pred = nn.Linear(4096, 4 * self.n_classes) 

参考リンク

おすすめ

転載: blog.csdn.net/hello_dear_you/article/details/129309592