Spaces:
				
			
			
	
			
			
		Runtime error
		
	
	
	
			
			
	
	
	
	
		
		
		Runtime error
		
	| # Copyright (c) OpenMMLab. All rights reserved. | |
| import warnings | |
| import torch.nn as nn | |
| from mmcv.runner import BaseModule | |
| from mmdet.core import multi_apply | |
| from mmocr.models.builder import HEADS | |
| from ..postprocess.utils import poly_nms | |
| from .head_mixin import HeadMixin | |
| class FCEHead(HeadMixin, BaseModule): | |
| """The class for implementing FCENet head. | |
| FCENet(CVPR2021): `Fourier Contour Embedding for Arbitrary-shaped Text | |
| Detection <https://arxiv.org/abs/2104.10442>`_ | |
| Args: | |
| in_channels (int): The number of input channels. | |
| scales (list[int]) : The scale of each layer. | |
| fourier_degree (int) : The maximum Fourier transform degree k. | |
| nms_thr (float) : The threshold of nms. | |
| loss (dict): Config of loss for FCENet. | |
| postprocessor (dict): Config of postprocessor for FCENet. | |
| """ | |
| def __init__(self, | |
| in_channels, | |
| scales, | |
| fourier_degree=5, | |
| nms_thr=0.1, | |
| loss=dict(type='FCELoss', num_sample=50), | |
| postprocessor=dict( | |
| type='FCEPostprocessor', | |
| text_repr_type='poly', | |
| num_reconstr_points=50, | |
| alpha=1.0, | |
| beta=2.0, | |
| score_thr=0.3), | |
| train_cfg=None, | |
| test_cfg=None, | |
| init_cfg=dict( | |
| type='Normal', | |
| mean=0, | |
| std=0.01, | |
| override=[ | |
| dict(name='out_conv_cls'), | |
| dict(name='out_conv_reg') | |
| ]), | |
| **kwargs): | |
| old_keys = [ | |
| 'text_repr_type', 'decoding_type', 'num_reconstr_points', 'alpha', | |
| 'beta', 'score_thr' | |
| ] | |
| for key in old_keys: | |
| if kwargs.get(key, None): | |
| postprocessor[key] = kwargs.get(key) | |
| warnings.warn( | |
| f'{key} is deprecated, please specify ' | |
| 'it in postprocessor config dict. See ' | |
| 'https://github.com/open-mmlab/mmocr/pull/640' | |
| ' for details.', UserWarning) | |
| if kwargs.get('num_sample', None): | |
| loss['num_sample'] = kwargs.get('num_sample') | |
| warnings.warn( | |
| 'num_sample is deprecated, please specify ' | |
| 'it in loss config dict. See ' | |
| 'https://github.com/open-mmlab/mmocr/pull/640' | |
| ' for details.', UserWarning) | |
| BaseModule.__init__(self, init_cfg=init_cfg) | |
| loss['fourier_degree'] = fourier_degree | |
| postprocessor['fourier_degree'] = fourier_degree | |
| postprocessor['nms_thr'] = nms_thr | |
| HeadMixin.__init__(self, loss, postprocessor) | |
| assert isinstance(in_channels, int) | |
| self.downsample_ratio = 1.0 | |
| self.in_channels = in_channels | |
| self.scales = scales | |
| self.fourier_degree = fourier_degree | |
| self.nms_thr = nms_thr | |
| self.train_cfg = train_cfg | |
| self.test_cfg = test_cfg | |
| self.out_channels_cls = 4 | |
| self.out_channels_reg = (2 * self.fourier_degree + 1) * 2 | |
| self.out_conv_cls = nn.Conv2d( | |
| self.in_channels, | |
| self.out_channels_cls, | |
| kernel_size=3, | |
| stride=1, | |
| padding=1) | |
| self.out_conv_reg = nn.Conv2d( | |
| self.in_channels, | |
| self.out_channels_reg, | |
| kernel_size=3, | |
| stride=1, | |
| padding=1) | |
| def forward(self, feats): | |
| """ | |
| Args: | |
| feats (list[Tensor]): Each tensor has the shape of :math:`(N, C_i, | |
| H_i, W_i)`. | |
| Returns: | |
| list[[Tensor, Tensor]]: Each pair of tensors corresponds to the | |
| classification result and regression result computed from the input | |
| tensor with the same index. They have the shapes of :math:`(N, | |
| C_{cls,i}, H_i, W_i)` and :math:`(N, C_{out,i}, H_i, W_i)`. | |
| """ | |
| cls_res, reg_res = multi_apply(self.forward_single, feats) | |
| level_num = len(cls_res) | |
| preds = [[cls_res[i], reg_res[i]] for i in range(level_num)] | |
| return preds | |
| def forward_single(self, x): | |
| cls_predict = self.out_conv_cls(x) | |
| reg_predict = self.out_conv_reg(x) | |
| return cls_predict, reg_predict | |
| def get_boundary(self, score_maps, img_metas, rescale): | |
| assert len(score_maps) == len(self.scales) | |
| boundaries = [] | |
| for idx, score_map in enumerate(score_maps): | |
| scale = self.scales[idx] | |
| boundaries = boundaries + self._get_boundary_single( | |
| score_map, scale) | |
| # nms | |
| boundaries = poly_nms(boundaries, self.nms_thr) | |
| if rescale: | |
| boundaries = self.resize_boundary( | |
| boundaries, 1.0 / img_metas[0]['scale_factor']) | |
| results = dict(boundary_result=boundaries) | |
| return results | |
| def _get_boundary_single(self, score_map, scale): | |
| assert len(score_map) == 2 | |
| assert score_map[1].shape[1] == 4 * self.fourier_degree + 2 | |
| return self.postprocessor(score_map, scale) | |