fpn.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. # copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve.
  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. """
  15. This code is refer from:
  16. https://github.com/whai362/PSENet/blob/python3/models/neck/fpn.py
  17. """
  18. import paddle.nn as nn
  19. import paddle
  20. import math
  21. import paddle.nn.functional as F
  22. class Conv_BN_ReLU(nn.Layer):
  23. def __init__(self, in_planes, out_planes, kernel_size=1, stride=1, padding=0):
  24. super(Conv_BN_ReLU, self).__init__()
  25. self.conv = nn.Conv2D(
  26. in_planes,
  27. out_planes,
  28. kernel_size=kernel_size,
  29. stride=stride,
  30. padding=padding,
  31. bias_attr=False,
  32. )
  33. self.bn = nn.BatchNorm2D(out_planes, momentum=0.1)
  34. self.relu = nn.ReLU()
  35. for m in self.sublayers():
  36. if isinstance(m, nn.Conv2D):
  37. n = m._kernel_size[0] * m._kernel_size[1] * m._out_channels
  38. m.weight = paddle.create_parameter(
  39. shape=m.weight.shape,
  40. dtype="float32",
  41. default_initializer=paddle.nn.initializer.Normal(
  42. 0, math.sqrt(2.0 / n)
  43. ),
  44. )
  45. elif isinstance(m, nn.BatchNorm2D):
  46. m.weight = paddle.create_parameter(
  47. shape=m.weight.shape,
  48. dtype="float32",
  49. default_initializer=paddle.nn.initializer.Constant(1.0),
  50. )
  51. m.bias = paddle.create_parameter(
  52. shape=m.bias.shape,
  53. dtype="float32",
  54. default_initializer=paddle.nn.initializer.Constant(0.0),
  55. )
  56. def forward(self, x):
  57. return self.relu(self.bn(self.conv(x)))
  58. class FPN(nn.Layer):
  59. def __init__(self, in_channels, out_channels):
  60. super(FPN, self).__init__()
  61. # Top layer
  62. self.toplayer_ = Conv_BN_ReLU(
  63. in_channels[3], out_channels, kernel_size=1, stride=1, padding=0
  64. )
  65. # Lateral layers
  66. self.latlayer1_ = Conv_BN_ReLU(
  67. in_channels[2], out_channels, kernel_size=1, stride=1, padding=0
  68. )
  69. self.latlayer2_ = Conv_BN_ReLU(
  70. in_channels[1], out_channels, kernel_size=1, stride=1, padding=0
  71. )
  72. self.latlayer3_ = Conv_BN_ReLU(
  73. in_channels[0], out_channels, kernel_size=1, stride=1, padding=0
  74. )
  75. # Smooth layers
  76. self.smooth1_ = Conv_BN_ReLU(
  77. out_channels, out_channels, kernel_size=3, stride=1, padding=1
  78. )
  79. self.smooth2_ = Conv_BN_ReLU(
  80. out_channels, out_channels, kernel_size=3, stride=1, padding=1
  81. )
  82. self.smooth3_ = Conv_BN_ReLU(
  83. out_channels, out_channels, kernel_size=3, stride=1, padding=1
  84. )
  85. self.out_channels = out_channels * 4
  86. for m in self.sublayers():
  87. if isinstance(m, nn.Conv2D):
  88. n = m._kernel_size[0] * m._kernel_size[1] * m._out_channels
  89. m.weight = paddle.create_parameter(
  90. shape=m.weight.shape,
  91. dtype="float32",
  92. default_initializer=paddle.nn.initializer.Normal(
  93. 0, math.sqrt(2.0 / n)
  94. ),
  95. )
  96. elif isinstance(m, nn.BatchNorm2D):
  97. m.weight = paddle.create_parameter(
  98. shape=m.weight.shape,
  99. dtype="float32",
  100. default_initializer=paddle.nn.initializer.Constant(1.0),
  101. )
  102. m.bias = paddle.create_parameter(
  103. shape=m.bias.shape,
  104. dtype="float32",
  105. default_initializer=paddle.nn.initializer.Constant(0.0),
  106. )
  107. def _upsample(self, x, scale=1):
  108. return F.upsample(x, scale_factor=scale, mode="bilinear")
  109. def _upsample_add(self, x, y, scale=1):
  110. return F.upsample(x, scale_factor=scale, mode="bilinear") + y
  111. def forward(self, x):
  112. f2, f3, f4, f5 = x
  113. p5 = self.toplayer_(f5)
  114. f4 = self.latlayer1_(f4)
  115. p4 = self._upsample_add(p5, f4, 2)
  116. p4 = self.smooth1_(p4)
  117. f3 = self.latlayer2_(f3)
  118. p3 = self._upsample_add(p4, f3, 2)
  119. p3 = self.smooth2_(p3)
  120. f2 = self.latlayer3_(f2)
  121. p2 = self._upsample_add(p3, f2, 2)
  122. p2 = self.smooth3_(p2)
  123. p3 = self._upsample(p3, 2)
  124. p4 = self._upsample(p4, 4)
  125. p5 = self._upsample(p5, 8)
  126. fuse = paddle.concat([p2, p3, p4, p5], axis=1)
  127. return fuse