pse_postprocess.py 3.4 KB
Newer Older
W
WenmuZhou 已提交
1 2 3 4
"""
This code is refer from:
https://github.com/whai362/PSENet/blob/python3/models/head/psenet_head.py
"""
W
WenmuZhou 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
import cv2
import paddle
from paddle.nn import functional as F

from ppocr.postprocess.pse_postprocess.pse import pse


class PSEPostProcess(object):
    """
    The post process for PSE.
    """

    def __init__(self,
                 thresh=0.5,
                 box_thresh=0.85,
                 min_area=16,
                 box_type='box',
                 scale=4,
                 **kwargs):
        assert box_type in ['box', 'poly'], 'Only box and poly is supported'
        self.thresh = thresh
        self.box_thresh = box_thresh
        self.min_area = min_area
        self.box_type = box_type
        self.scale = scale

    def __call__(self, outs_dict, shape_list):
        pred = outs_dict['maps']
        if not isinstance(pred, paddle.Tensor):
            pred = paddle.to_tensor(pred)
W
WenmuZhou 已提交
41 42
        pred = F.interpolate(
            pred, scale_factor=4 // self.scale, mode='bilinear')
W
WenmuZhou 已提交
43 44 45 46 47 48 49 50 51 52 53 54

        score = F.sigmoid(pred[:, 0, :, :])

        kernels = (pred > self.thresh).astype('float32')
        text_mask = kernels[:, 0, :, :]
        kernels[:, 0:, :, :] = kernels[:, 0:, :, :] * text_mask

        score = score.numpy()
        kernels = kernels.numpy().astype(np.uint8)

        boxes_batch = []
        for batch_index in range(pred.shape[0]):
W
WenmuZhou 已提交
55 56 57
            boxes, scores = self.boxes_from_bitmap(score[batch_index],
                                                   kernels[batch_index],
                                                   shape_list[batch_index])
W
WenmuZhou 已提交
58 59 60 61

            boxes_batch.append({'points': boxes, 'scores': scores})
        return boxes_batch

W
WenmuZhou 已提交
62
    def boxes_from_bitmap(self, score, kernels, shape):
W
WenmuZhou 已提交
63
        label = pse(kernels, self.min_area)
W
WenmuZhou 已提交
64
        return self.generate_box(score, label, shape)
W
WenmuZhou 已提交
65

W
WenmuZhou 已提交
66 67
    def generate_box(self, score, label, shape):
        src_h, src_w, ratio_h, ratio_w = shape
W
WenmuZhou 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
        label_num = np.max(label) + 1

        boxes = []
        scores = []
        for i in range(1, label_num):
            ind = label == i
            points = np.array(np.where(ind)).transpose((1, 0))[:, ::-1]

            if points.shape[0] < self.min_area:
                label[ind] = 0
                continue

            score_i = np.mean(score[ind])
            if score_i < self.box_thresh:
                label[ind] = 0
                continue

            if self.box_type == 'box':
                rect = cv2.minAreaRect(points)
                bbox = cv2.boxPoints(rect)
            elif self.box_type == 'poly':
                box_height = np.max(points[:, 1]) + 10
                box_width = np.max(points[:, 0]) + 10

                mask = np.zeros((box_height, box_width), np.uint8)
                mask[points[:, 1], points[:, 0]] = 255

W
WenmuZhou 已提交
95 96
                contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL,
                                               cv2.CHAIN_APPROX_SIMPLE)
W
WenmuZhou 已提交
97 98 99 100
                bbox = np.squeeze(contours[0], 1)
            else:
                raise NotImplementedError

W
WenmuZhou 已提交
101 102
            bbox[:, 0] = np.clip(np.round(bbox[:, 0] / ratio_w), 0, src_w)
            bbox[:, 1] = np.clip(np.round(bbox[:, 1] / ratio_h), 0, src_h)
W
WenmuZhou 已提交
103 104 105
            boxes.append(bbox)
            scores.append(score_i)
        return boxes, scores