2 Copyright (c) 2019-present NAVER Corp.
13 """ auxilary functions """
18 out = np.matmul(Minv, (pt[0], pt[1], 1))
19 return np.array([out[0] / out[2], out[1] / out[2]])
22 """ end of auxilary functions """
32 linkmap = linkmap.copy()
33 textmap = textmap.copy()
34 img_h, img_w = textmap.shape
36 """ labeling method """
37 ret, text_score = cv2.threshold(textmap, low_text, 1, 0)
38 ret, link_score = cv2.threshold(linkmap, link_threshold, 1, 0)
40 text_score_comb = np.clip(text_score + link_score, 0, 1)
41 nLabels, labels, stats, centroids = cv2.connectedComponentsWithStats(
42 text_score_comb.astype(np.uint8), connectivity=4)
46 for k
in range(1, nLabels):
48 size = stats[k, cv2.CC_STAT_AREA]
53 if np.max(textmap[labels == k]) < text_threshold:
57 segmap = np.zeros(textmap.shape, dtype=np.uint8)
58 segmap[labels == k] = 255
59 segmap[np.logical_and(link_score == 1,
61 x, y = stats[k, cv2.CC_STAT_LEFT], stats[k, cv2.CC_STAT_TOP]
62 w, h = stats[k, cv2.CC_STAT_WIDTH], stats[k, cv2.CC_STAT_HEIGHT]
63 niter =
int(math.sqrt(size * min(w, h) / (w * h)) * 2)
64 sx, ex, sy, ey = x - niter, x + w + niter + 1, \
65 y - niter, y + h + niter + 1
75 kernel = cv2.getStructuringElement(
76 cv2.MORPH_RECT, (1 + niter, 1 + niter))
77 segmap[sy:ey, sx:ex] = cv2.dilate(segmap[sy:ey, sx:ex], kernel)
80 np_contours = np.roll(np.array(np.where(segmap != 0)),
81 1, axis=0).transpose().reshape(-1, 2)
82 rectangle = cv2.minAreaRect(np_contours)
83 box = cv2.boxPoints(rectangle)
98 w, h = np.linalg.norm(box[0] - box[1]), np.linalg.norm(box[1] - box[2])
99 box_ratio = max(w, h) / (min(w, h) + 1e-5)
100 if abs(1 - box_ratio) <= 0.1:
101 l, r = min(np_contours[:, 0]), max(np_contours[:, 0])
102 t, b = min(np_contours[:, 1]), max(np_contours[:, 1])
103 box = np.array([[l, t], [r, t], [r, b], [l, b]], dtype=np.float32)
106 startidx = box.sum(axis=1).argmin()
107 box = np.roll(box, 4 - startidx, 0)
113 return det, labels, mapper
125 for k, box
in enumerate(boxes):
127 w =
int(np.linalg.norm(box[0] - box[1]) + 1)
128 h =
int(np.linalg.norm(box[1] - box[2]) + 1)
134 tar = np.float32([[0, 0], [w, 0], [w, h], [0, h]])
135 M = cv2.getPerspectiveTransform(box, tar)
136 word_label = cv2.warpPerspective(
137 labels, M, (w, h), flags=cv2.INTER_NEAREST)
139 Minv = np.linalg.inv(M)
140 except BaseException:
145 cur_label = mapper[k]
146 word_label[word_label != cur_label] = 0
147 word_label[word_label > 0] = 1
149 """ Polygon generation """
154 region = np.where(word_label[:, i] != 0)[0]
157 cp.append((i, region[0], region[-1]))
158 length = region[-1] - region[0] + 1
163 if h * max_len_ratio < max_len:
168 tot_seg = num_cp * 2 + 1
171 cp_section = [[0, 0]] * tot_seg
172 seg_height = [0] * num_cp
176 for i
in range(0, len(cp)):
178 if (seg_num + 1) * seg_w <= x
and seg_num <= tot_seg:
182 cp_section[seg_num] = [
183 cp_section[seg_num][0] / num_sec,
184 cp_section[seg_num][1] / num_sec]
194 cp_section[seg_num] = [
195 cp_section[seg_num][0] + x,
196 cp_section[seg_num][1] + cy]
203 pp[
int((seg_num - 1) / 2)] = (x, cy)
204 seg_height[
int((seg_num - 1) / 2)] = cur_h
210 cp_section[-1][0] / num_sec,
211 cp_section[-1][1] / num_sec]
215 if None in pp
or seg_w < np.max(seg_height) * 0.25:
220 half_char_h = np.median(seg_height) * expand_ratio / 2
224 for i, (x, cy)
in enumerate(pp):
225 dx = cp_section[i * 2 + 2][0] - cp_section[i * 2][0]
226 dy = cp_section[i * 2 + 2][1] - cp_section[i * 2][1]
228 new_pp.append([x, cy - half_char_h, x, cy + half_char_h])
230 rad = - math.atan2(dy, dx)
231 c, s = half_char_h * math.cos(rad), half_char_h * math.sin(rad)
232 new_pp.append([x - s, cy - c, x + s, cy + c])
235 isSppFound, isEppFound =
False,
False
236 grad_s = (pp[1][1] - pp[0][1]) / (pp[1][0] - pp[0][0]) + \
237 (pp[2][1] - pp[1][1]) / (pp[2][0] - pp[1][0])
238 grad_e = (pp[-2][1] - pp[-1][1]) / (pp[-2][0] - pp[-1][0]) + \
239 (pp[-3][1] - pp[-2][1]) / (pp[-3][0] - pp[-2][0])
240 for r
in np.arange(0.5, max_r, step_r):
241 dx = 2 * half_char_h * r
243 line_img = np.zeros(word_label.shape, dtype=np.uint8)
245 p = np.array(new_pp[0]) - np.array([dx, dy, dx, dy])
251 p[3])), 1, thickness=1)
252 if np.sum(np.logical_and(word_label, line_img)
253 ) == 0
or r + 2 * step_r >= max_r:
257 line_img = np.zeros(word_label.shape, dtype=np.uint8)
259 p = np.array(new_pp[-1]) + np.array([dx, dy, dx, dy])
265 p[3])), 1, thickness=1)
266 if np.sum(np.logical_and(word_label, line_img)
267 ) == 0
or r + 2 * step_r >= max_r:
270 if isSppFound
and isEppFound:
274 if not (isSppFound
and isEppFound):
280 poly.append(
warpCoord(Minv, (spp[0], spp[1])))
282 poly.append(
warpCoord(Minv, (p[0], p[1])))
283 poly.append(
warpCoord(Minv, (epp[0], epp[1])))
284 poly.append(
warpCoord(Minv, (epp[2], epp[3])))
285 for p
in reversed(new_pp):
286 poly.append(
warpCoord(Minv, (p[2], p[3])))
287 poly.append(
warpCoord(Minv, (spp[2], spp[3])))
292 poly = np.array(poly)
293 startidx = poly.sum(axis=1).argmin()
294 poly = np.roll(poly, len(poly) - startidx, 0)
308 textmap, linkmap, text_threshold, link_threshold, low_text)
313 polys = [
None] * len(boxes)
320 polys = np.array(polys)
321 for k
in range(len(polys)):
322 if polys[k]
is not None:
323 polys[k] *= (ratio_w * ratio_net, ratio_h * ratio_net)