シーン解析 (シーン解析) はセマンティック セグメンテーションの重要な応用方向です. 一般的なセマンティック セグメンテーション タスクとは異なり, シーン解析は複雑な自然画像シーンのより大きなオブジェクト カテゴリの各ピクセルを分類する必要があります. シーン解析は自動的に広い範囲があります.運転やロボットの知覚などの方向へのアプリケーションの。しかし、自然シーンの複雑さ、セマンティック タグの多様性、およびターゲット オブジェクトの可変性のために、シーン解析問題の研究には多くの困難がありました。
シーン分析は一般に FCN と構造設計のための中空畳み込みネットワークに基づいています. その後の改善スキームには主に 2 つの方向性があります. 1 つはマルチスケールの特徴統合です. 学界の一般的な意見は, 深い特徴が画像の意味情報を抽出できるということです.しかし、位置情報が不足しています。マルチスケール機能を統合すると、モデル効果が大幅に向上します。もう 1 つは、画像セグメンテーション結果を最適化するための後処理に CRF を使用するなど、グラフ モデルの構造予測を組み合わせることです.これらの改善により、ピクセルの配置の問題をある程度軽減することができますが、それ以上の効果はまだ限定的です.複雑なイメージシーンです。セマンティック セグメンテーション ネットワークにグローバル情報を追加する設計は、前のセクションの ParseNet など、多くの研究でも言及されています。これは、FCN をグローバル平均プーリングで補うことによってセグメンテーション効果を向上させます。しかし、この種のグローバル情報は、150 のセマンティック カテゴリを含む ADE20K データセットなど、一部の複雑なシーン解析データセットへの影響を反映するには十分ではありません。要約すると、FCN には、複雑なシーン分析に関して次の 3 つの問題があります。
(1) ピクセル コンテキストが一致しません。セマンティック セグメンテーションでは, 画像のコンテキスト情報が非常に重要です. 異なるピクセル カテゴリ間で視覚パターンが共起することがよくあります. たとえば, 飛行機は通常, 滑走路または空中にのみ表示されますが, 道路には表示されません.・滑走路と空、3つのオブジェクト間の発生パターン。
(2) セマンティック ラベルの混乱。ADE20K データセットには、山と丘、建物と超高層ビルなど、意味的に類似したカテゴリが多数あります。FCN がこの紛らわしいカテゴリについて正確な判断を下すことは困難です。
(3) 小さなターゲット カテゴリを予測することは困難です。シーン分析では、ターゲット オブジェクトは任意のサイズになる可能性があるため、小さなターゲット オブジェクトの予測効果が非常に低い場合があります.たとえば、街灯や看板の認識では、FCN のパフォーマンスは非常に低くなります.
上記の問題に対応して、関連する学者は、空間ピラミッド プーリング (SPP) に基づくさまざまな画像領域に基づく、より広範なグローバル コンテキスト情報統合構造を提案しました: PSPNet、PSPNet を提案した論文は Pyramid Scene Parsing Network です。マルチスケールのコンテキスト構造の方向に設計します。PSPNet ネットワーク構造を図 1 に示します。
CNN ネットワークによって抽出された入力画像 (a) の特徴マップ (b) は、ピラミッド プーリング モジュール (Pyramid Pooling Module、PPM) に送信され、(c) では 4 つの異なるスケールが使用されることがわかります。グローバル プーリング (1*1、2*2、3*3、および 6*6) がダウンサンプリングされ、1*1 畳み込みと組み合わされて、次元削減されたコンテキスト情報表現が生成されます。次に、双一次補間を直接使用して低解像度の特徴マップをアップサンプリングし、ステージ (b) の特徴マップと接続して最終的なグローバル ピラミッド プーリング特徴を形成し、最後に一連の畳み込みを実行して最終的なセマンティック セグメンテーション予測結果を形成します。 (d). 上記の構造に基づいて, PSPNet はシーン解析タスクに効果的なグローバル コンテキストの事前情報を提供できます. ダイレクト グローバル プーリングと比較して, PPM はマルチスケールの情報表現を収集でき, 計算オーバーヘッドは FCN に比べてそれほど増加しません. さらに、PSPNet トレーニング中の勾配消失を防ぐための深い監視メカニズムとして、補助損失機能が追加されています。
PSPNet は ADE20K、PASCAL VOC 2012、Cityscapes データセットでテストされ、そのすべてが当時の SOTA のセグメンテーション レベルに達することができました。さらに、補助損失関数と事前トレーニング済みモデルに関して、十分なアブレーション研究が行われています。ADE20K データセットでの PSPNet の一連のテスト結果を図 2 に示します。3 つのテスト画像では、FCN は画像のコンテキストをキャプチャできません (最初の画像で水に浮かぶボートを車として認識します) が、PSPNet は良好なセグメンテーション効果を得ることができます。
次のコードは、PSPNet ネットワーク構造の簡単な実装プロセスを示しています。
### 定义PPM模块类
class _PyramidPoolingModule(nn.Module):
def __init__(self, in_dim, reduction_dim, setting):
super(_PyramidPoolingModule, self).__init__()
self.features = []
for s in setting:
self.features.append(nn.Sequential(
nn.AdaptiveAvgPool2d(s),
nn.Conv2d(in_dim, reduction_dim, kernel_size=1, bias=False),
nn.BatchNorm2d(reduction_dim, momentum=.95),
nn.ReLU(inplace=True)
))
self.features = nn.ModuleList(self.features)
# PPM前向计算流程
def forward(self, x):
x_size = x.size()
out = [x]
for f in self.features:
out.append(F.upsample(f(x), x_size[2:], mode='bilinear'))
out = torch.cat(out, 1)
return out
### 定义PSPNet类
class PSPNet(nn.Module):
def __init__(self, num_classes, use_aux=True):
super(PSPNet, self).__init__()
self.use_aux = use_aux
# 使用ResNet101作为预训练模型
resnet = models.resnet101()
self.layer0 = nn.Sequential(resnet.conv1, resnet.bn1, resnet.relu, resnet.maxpool)
self.layer1, self.layer2, self.layer3, self.layer4 = resnet.layer1, resnet.layer2, resnet.layer3, resnet.layer4
for n, m in self.layer3.named_modules():
if 'conv2' in n:
m.dilation, m.padding, m.stride = (2, 2), (2, 2), (1,1)
elif 'downsample.0' in n:
m.stride = (1, 1)
for n, m in self.layer4.named_modules():
if 'conv2' in n:
m.dilation, m.padding, m.stride = (4, 4), (4, 4), (1,1)
elif 'downsample.0' in n:
m.stride = (1, 1)
self.ppm = _PyramidPoolingModule(2048, 512, (1, 2, 3, 6))
self.final = nn.Sequential(
nn.Conv2d(4096, 512, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(512, momentum=.95),
nn.ReLU(inplace=True),
nn.Dropout(0.1),
nn.Conv2d(512, num_classes, kernel_size=1)
)
# 深监督辅助损失
if use_aux:
self.aux_logits = nn.Conv2d(1024, num_classes, kernel_size=1)
initialize_weights(self.aux_logits)
initialize_weights(self.ppm, self.final)
### PSPNet前向计算流程
def forward(self, x):
x_size = x.size()
x = self.layer0(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
if self.training and self.use_aux:
aux = self.aux_logits(x)
x = self.layer4(x)
x = self.ppm(x)
x = self.final(x)
if self.training and self.use_aux:
return F.upsample(x, x_size[2:], mode='bilinear'), F.upsample(aux, x_size[2:], mode='bilinear')
return F.upsample(x, x_size[2:], mode='bilinear')
過去のハイライト:
深層学習の論文を集中的に読む [5]: Attention UNet
深層学習の論文を集中的に読む [2]: UNet ネットワーク
深層学習の論文を集中的に読む [1]: FCN 完全な畳み込みネットワーク