123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- # -*- coding:utf-8 -*-
- # @author :adolf
- import torch.nn.functional as F
- from torch import nn, Tensor
- """
- out_channels=96时,和现有的fpn相比,这个fpn精度差不多,但是模型尺寸会大500k
- """
- class FeaturePyramidNetwork(nn.Module):
- def __init__(self, in_channels, out_channels=256):
- super(FeaturePyramidNetwork, self).__init__()
- self.inner_blocks = nn.ModuleList()
- self.layer_blocks = nn.ModuleList()
- self.out_channels = out_channels
- for in_channels in in_channels:
- if in_channels == 0:
- raise ValueError("in_channels=0 is currently not supported")
- inner_block_module = nn.Conv2d(in_channels, out_channels, 1)
- layer_block_module = nn.Conv2d(out_channels, out_channels, 3, padding=1)
- self.inner_blocks.append(inner_block_module)
- self.layer_blocks.append(layer_block_module)
- # initialize parameters now to avoid modifying the initialization of top_blocks
- for m in self.children():
- if isinstance(m, nn.Conv2d):
- nn.init.kaiming_uniform_(m.weight, a=1)
- nn.init.constant_(m.bias, 0)
- def get_result_from_inner_blocks(self, x, idx):
- num_blocks = 0
- for m in self.inner_blocks:
- num_blocks += 1
- if idx < 0:
- idx += num_blocks
- i = 0
- out = x
- for module in self.inner_blocks:
- if i == idx:
- out = module(x)
- i += 1
- return out
- def get_result_from_layer_blocks(self, x, idx):
- num_blocks = 0
- for m in self.layer_blocks:
- num_blocks += 1
- if idx < 0:
- idx += num_blocks
- i = 0
- out = x
- for module in self.layer_blocks:
- if i == idx:
- out = module(x)
- i += 1
- return out
- def forward(self, x):
- # unpack OrderedDict into two lists for easier handling
- # names = list(x.keys())
- # x = list(x.values())
- last_inner = self.get_result_from_inner_blocks(x[-1], -1)
- results = []
- results.append(self.get_result_from_layer_blocks(last_inner, -1))
- for idx in range(len(x) - 2, -1, -1):
- inner_lateral = self.get_result_from_inner_blocks(x[idx], idx)
- feat_shape = inner_lateral.shape[-2:]
- inner_top_down = F.interpolate(last_inner, size=feat_shape, mode="nearest")
- last_inner = inner_lateral + inner_top_down
- results.insert(0, self.get_result_from_layer_blocks(last_inner, idx))
- # make it back an OrderedDict
- # out = OrderedDict([(k, v) for k, v in zip(names, results)])
- out = results[0]
- return out
- class ExtraFPNBlock(nn.Module):
- def forward(self, results, x, names):
- pass
- class LastLevelMaxPool(ExtraFPNBlock):
- def forward(self, x, y, names):
- names.append("pool")
- x.append(F.max_pool2d(x[-1], 1, 2, 0))
- return x, names
- class LastLevelP6P7(ExtraFPNBlock):
- def __init__(self, in_channels, out_channels):
- super(LastLevelP6P7, self).__init__()
- self.p6 = nn.Conv2d(in_channels, out_channels, 3, 2, 1)
- self.p7 = nn.Conv2d(out_channels, out_channels, 3, 2, 1)
- for module in [self.p6, self.p7]:
- nn.init.kaiming_uniform_(module.weight, a=1)
- nn.init.constant_(module.bias, 0)
- self.use_P5 = in_channels == out_channels
- def forward(self, p, c, names):
- p5, c5 = p[-1], c[-1]
- x = p5 if self.use_P5 else c5
- p6 = self.p6(x)
- p7 = self.p7(F.relu(p6))
- p.extend([p6, p7])
- names.extend(["p6", "p7"])
- return p, names
|