hrfpn.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import paddle
  15. import paddle.nn.functional as F
  16. import paddle.nn as nn
  17. from ppdet.core.workspace import register
  18. from ..shape_spec import ShapeSpec
  19. __all__ = ['HRFPN']
  20. @register
  21. class HRFPN(nn.Layer):
  22. """
  23. Args:
  24. in_channels (list): number of input feature channels from backbone
  25. out_channel (int): number of output feature channels
  26. share_conv (bool): whether to share conv for different layers' reduction
  27. extra_stage (int): add extra stage for returning HRFPN fpn_feats
  28. spatial_scales (list): feature map scaling factor
  29. """
  30. def __init__(self,
  31. in_channels=[18, 36, 72, 144],
  32. out_channel=256,
  33. share_conv=False,
  34. extra_stage=1,
  35. spatial_scales=[1. / 4, 1. / 8, 1. / 16, 1. / 32]):
  36. super(HRFPN, self).__init__()
  37. in_channel = sum(in_channels)
  38. self.in_channel = in_channel
  39. self.out_channel = out_channel
  40. self.share_conv = share_conv
  41. for i in range(extra_stage):
  42. spatial_scales = spatial_scales + [spatial_scales[-1] / 2.]
  43. self.spatial_scales = spatial_scales
  44. self.num_out = len(self.spatial_scales)
  45. self.reduction = nn.Conv2D(
  46. in_channels=in_channel,
  47. out_channels=out_channel,
  48. kernel_size=1,
  49. bias_attr=False)
  50. if share_conv:
  51. self.fpn_conv = nn.Conv2D(
  52. in_channels=out_channel,
  53. out_channels=out_channel,
  54. kernel_size=3,
  55. padding=1,
  56. bias_attr=False)
  57. else:
  58. self.fpn_conv = []
  59. for i in range(self.num_out):
  60. conv_name = "fpn_conv_" + str(i)
  61. conv = self.add_sublayer(
  62. conv_name,
  63. nn.Conv2D(
  64. in_channels=out_channel,
  65. out_channels=out_channel,
  66. kernel_size=3,
  67. padding=1,
  68. bias_attr=False))
  69. self.fpn_conv.append(conv)
  70. def forward(self, body_feats):
  71. num_backbone_stages = len(body_feats)
  72. outs = []
  73. outs.append(body_feats[0])
  74. # resize
  75. for i in range(1, num_backbone_stages):
  76. resized = F.interpolate(
  77. body_feats[i], scale_factor=2**i, mode='bilinear')
  78. outs.append(resized)
  79. # concat
  80. out = paddle.concat(outs, axis=1)
  81. assert out.shape[
  82. 1] == self.in_channel, 'in_channel should be {}, be received {}'.format(
  83. out.shape[1], self.in_channel)
  84. # reduction
  85. out = self.reduction(out)
  86. # conv
  87. outs = [out]
  88. for i in range(1, self.num_out):
  89. outs.append(F.avg_pool2d(out, kernel_size=2**i, stride=2**i))
  90. outputs = []
  91. for i in range(self.num_out):
  92. conv_func = self.fpn_conv if self.share_conv else self.fpn_conv[i]
  93. conv = conv_func(outs[i])
  94. outputs.append(conv)
  95. fpn_feats = [outputs[k] for k in range(self.num_out)]
  96. return fpn_feats
  97. @classmethod
  98. def from_config(cls, cfg, input_shape):
  99. return {
  100. 'in_channels': [i.channels for i in input_shape],
  101. 'spatial_scales': [1.0 / i.stride for i in input_shape],
  102. }
  103. @property
  104. def out_shape(self):
  105. return [
  106. ShapeSpec(
  107. channels=self.out_channel, stride=1. / s)
  108. for s in self.spatial_scales
  109. ]