vgg.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # Copyright (c) 2021 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. from paddle import ParamAttr
  16. import paddle.nn as nn
  17. import paddle.nn.functional as F
  18. from paddle.nn import Conv2D, BatchNorm, Linear, Dropout
  19. from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D
  20. from paddleseg.cvlibs import manager
  21. import ppmatting
  22. class ConvBlock(nn.Layer):
  23. def __init__(self, input_channels, output_channels, groups, name=None):
  24. super(ConvBlock, self).__init__()
  25. self.groups = groups
  26. self._conv_1 = Conv2D(
  27. in_channels=input_channels,
  28. out_channels=output_channels,
  29. kernel_size=3,
  30. stride=1,
  31. padding=1,
  32. weight_attr=ParamAttr(name=name + "1_weights"),
  33. bias_attr=False)
  34. if groups == 2 or groups == 3 or groups == 4:
  35. self._conv_2 = Conv2D(
  36. in_channels=output_channels,
  37. out_channels=output_channels,
  38. kernel_size=3,
  39. stride=1,
  40. padding=1,
  41. weight_attr=ParamAttr(name=name + "2_weights"),
  42. bias_attr=False)
  43. if groups == 3 or groups == 4:
  44. self._conv_3 = Conv2D(
  45. in_channels=output_channels,
  46. out_channels=output_channels,
  47. kernel_size=3,
  48. stride=1,
  49. padding=1,
  50. weight_attr=ParamAttr(name=name + "3_weights"),
  51. bias_attr=False)
  52. if groups == 4:
  53. self._conv_4 = Conv2D(
  54. in_channels=output_channels,
  55. out_channels=output_channels,
  56. kernel_size=3,
  57. stride=1,
  58. padding=1,
  59. weight_attr=ParamAttr(name=name + "4_weights"),
  60. bias_attr=False)
  61. self._pool = MaxPool2D(
  62. kernel_size=2, stride=2, padding=0, return_mask=True)
  63. def forward(self, inputs):
  64. x = self._conv_1(inputs)
  65. x = F.relu(x)
  66. if self.groups == 2 or self.groups == 3 or self.groups == 4:
  67. x = self._conv_2(x)
  68. x = F.relu(x)
  69. if self.groups == 3 or self.groups == 4:
  70. x = self._conv_3(x)
  71. x = F.relu(x)
  72. if self.groups == 4:
  73. x = self._conv_4(x)
  74. x = F.relu(x)
  75. skip = x
  76. x, max_indices = self._pool(x)
  77. return x, max_indices, skip
  78. class VGGNet(nn.Layer):
  79. def __init__(self, input_channels=3, layers=11, pretrained=None):
  80. super(VGGNet, self).__init__()
  81. self.pretrained = pretrained
  82. self.layers = layers
  83. self.vgg_configure = {
  84. 11: [1, 1, 2, 2, 2],
  85. 13: [2, 2, 2, 2, 2],
  86. 16: [2, 2, 3, 3, 3],
  87. 19: [2, 2, 4, 4, 4]
  88. }
  89. assert self.layers in self.vgg_configure.keys(), \
  90. "supported layers are {} but input layer is {}".format(
  91. self.vgg_configure.keys(), layers)
  92. self.groups = self.vgg_configure[self.layers]
  93. # matting的第一层卷积输入为4通道,初始化是直接初始化为0
  94. self._conv_block_1 = ConvBlock(
  95. input_channels, 64, self.groups[0], name="conv1_")
  96. self._conv_block_2 = ConvBlock(64, 128, self.groups[1], name="conv2_")
  97. self._conv_block_3 = ConvBlock(128, 256, self.groups[2], name="conv3_")
  98. self._conv_block_4 = ConvBlock(256, 512, self.groups[3], name="conv4_")
  99. self._conv_block_5 = ConvBlock(512, 512, self.groups[4], name="conv5_")
  100. # 这一层的初始化需要利用vgg fc6的参数转换后进行初始化,可以暂时不考虑初始化
  101. self._conv_6 = Conv2D(
  102. 512, 512, kernel_size=3, padding=1, bias_attr=False)
  103. self.init_weight()
  104. def forward(self, inputs):
  105. fea_list = []
  106. ids_list = []
  107. x, ids, skip = self._conv_block_1(inputs)
  108. fea_list.append(skip)
  109. ids_list.append(ids)
  110. x, ids, skip = self._conv_block_2(x)
  111. fea_list.append(skip)
  112. ids_list.append(ids)
  113. x, ids, skip = self._conv_block_3(x)
  114. fea_list.append(skip)
  115. ids_list.append(ids)
  116. x, ids, skip = self._conv_block_4(x)
  117. fea_list.append(skip)
  118. ids_list.append(ids)
  119. x, ids, skip = self._conv_block_5(x)
  120. fea_list.append(skip)
  121. ids_list.append(ids)
  122. x = F.relu(self._conv_6(x))
  123. fea_list.append(x)
  124. return fea_list
  125. def init_weight(self):
  126. if self.pretrained is not None:
  127. ppmatting.utils.load_pretrained_model(self, self.pretrained)
  128. @manager.BACKBONES.add_component
  129. def VGG11(**args):
  130. model = VGGNet(layers=11, **args)
  131. return model
  132. @manager.BACKBONES.add_component
  133. def VGG13(**args):
  134. model = VGGNet(layers=13, **args)
  135. return model
  136. @manager.BACKBONES.add_component
  137. def VGG16(**args):
  138. model = VGGNet(layers=16, **args)
  139. return model
  140. @manager.BACKBONES.add_component
  141. def VGG19(**args):
  142. model = VGGNet(layers=19, **args)
  143. return model