ターゲット検出用のSPPNET



Sppnet Target Detection




主な参考ブログ: http://www.cnblogs.com/marsggbo/p/8572846.html https://www.cnblogs.com/573177885qq/p/6071646.html
RCNNを理解した後、領域提案を通じて候補ボックスを生成した後、RCNNは特徴を抽出するために各候補ボックス画像をCNNネットワークに入力する必要があることがわかりました。たとえば、画像が選択的検索によって2000の候補領域を生成する場合、次のことが必要になります。特徴抽出は2000回実行されたため、効率に大きな影響がありました。さらに、Alex CNNネットワークの入力サイズは固定されているため、実際に作成する候補領域のサイズは実際に多様です。このように、入力ネットワークが特徴を抽出して同じサイズにする前に、候補領域に対してクロップ/ワープ操作を実行する必要があります。ただし、これらの操作によってグラフィックが歪む可能性があり、それによって結果に影響を与える可能性があります。 cnnネットワークが固定入力を必要とする理由は、主に、最終的に完全に接続された層の入力ニューロンの数を固定する必要があるためです。次に、最後の畳み込み層の背後にあるプーリング層を変更して、入力サイズが同じサイズの出力を持つことができないという関数を満たすことができるようにすることで、これを行うことができます。このように、畳み込みネットワークの入力サイズが異なっていても、完全に接続された層を入力すると、同じサイズに達する可能性があります。この機能を実装しているのはSPPNETです。次の図は、SPPNETの概略図です。

一般的なプロセス:

1.1。まず、選択的検索により、2000個の候補ウィンドウが検出される画像を検索されます。



2.特徴抽出段階。検出する画像全体をCNNに入力し、1回限りの特徴抽出を実行して特徴マップを取得し、特徴マップで各候補フレームの領域を見つけてから、各候補フレームにピラミッド空間プーリングを使用します。固定長の特徴ベクトルが抽出されます。 SPP-Netは画像全体に対して1回だけ特徴抽出を実行する必要があるため、R-CNNは各候補ボックスを入力してから、CNNに入ります。これにより、想像力が大幅に向上します。R-CNNはCNNを2000回トラバースするのと同等ですが、SPP-Netは1回だけトラバースする必要があるためです。最後に、SVMアルゴリズムは、R-CNNと同じ特徴ベクトルの分類と認識に使用されます。

予防:

1):



2)SPPNETで寸法を計算するための式

入力データサイズが上記と同じであると仮定します((107十一)。(10,7,11)、しかし、プーリングの数はに変更されます((44)。(4.4)

このとき、コアサイズは((3)。(2.3)、ステップサイズは((1)。(1,2)、プーリング後のマトリックスサイズは確かに656 ∗ 5←[行列のサイズを計算する簡単な方法:(7 = 2 + 1 * 5、11 = 3 + 2 * 4)]代わりに444 ∗ 4

だから問題は何ですか?パディングの存在を無視します

では、もう一度確認しましょう。
入力データサイズが上記と同じであると仮定します((107十一)。、プーリングの数は((44)。



カーネルサイズは((3)。、ストライドサイズは((3)。、つまりパディングは((11)。

マトリックスサイズの計算式を使用します。プール後のマトリックスサイズは次のとおりです。444 ∗ 4Pythonコードの実装(pyTorch)#coding=utf-8 import math import torch import torch.nn.functional as F # Build SPP layer (spatial pyramid pooling layer) class SPPLayer(torch.nn.Module): def __init__(self, num_levels, pool_type='max_pool'): super(SPPLayer, self).__init__() self.num_levels = num_levels self.pool_type = pool_type def forward(self, x): num, c, h, w = x.size() # num: number of samples c: number of channels h: height w: width for i in range(self.num_levels): level = i+1 kernel_size = (math.ceil(h / level), math.ceil(w / level)) stride = (math.ceil(h / level), math.ceil(w / level)) pooling = (math.floor((kernel_size[0]*level-h+1)/2), math.floor((kernel_size[1]*level-w+1)/2)) # Choose pooling method if self.pool_type == 'max_pool': tensor = F.max_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1) else: tensor = F.avg_pool2d(x, kernel_size=kernel_size, stride=stride, padding=pooling).view(num, -1) # Expand, stitch if (i == 0): x_flatten = tensor.view(num, -1) else: x_flatten = torch.cat((x_flatten, tensor.view(num, -1)), 1) return x_flatten