def parse_txt(gt_path): """ .mat file parser :param gt_path: (str), mat file path :return: (list), TextInstance """ lines = read_lines(gt_path + ".txt") polygons = [] for line in lines: line = strs.remove_all(line.strip('\ufeff'), '\xef\xbb\xbf') gt = line.split(',') x1, y1, x2, y2, x3, y3, x4, y4 = list(map(int, gt[:8])) xx = [x1, x2, x3, x4] yy = [y1, y2, y3, y4] if gt[-1].strip() == "###": label = gt[-1].strip().replace("###", "#") else: label = "GG" pts = np.stack([xx, yy]).T.astype(np.int32) d1 = norm2(pts[0] - pts[1]) d2 = norm2(pts[1] - pts[2]) d3 = norm2(pts[2] - pts[3]) d4 = norm2(pts[3] - pts[0]) if min([d1, d2, d3, d4]) < 2: continue polygons.append(TextInstance(pts, 'c', label)) return polygons
def adjust_contours(self, image, all_contours): mask = np.zeros(image.shape[0:2]) # image_show = image.copy() bbox_contours = list() for idx, (boundary_point, line) in enumerate(all_contours): deal_mask = mask.copy() cv2.drawContours(deal_mask, [boundary_point], -1, 1, -1) deal_contours, _ = cv2.findContours(deal_mask.astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) new_line = list() for ip, _ in enumerate(line): if not (self.in_contour(deal_contours[0], line[ip, 0, :])\ or self.in_contour(deal_contours[0], line[ip, 1, :])): new_line.append(line[ip]) try: new_line = np.array(new_line) vet10 = np.array(new_line[0:-1, 0, :]) - np.array(new_line[1:, 0, :]) vet20 = np.array(new_line[0:-1, 1, :]) - np.array(new_line[1:, 1, :]) except: continue cosin0 = np.sum(vet10 * vet20, axis=1) / (norm2(vet10, axis=1) * norm2(vet20, axis=1)) vet11 = np.array(new_line[0:-1, 0, :]) - np.array(new_line[0:-1, 1, :]) vet21 = np.array(new_line[1:, 0, :]) - np.array(new_line[1:, 1, :]) cosin1 = np.sum(vet11 * vet21, axis=1) / (norm2(vet11, axis=1) * norm2(vet21, axis=1)) defect_point = (np.where((cosin0 < 0.6) & (cosin1 < 0.6))[0]).tolist() defect_size = (np.where((cosin0 < 0.6) & (cosin1 < 1))[0]) if len(defect_point): defect_point = sorted(defect_point) dps = list() for index in defect_point: iip = defect_size[np.where(np.abs(defect_size - index) <= 5)].tolist() min_iip = min(iip)-1 max_iip = max(iip)+1 dps += list(range(min_iip, max_iip+1)) defect_point.insert(0, 0) defect_point.append(len(new_line)) defect_point = sorted(list(set(defect_point))) segline = np.stack([defect_point[0:-1], defect_point[1:]], axis=1) for seg in segline[1::2]: new_line[seg[0]:seg[1]] = new_line[seg[0]:seg[1], ::-1, :] new_line = np.delete(new_line, dps, axis=0) if new_line.shape[0] < 4: continue boundary_point = np.concatenate([new_line[:, 0, :], new_line[::-1, 1, :]], axis=0) bbox_contours.append([boundary_point, new_line]) return bbox_contours
def find_min_radii(self,pts): bottom = find_bottom(pts) e1, e2 = find_long_edges(pts, bottom) # find two long edge sequence inner_points1 = split_edge_seqence(pts, e1, 16) inner_points2 = split_edge_seqence(pts, e2, 16) inner_points2 = inner_points2[::-1] center_points = (inner_points1 + inner_points2) / 2 # disk center radii = norm2(inner_points1 - center_points, axis=1) return inner_points1,inner_points2,center_points
def disk_cover(self, unit_disk): n_disk = get_n_parts(self.points, self.bottoms, self.e1, self.e2, unit_disk) inner_points1 = split_edge_seqence(self.points, self.e1, n_disk) inner_points2 = split_edge_seqence(self.points, self.e2, n_disk) inner_points2 = inner_points2[::-1] # inverse one of long edge center_points = (inner_points1 + inner_points2) / 2 # disk center radii = norm2(inner_points1 - center_points, axis=1) # disk radius return inner_points1, inner_points2, center_points, radii
def disk_cover(self, n_disk=15): """ cover text region with several disks :param n_disk: number of disks :return: """ inner_points1 = split_edge_seqence(self.points, self.e1, n_disk) inner_points2 = split_edge_seqence(self.points, self.e2, n_disk) inner_points2 = inner_points2[::-1] # innverse one of long edge center_points = (inner_points1 + inner_points2) / 2 # disk center radii = norm2(inner_points1 - center_points, axis=1) # disk radius return inner_points1, inner_points2, center_points, radii
def graph_propagation_naive(edges, score, th, bboxs=None, dis_thresh=50, pool='avg'): edges = np.sort(edges, axis=1) score_dict = {} # score lookup table if pool is None: for i, e in enumerate(edges): score_dict[e[0], e[1]] = score[i] elif pool == 'avg': for i, e in enumerate(edges): if bboxs is not None: box1 = bboxs[e[0]][:8].reshape(4, 2) box2 = bboxs[e[1]][:8].reshape(4, 2) c1 = np.mean(box1, 0) c2 = np.mean(box2, 0) dst = norm2(c1 - c2) if dst > dis_thresh: score[i] = 0 if (e[0], e[1]) in score_dict: score_dict[e[0], e[1]] = 0.5 * (score_dict[e[0], e[1]] + score[i]) else: score_dict[e[0], e[1]] = score[i] elif pool == 'max': for i, e in enumerate(edges): if (e[0], e[1]) in score_dict: score_dict[e[0], e[1]] = max(score_dict[e[0], e[1]], score[i]) else: score_dict[e[0], e[1]] = score[i] else: raise ValueError('Pooling operation not supported') nodes = np.sort(np.unique(edges.flatten())) mapping = -1 * np.ones((nodes.max() + 1), dtype=np.int) mapping[nodes] = np.arange(nodes.shape[0]) link_idx = mapping[edges] vertex = [Data(n) for n in nodes] for l, s in zip(link_idx, score): vertex[l[0]].add_link(vertex[l[1]], s) # first iteration comps = connected_components(vertex, score_dict, th) return comps
def mask_to_tcl(self, pred_sin, pred_cos, pred_radii, tcl_mask, init_xy, direct=1): """ Iteratively find center line in tcl mask using initial point (x, y) :param pred_sin: predict sin map :param pred_cos: predict cos map :param tcl_mask: predict tcl mask :param init_xy: initial (x, y) :param direct: direction [-1|1] :return: """ H, W = pred_sin.shape x_init, y_init = init_xy sin = pred_sin[int(y_init), int(x_init)] cos = pred_cos[int(y_init), int(x_init)] radii = pred_radii[int(y_init), int(x_init)] x_shift, y_shift = self.centerlize(x_init, y_init, cos, sin, tcl_mask) result = [] while tcl_mask[int(y_shift), int(x_shift)]: result.append(np.array([x_shift, y_shift, radii])) x, y = x_shift, y_shift sin = pred_sin[int(y), int(x)] cos = pred_cos[int(y), int(x)] x_c, y_c = self.centerlize(x, y, cos, sin, tcl_mask) sin_c = pred_sin[int(y_c), int(x_c)] cos_c = pred_cos[int(y_c), int(x_c)] radii = pred_radii[int(y_c), int(x_c)] # shift stride for shrink in np.arange(0.5, 0.0, -0.1): # [0.5, 0.4, 0.3, 0.2, 0.1] t = shrink * radii # stride = +/- 0.5 * [sin|cos](theta), if new point is outside, shrink it until shrink < 0.1, hit ends x_shift_pos = x_c + cos_c * t * direct # positive direction y_shift_pos = y_c + sin_c * t * direct # positive direction x_shift_neg = x_c - cos_c * t * direct # negative direction y_shift_neg = y_c - sin_c * t * direct # negative direction # if first point, select positive direction shift if len(result) == 1: x_shift, y_shift = x_shift_pos, y_shift_pos else: # else select point further with second last point dist_pos = norm2(result[-2][:2] - (x_shift_pos, y_shift_pos)) dist_neg = norm2(result[-2][:2] - (x_shift_neg, y_shift_neg)) if dist_pos > dist_neg: x_shift, y_shift = x_shift_pos, y_shift_pos else: x_shift, y_shift = x_shift_neg, y_shift_neg # if out of bounds, skip if int(x_shift) >= W or int(x_shift) < 0 or int( y_shift) >= H or int(y_shift) < 0: continue # found an inside point if tcl_mask[int(y_shift), int(x_shift)]: break # if out of bounds, break if int(x_shift) >= W or int(x_shift) < 0 or int( y_shift) >= H or int(y_shift) < 0: break return result
def mask_to_tcl(self, pred_sin, pred_cos, pred_radii, tcl_contour, init_xy, direct=1): """ Iteratively find center line in tcl mask using initial point (x, y) :param pred_sin: predict sin map :param pred_cos: predict cos map :param tcl_contour: predict tcl contour :param init_xy: initial (x, y) :param direct: direction [-1|1] :return: """ H, W = pred_sin.shape x_shift, y_shift = init_xy result = [] max_attempt = 200 attempt = 0 while self.in_contour(tcl_contour, (x_shift, y_shift)): attempt += 1 sin = pred_sin[int(y_shift), int(x_shift)] cos = pred_cos[int(y_shift), int(x_shift)] x_c, y_c = self.centerlize(x_shift, y_shift, H, W, cos, sin, tcl_contour) sin_c = pred_sin[int(y_c), int(x_c)] cos_c = pred_cos[int(y_c), int(x_c)] radii_c = pred_radii[int(y_c), int(x_c)] result.append(np.array([x_c, y_c, radii_c])) # shift stride for shrink in [1 / 2., 1 / 4., 1 / 8., 1 / 16., 1 / 32.]: t = shrink * radii_c # stride = +/- 0.5 * [sin|cos](theta), if new point is outside, shrink it until shrink < 1/32., hit ends x_shift_pos = x_c + cos_c * t * direct # positive direction y_shift_pos = y_c + sin_c * t * direct # positive direction x_shift_neg = x_c - cos_c * t * direct # negative direction y_shift_neg = y_c - sin_c * t * direct # negative direction # if first point, select positive direction shift if len(result) == 1: x_shift, y_shift = x_shift_pos, y_shift_pos else: # else select point further with second last point dist_pos = norm2(result[-2][:2] - (x_shift_pos, y_shift_pos)) dist_neg = norm2(result[-2][:2] - (x_shift_neg, y_shift_neg)) if dist_pos > dist_neg: x_shift, y_shift = x_shift_pos, y_shift_pos else: x_shift, y_shift = x_shift_neg, y_shift_neg # if out of bounds, skip if int(x_shift) >= W or int(x_shift) < 0 or int( y_shift) >= H or int(y_shift) < 0: continue # found an inside point if self.in_contour(tcl_contour, (x_shift, y_shift)): break # if out of bounds, break if int(x_shift) >= W or int(x_shift) < 0 or int( y_shift) >= H or int(y_shift) < 0: break if attempt > max_attempt: break return np.array(result)