rec_resnet_32.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. # copyright (c) 2022 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/hikopensource/DAVAR-Lab-OCR/davarocr/davar_rcg/models/backbones/ResNet32.py
  17. """
  18. from __future__ import absolute_import
  19. from __future__ import division
  20. from __future__ import print_function
  21. import paddle.nn as nn
  22. __all__ = ["ResNet32"]
  23. conv_weight_attr = nn.initializer.KaimingNormal()
  24. class ResNet32(nn.Layer):
  25. """
  26. Feature Extractor is proposed in FAN Ref [1]
  27. Ref [1]: Focusing Attention: Towards Accurate Text Recognition in Neural Images ICCV-2017
  28. """
  29. def __init__(self, in_channels, out_channels=512):
  30. """
  31. Args:
  32. in_channels (int): input channel
  33. output_channel (int): output channel
  34. """
  35. super(ResNet32, self).__init__()
  36. self.out_channels = out_channels
  37. self.ConvNet = ResNet(in_channels, out_channels, BasicBlock, [1, 2, 5, 3])
  38. def forward(self, inputs):
  39. """
  40. Args:
  41. inputs: input feature
  42. Returns:
  43. output feature
  44. """
  45. return self.ConvNet(inputs)
  46. class BasicBlock(nn.Layer):
  47. """Res-net Basic Block"""
  48. expansion = 1
  49. def __init__(
  50. self, inplanes, planes, stride=1, downsample=None, norm_type="BN", **kwargs
  51. ):
  52. """
  53. Args:
  54. inplanes (int): input channel
  55. planes (int): channels of the middle feature
  56. stride (int): stride of the convolution
  57. downsample (int): type of the down_sample
  58. norm_type (str): type of the normalization
  59. **kwargs (None): backup parameter
  60. """
  61. super(BasicBlock, self).__init__()
  62. self.conv1 = self._conv3x3(inplanes, planes)
  63. self.bn1 = nn.BatchNorm2D(planes)
  64. self.conv2 = self._conv3x3(planes, planes)
  65. self.bn2 = nn.BatchNorm2D(planes)
  66. self.relu = nn.ReLU()
  67. self.downsample = downsample
  68. self.stride = stride
  69. def _conv3x3(self, in_planes, out_planes, stride=1):
  70. """
  71. Args:
  72. in_planes (int): input channel
  73. out_planes (int): channels of the middle feature
  74. stride (int): stride of the convolution
  75. Returns:
  76. nn.Layer: Conv2D with kernel = 3
  77. """
  78. return nn.Conv2D(
  79. in_planes,
  80. out_planes,
  81. kernel_size=3,
  82. stride=stride,
  83. padding=1,
  84. weight_attr=conv_weight_attr,
  85. bias_attr=False,
  86. )
  87. def forward(self, x):
  88. residual = x
  89. out = self.conv1(x)
  90. out = self.bn1(out)
  91. out = self.relu(out)
  92. out = self.conv2(out)
  93. out = self.bn2(out)
  94. if self.downsample is not None:
  95. residual = self.downsample(x)
  96. out += residual
  97. out = self.relu(out)
  98. return out
  99. class ResNet(nn.Layer):
  100. """Res-Net network structure"""
  101. def __init__(self, input_channel, output_channel, block, layers):
  102. """
  103. Args:
  104. input_channel (int): input channel
  105. output_channel (int): output channel
  106. block (BasicBlock): convolution block
  107. layers (list): layers of the block
  108. """
  109. super(ResNet, self).__init__()
  110. self.output_channel_block = [
  111. int(output_channel / 4),
  112. int(output_channel / 2),
  113. output_channel,
  114. output_channel,
  115. ]
  116. self.inplanes = int(output_channel / 8)
  117. self.conv0_1 = nn.Conv2D(
  118. input_channel,
  119. int(output_channel / 16),
  120. kernel_size=3,
  121. stride=1,
  122. padding=1,
  123. weight_attr=conv_weight_attr,
  124. bias_attr=False,
  125. )
  126. self.bn0_1 = nn.BatchNorm2D(int(output_channel / 16))
  127. self.conv0_2 = nn.Conv2D(
  128. int(output_channel / 16),
  129. self.inplanes,
  130. kernel_size=3,
  131. stride=1,
  132. padding=1,
  133. weight_attr=conv_weight_attr,
  134. bias_attr=False,
  135. )
  136. self.bn0_2 = nn.BatchNorm2D(self.inplanes)
  137. self.relu = nn.ReLU()
  138. self.maxpool1 = nn.MaxPool2D(kernel_size=2, stride=2, padding=0)
  139. self.layer1 = self._make_layer(block, self.output_channel_block[0], layers[0])
  140. self.conv1 = nn.Conv2D(
  141. self.output_channel_block[0],
  142. self.output_channel_block[0],
  143. kernel_size=3,
  144. stride=1,
  145. padding=1,
  146. weight_attr=conv_weight_attr,
  147. bias_attr=False,
  148. )
  149. self.bn1 = nn.BatchNorm2D(self.output_channel_block[0])
  150. self.maxpool2 = nn.MaxPool2D(kernel_size=2, stride=2, padding=0)
  151. self.layer2 = self._make_layer(
  152. block, self.output_channel_block[1], layers[1], stride=1
  153. )
  154. self.conv2 = nn.Conv2D(
  155. self.output_channel_block[1],
  156. self.output_channel_block[1],
  157. kernel_size=3,
  158. stride=1,
  159. padding=1,
  160. weight_attr=conv_weight_attr,
  161. bias_attr=False,
  162. )
  163. self.bn2 = nn.BatchNorm2D(self.output_channel_block[1])
  164. self.maxpool3 = nn.MaxPool2D(kernel_size=2, stride=(2, 1), padding=(0, 1))
  165. self.layer3 = self._make_layer(
  166. block, self.output_channel_block[2], layers[2], stride=1
  167. )
  168. self.conv3 = nn.Conv2D(
  169. self.output_channel_block[2],
  170. self.output_channel_block[2],
  171. kernel_size=3,
  172. stride=1,
  173. padding=1,
  174. weight_attr=conv_weight_attr,
  175. bias_attr=False,
  176. )
  177. self.bn3 = nn.BatchNorm2D(self.output_channel_block[2])
  178. self.layer4 = self._make_layer(
  179. block, self.output_channel_block[3], layers[3], stride=1
  180. )
  181. self.conv4_1 = nn.Conv2D(
  182. self.output_channel_block[3],
  183. self.output_channel_block[3],
  184. kernel_size=2,
  185. stride=(2, 1),
  186. padding=(0, 1),
  187. weight_attr=conv_weight_attr,
  188. bias_attr=False,
  189. )
  190. self.bn4_1 = nn.BatchNorm2D(self.output_channel_block[3])
  191. self.conv4_2 = nn.Conv2D(
  192. self.output_channel_block[3],
  193. self.output_channel_block[3],
  194. kernel_size=2,
  195. stride=1,
  196. padding=0,
  197. weight_attr=conv_weight_attr,
  198. bias_attr=False,
  199. )
  200. self.bn4_2 = nn.BatchNorm2D(self.output_channel_block[3])
  201. def _make_layer(self, block, planes, blocks, stride=1):
  202. """
  203. Args:
  204. block (block): convolution block
  205. planes (int): input channels
  206. blocks (list): layers of the block
  207. stride (int): stride of the convolution
  208. Returns:
  209. nn.Sequential: the combination of the convolution block
  210. """
  211. downsample = None
  212. if stride != 1 or self.inplanes != planes * block.expansion:
  213. downsample = nn.Sequential(
  214. nn.Conv2D(
  215. self.inplanes,
  216. planes * block.expansion,
  217. kernel_size=1,
  218. stride=stride,
  219. weight_attr=conv_weight_attr,
  220. bias_attr=False,
  221. ),
  222. nn.BatchNorm2D(planes * block.expansion),
  223. )
  224. layers = list()
  225. layers.append(block(self.inplanes, planes, stride, downsample))
  226. self.inplanes = planes * block.expansion
  227. for _ in range(1, blocks):
  228. layers.append(block(self.inplanes, planes))
  229. return nn.Sequential(*layers)
  230. def forward(self, x):
  231. x = self.conv0_1(x)
  232. x = self.bn0_1(x)
  233. x = self.relu(x)
  234. x = self.conv0_2(x)
  235. x = self.bn0_2(x)
  236. x = self.relu(x)
  237. x = self.maxpool1(x)
  238. x = self.layer1(x)
  239. x = self.conv1(x)
  240. x = self.bn1(x)
  241. x = self.relu(x)
  242. x = self.maxpool2(x)
  243. x = self.layer2(x)
  244. x = self.conv2(x)
  245. x = self.bn2(x)
  246. x = self.relu(x)
  247. x = self.maxpool3(x)
  248. x = self.layer3(x)
  249. x = self.conv3(x)
  250. x = self.bn3(x)
  251. x = self.relu(x)
  252. x = self.layer4(x)
  253. x = self.conv4_1(x)
  254. x = self.bn4_1(x)
  255. x = self.relu(x)
  256. x = self.conv4_2(x)
  257. x = self.bn4_2(x)
  258. x = self.relu(x)
  259. return x