Spaces:
Runtime error
Runtime error
File size: 6,004 Bytes
2366e36 |
1 2 3 4 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# Copyright (c) OpenMMLab. All rights reserved.
import sys
import cv2
import numpy as np
import pyclipper
from mmcv.utils import print_log
from shapely.geometry import Polygon as plg
import mmocr.utils.check_argument as check_argument
class BaseTextDetTargets:
"""Generate text detector ground truths."""
def __init__(self):
pass
def point2line(self, xs, ys, point_1, point_2):
"""Compute the distance from point to a line. This is adapted from
https://github.com/MhLiao/DB.
Args:
xs (ndarray): The x coordinates of size hxw.
ys (ndarray): The y coordinates of size hxw.
point_1 (ndarray): The first point with shape 1x2.
point_2 (ndarray): The second point with shape 1x2.
Returns:
result (ndarray): The distance matrix of size hxw.
"""
# suppose a triangle with three edge abc with c=point_1 point_2
# a^2
a_square = np.square(xs - point_1[0]) + np.square(ys - point_1[1])
# b^2
b_square = np.square(xs - point_2[0]) + np.square(ys - point_2[1])
# c^2
c_square = np.square(point_1[0] - point_2[0]) + np.square(point_1[1] -
point_2[1])
# -cosC=(c^2-a^2-b^2)/2(ab)
neg_cos_c = (
(c_square - a_square - b_square) /
(np.finfo(np.float32).eps + 2 * np.sqrt(a_square * b_square)))
# sinC^2=1-cosC^2
square_sin = 1 - np.square(neg_cos_c)
square_sin = np.nan_to_num(square_sin)
# distance=a*b*sinC/c=a*h/c=2*area/c
result = np.sqrt(a_square * b_square * square_sin /
(np.finfo(np.float32).eps + c_square))
# set result to minimum edge if C<pi/2
result[neg_cos_c < 0] = np.sqrt(np.fmin(a_square,
b_square))[neg_cos_c < 0]
return result
def polygon_area(self, polygon):
"""Compute the polygon area. Please refer to Green's theorem.
https://en.wikipedia.org/wiki/Green%27s_theorem. This is adapted from
https://github.com/MhLiao/DB.
Args:
polygon (ndarray): The polygon boundary points.
"""
polygon = polygon.reshape(-1, 2)
edge = 0
for i in range(polygon.shape[0]):
next_index = (i + 1) % polygon.shape[0]
edge += (polygon[next_index, 0] - polygon[i, 0]) * (
polygon[next_index, 1] + polygon[i, 1])
return edge / 2.
def polygon_size(self, polygon):
"""Estimate the height and width of the minimum bounding box of the
polygon.
Args:
polygon (ndarray): The polygon point sequence.
Returns:
size (tuple): The height and width of the minimum bounding box.
"""
poly = polygon.reshape(-1, 2)
rect = cv2.minAreaRect(poly.astype(np.int32))
size = rect[1]
return size
def generate_kernels(self,
img_size,
text_polys,
shrink_ratio,
max_shrink=sys.maxsize,
ignore_tags=None):
"""Generate text instance kernels for one shrink ratio.
Args:
img_size (tuple(int, int)): The image size of (height, width).
text_polys (list[list[ndarray]]: The list of text polygons.
shrink_ratio (float): The shrink ratio of kernel.
Returns:
text_kernel (ndarray): The text kernel mask of (height, width).
"""
assert isinstance(img_size, tuple)
assert check_argument.is_2dlist(text_polys)
assert isinstance(shrink_ratio, float)
h, w = img_size
text_kernel = np.zeros((h, w), dtype=np.float32)
for text_ind, poly in enumerate(text_polys):
instance = poly[0].reshape(-1, 2).astype(np.int32)
area = plg(instance).area
peri = cv2.arcLength(instance, True)
distance = min(
int(area * (1 - shrink_ratio * shrink_ratio) / (peri + 0.001) +
0.5), max_shrink)
pco = pyclipper.PyclipperOffset()
pco.AddPath(instance, pyclipper.JT_ROUND,
pyclipper.ET_CLOSEDPOLYGON)
shrunk = np.array(pco.Execute(-distance))
# check shrunk == [] or empty ndarray
if len(shrunk) == 0 or shrunk.size == 0:
if ignore_tags is not None:
ignore_tags[text_ind] = True
continue
try:
shrunk = np.array(shrunk[0]).reshape(-1, 2)
except Exception as e:
print_log(f'{shrunk} with error {e}')
if ignore_tags is not None:
ignore_tags[text_ind] = True
continue
cv2.fillPoly(text_kernel, [shrunk.astype(np.int32)], text_ind + 1)
return text_kernel, ignore_tags
def generate_effective_mask(self, mask_size: tuple, polygons_ignore):
"""Generate effective mask by setting the ineffective regions to 0 and
effective regions to 1.
Args:
mask_size (tuple): The mask size.
polygons_ignore (list[[ndarray]]: The list of ignored text
polygons.
Returns:
mask (ndarray): The effective mask of (height, width).
"""
assert check_argument.is_2dlist(polygons_ignore)
mask = np.ones(mask_size, dtype=np.uint8)
for poly in polygons_ignore:
instance = poly[0].reshape(-1,
2).astype(np.int32).reshape(1, -1, 2)
cv2.fillPoly(mask, instance, 0)
return mask
def generate_targets(self, results):
raise NotImplementedError
def __call__(self, results):
results = self.generate_targets(results)
return results
|