hrfpn.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # Copyright (c) 2019 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. from __future__ import absolute_import
  15. from __future__ import division
  16. from __future__ import print_function
  17. from collections import OrderedDict
  18. from paddle import fluid
  19. from paddle.fluid.param_attr import ParamAttr
  20. from ppdet.core.workspace import register
  21. __all__ = ['HRFPN']
  22. @register
  23. class HRFPN(object):
  24. """
  25. HRNet, see https://arxiv.org/abs/1908.07919
  26. Args:
  27. num_chan (int): number of feature channels
  28. pooling_type (str): pooling type of downsampling
  29. share_conv (bool): whethet to share conv for different layers' reduction
  30. spatial_scale (list): feature map scaling factor
  31. """
  32. def __init__(
  33. self,
  34. num_chan=256,
  35. pooling_type="avg",
  36. share_conv=False,
  37. spatial_scale=[1. / 64, 1. / 32, 1. / 16, 1. / 8, 1. / 4], ):
  38. self.num_chan = num_chan
  39. self.pooling_type = pooling_type
  40. self.share_conv = share_conv
  41. self.spatial_scale = spatial_scale
  42. return
  43. def get_output(self, body_dict):
  44. num_out = len(self.spatial_scale)
  45. body_name_list = list(body_dict.keys())
  46. num_backbone_stages = len(body_name_list)
  47. outs = []
  48. outs.append(body_dict[body_name_list[0]])
  49. # resize
  50. for i in range(1, len(body_dict)):
  51. resized = self.resize_input_tensor(body_dict[body_name_list[i]],
  52. outs[0], 2**i)
  53. outs.append(resized)
  54. # concat
  55. out = fluid.layers.concat(outs, axis=1)
  56. # reduction
  57. out = fluid.layers.conv2d(
  58. input=out,
  59. num_filters=self.num_chan,
  60. filter_size=1,
  61. stride=1,
  62. padding=0,
  63. param_attr=ParamAttr(name='hrfpn_reduction_weights'),
  64. bias_attr=False)
  65. # conv
  66. outs = [out]
  67. for i in range(1, num_out):
  68. outs.append(
  69. self.pooling(
  70. out, size=2**i, stride=2**i,
  71. pooling_type=self.pooling_type))
  72. outputs = []
  73. for i in range(num_out):
  74. conv_name = "shared_fpn_conv" if self.share_conv else "shared_fpn_conv_" + str(
  75. i)
  76. conv = fluid.layers.conv2d(
  77. input=outs[i],
  78. num_filters=self.num_chan,
  79. filter_size=3,
  80. stride=1,
  81. padding=1,
  82. param_attr=ParamAttr(name=conv_name + "_weights"),
  83. bias_attr=False)
  84. outputs.append(conv)
  85. for idx in range(0, num_out - len(body_name_list)):
  86. body_name_list.append("fpn_res5_sum_subsampled_{}x".format(2**(idx +
  87. 1)))
  88. outputs = outputs[::-1]
  89. body_name_list = body_name_list[::-1]
  90. res_dict = OrderedDict([(body_name_list[k], outputs[k])
  91. for k in range(len(body_name_list))])
  92. return res_dict, self.spatial_scale
  93. def resize_input_tensor(self, body_input, ref_output, scale):
  94. shape = fluid.layers.shape(ref_output)
  95. shape_hw = fluid.layers.slice(shape, axes=[0], starts=[2], ends=[4])
  96. out_shape_ = shape_hw
  97. out_shape = fluid.layers.cast(out_shape_, dtype='int32')
  98. out_shape.stop_gradient = True
  99. body_output = fluid.layers.resize_bilinear(
  100. body_input, scale=scale, out_shape=out_shape)
  101. return body_output
  102. def pooling(self, input, size, stride, pooling_type):
  103. pool = fluid.layers.pool2d(
  104. input=input,
  105. pool_size=size,
  106. pool_stride=stride,
  107. pool_type=pooling_type)
  108. return pool