def _offset_profile(poly): pco = pyclipper.PyclipperOffset() pco.AddPath(pyclipper.scale_to_clipper(poly), pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) offset = pco.Execute(-pyclipper.scale_to_clipper(Layer.bead_width/2)) offset = pyclipper.scale_from_clipper(offset) offset = np.reshape(offset, (-1,2)) return offset
def shrink(bboxes, rate, max_shr=20): rate = rate * rate shrinked_bboxes = [] for bbox in bboxes: area = plg.Polygon(bbox).area() peri = perimeter(bbox) pco = pyclipper.PyclipperOffset() pco.AddPath(bbox, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) offset = min((int)(area * (1 - rate) / (peri + 0.001) + 0.5), max_shr) shrinked_bbox = pco.Execute(-offset) if len(shrinked_bbox) == 0: shrinked_bboxes.append(bbox) continue shrinked_bbox = np.array(shrinked_bbox)[0] if len(shrinked_bbox) <= 2: shrinked_bboxes.append(bbox) continue #print 'bbox3',shrinked_bbox shrinked_bboxes.append(shrinked_bbox) return shrinked_bboxes
def unclip(self, box, unclip_ratio=1.5): poly = Polygon(box) distance = poly.area * unclip_ratio / poly.length offset = pyclipper.PyclipperOffset() offset.AddPath(box, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) expanded = np.array(offset.Execute(distance)) return expanded
def decode_dice(preds, scale=1, threshold=0.7311, min_area=5): import pyclipper preds[:2, :, :] = torch.sigmoid(preds[:2, :, :]) preds = preds.detach().cpu().numpy() text = preds[0] > threshold # text kernel = (preds[1] > threshold) * text # kernel label_num, label = cv2.connectedComponents(kernel.astype(np.uint8), connectivity=4) bbox_list = [] for label_idx in range(1, label_num): points = np.array(np.where(label_num == label_idx)).transpose( (1, 0))[:, ::-1] rect = cv2.minAreaRect(points) poly = cv2.boxPoints(rect).astype(int) d_i = cv2.contourArea(poly) * 1.5 / cv2.arcLength(poly, True) pco = pyclipper.PyclipperOffset() pco.AddPath(poly, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) shrinked_poly = np.array(pco.Execute(-d_i)) if cv2.contourArea(shrinked_poly) < 800 / (scale * scale): continue bbox_list.append([ shrinked_poly[1], shrinked_poly[2], shrinked_poly[3], shrinked_poly[0] ]) return label, np.array(bbox_list)
def generate_offset_polygon(lot): nodes, ways = {}, {} subj = [] for x, y in lot: subj.append((pyclipper.scale_to_clipper(x), pyclipper.scale_to_clipper(y))) pco = pyclipper.PyclipperOffset() pco.AddPath(subj, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON) solution = pco.Execute(-150000.0) building_lot = [(pyclipper.scale_from_clipper(x), pyclipper.scale_from_clipper(y)) for x, y in solution[0]] if len(building_lot) == 0: # failed to get offset polygon with the fixed param return nodes, ways building_nodes = [] for x, y in building_lot: n = new_node(x, y) building_nodes.append(n.id) nodes[n.id] = n way = new_way() way.nodes = building_nodes+[building_nodes[0]] way.tags = {"building":"residential"} ways[way.id] = way return nodes, ways
def fill_closed_region_with_iso_contours(self, input_contours, offset): """ fill a region with iso contours add all contours into self.iso_contours_of_a_region return @iso_contours_of_a_region, which inclues an iso contour list, each is represented as c[i,j] example: pe = pathEngine() pe.generate_contours_from_img(filepath, True) contour_tree = pe.convert_hiearchy_to_PyPolyTree() group_contour = pe.get_contours_from_each_connected_region(contour_tree, '0') for cs in group_contour.values(): pe.iso_contours_of_a_region.clear() iso_contours = pe.fill_closed_region_with_iso_contours(cs, offset) """ self.offset = offset iso_contours_of_a_region = [] contours = input_contours iso_contours_of_a_region.append(input_contours) while (len(contours) != 0): pco = pyclipper.PyclipperOffset() pco.AddPaths(contours, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) contours = pco.Execute(offset) iso_contours_of_a_region.append(contours) return iso_contours_of_a_region
def test_clear(self): pc = pyclipper.PyclipperOffset() self.add_path(pc, PATH_CLIP_1) pc.Clear() solution = pc.Execute(2.0) self.assertIsInstance(solution, list) self.assertEqual(len(solution), 0)
def generate_rbox(im_size, text_polys, text_tags, training_mask, i, n, m): """ 生成mask图,白色部分是文本,黑色是背景 :param im_size: 图像的h,w :param text_polys: 框的坐标 :param text_tags: 标注文本框是否参与训练 :return: 生成的mask图 """ h, w = im_size score_map = np.zeros((h, w), dtype=np.uint8) for poly, tag in zip(text_polys, text_tags): poly = poly.astype(np.int) r_i = 1 - (1 - m) * (n - i) / (n - 1) d_i = cv2.contourArea(poly) * (1 - r_i * r_i) / cv2.arcLength( poly, True) pco = pyclipper.PyclipperOffset() # pco.AddPath(pyclipper.scale_to_clipper(poly), pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) # shrinked_poly = np.floor(np.array(pyclipper.scale_from_clipper(pco.Execute(-d_i)))).astype(np.int) pco.AddPath(poly, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) shrinked_poly = np.array(pco.Execute(-d_i)) cv2.fillPoly(score_map, shrinked_poly, 1) # 制作mask # rect = cv2.minAreaRect(shrinked_poly) # poly_h, poly_w = rect[1] # if min(poly_h, poly_w) < 10: # cv2.fillPoly(training_mask, shrinked_poly, 0) if not tag: cv2.fillPoly(training_mask, shrinked_poly, 0) # 闭运算填充内部小框 # kernel = np.ones((3, 3), np.uint8) # score_map = cv2.morphologyEx(score_map, cv2.MORPH_CLOSE, kernel) return score_map, training_mask
def test_execute2(self): pc = pyclipper.PyclipperOffset() self.add_path(pc, PATH_CLIP_1) solution = pc.Execute2(2.0) self.assertIsInstance(solution, pyclipper.PyPolyNode) self.assertEqual(len(pyclipper.OpenPathsFromPolyTree(solution)), 0) self.assertEqual(len(pyclipper.ClosedPathsFromPolyTree(solution)), 1)
def generate_rbox(im_size, text_polys, text_tags, training_mask, shrink_ratio): """ 生成mask图,白色部分是文本,黑色是北京 :param im_size: 图像的h,w :param text_polys: 框的坐标 :param text_tags: 标注文本框是否参与训练 :param training_mask: 忽略标注为 DO NOT CARE 的矩阵 :return: 生成的mask图 """ h, w = im_size score_map = np.zeros((h, w), dtype=np.uint8) for i, (poly, tag) in enumerate(zip(text_polys, text_tags)): try: poly = poly.astype(np.int) # d_i = cv2.contourArea(poly) * (1 - shrink_ratio * shrink_ratio) / cv2.arcLength(poly, True) d_i = cv2.contourArea(poly) * (1 - shrink_ratio) / cv2.arcLength( poly, True) + 0.5 pco = pyclipper.PyclipperOffset() pco.AddPath(poly, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) shrinked_poly = np.array(pco.Execute(-d_i)) cv2.fillPoly(score_map, shrinked_poly, i + 1) if not tag: cv2.fillPoly(training_mask, shrinked_poly, 0) except: print(poly) return score_map, training_mask
def shrink(bboxes, rate, max_shr=20): rate = rate * rate shrinked_bboxes = [] for bbox in bboxes: area = plg.Polygon(bbox).area() peri = perimeter(bbox) try: pco = pyclipper.PyclipperOffset() pco.AddPath(bbox, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) offset = min(int(area * (1 - rate) / (peri + 0.001) + 0.5), max_shr) shrinked_bbox = pco.Execute(-offset) if len(shrinked_bbox) == 0: shrinked_bboxes.append(bbox) continue shrinked_bbox = np.array(shrinked_bbox[0]) if shrinked_bbox.shape[0] <= 2: shrinked_bboxes.append(bbox) continue shrinked_bboxes.append(shrinked_bbox) except Exception: print(type(shrinked_bbox), shrinked_bbox) print('area:', area, 'peri:', peri) shrinked_bboxes.append(bbox) return shrinked_bboxes
def _draw_border_map(poly, canvas, mask): poly = np.array(poly).copy() #poly = sorted(poly, key=lambda poly: (poly[0], poly[1])) #poly.append(poly[0]) #poly = np.array(poly) assert poly.ndim == 2 assert poly.shape[1] == 2 poly_shape = Polygon(poly) if poly_shape.area <= 0: return distance = poly_shape.area * ( 1 - np.power(cfg.SHRINK_RATIO, 2)) / poly_shape.length subject = [tuple(l) for l in poly] padding = pyclipper.PyclipperOffset() padding.AddPath(subject, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) padded_polygon = np.array(padding.Execute(distance)[0]) cv2.fillPoly(mask, [padded_polygon.astype(np.int32)], 1.0) xmin = padded_polygon[:, 0].min() xmax = padded_polygon[:, 0].max() ymin = padded_polygon[:, 1].min() ymax = padded_polygon[:, 1].max() width = xmax - xmin + 1 height = ymax - ymin + 1 poly[:, 0] = poly[:, 0] - xmin poly[:, 1] = poly[:, 1] - ymin xs = np.broadcast_to( np.linspace(0, width - 1, num=width).reshape(1, width), (height, width)) ys = np.broadcast_to( np.linspace(0, height - 1, num=height).reshape(height, 1), (height, width)) distance_map = np.zeros((poly.shape[0], height, width), dtype=np.float32) for i in range(poly.shape[0]): j = (i + 1) % poly.shape[0] absolute_distance = _distance(xs, ys, poly[i], poly[j]) distance_map[i] = np.clip(absolute_distance / distance, 0, 1) distance_map = distance_map.min(axis=0) xmin_valid = min(max(0, xmin), canvas.shape[1] - 1) xmax_valid = min(max(0, xmax), canvas.shape[1] - 1) ymin_valid = min(max(0, ymin), canvas.shape[0] - 1) ymax_valid = min(max(0, ymax), canvas.shape[0] - 1) # print(xmin_valid, xmax_valid, ymin_valid, ymax_valid) # print(xmin, xmax, ymin, ymax) # print(distance_map.shape) # print(distance_map[ # ymin_valid - ymin:ymax_valid - ymax + height, # xmin_valid - xmin:xmax_valid - xmax + width].shape) canvas[ymin_valid:ymax_valid + 1, xmin_valid:xmax_valid + 1] = np.fmax( 1 - distance_map[ymin_valid - ymin:ymax_valid - ymax + height, xmin_valid - xmin:xmax_valid - xmax + width], canvas[ymin_valid:ymax_valid + 1, xmin_valid:xmax_valid + 1]) return canvas, mask
def draw_border_map(self, polygon, canvas, mask): polygon = np.array(polygon) assert polygon.ndim == 2 assert polygon.shape[1] == 2 polygon_shape = Polygon(polygon) distance = polygon_shape.area * \ (1 - np.power(self.shrink_ratio, 2)) / polygon_shape.length subject = [tuple(l) for l in polygon] padding = pyclipper.PyclipperOffset() padding.AddPath(subject, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) padded_polygon = np.array(padding.Execute(distance)[0]) cv2.fillPoly(mask, [padded_polygon.astype(np.int32)], 1.0) xmin = padded_polygon[:, 0].min() xmax = padded_polygon[:, 0].max() ymin = padded_polygon[:, 1].min() ymax = padded_polygon[:, 1].max() width = xmax - xmin + 1 height = ymax - ymin + 1 polygon[:, 0] = polygon[:, 0] - xmin polygon[:, 1] = polygon[:, 1] - ymin xs = np.broadcast_to( np.linspace(0, width - 1, num=width).reshape(1, width), (height, width)) ys = np.broadcast_to( np.linspace(0, height - 1, num=height).reshape(height, 1), (height, width)) distance_map = np.zeros((polygon.shape[0], height, width), dtype=np.float32) for i in range(polygon.shape[0]): j = (i + 1) % polygon.shape[0] absolute_distance = self.distance(xs, ys, polygon[i], polygon[j]) distance_map[i] = np.clip(absolute_distance / distance, 0, 1) distance_map = distance_map.min(axis=0) xmin_valid = min(max(0, xmin), canvas.shape[1] - 1) xmax_valid = min(max(0, xmax), canvas.shape[1] - 1) ymin_valid = min(max(0, ymin), canvas.shape[0] - 1) ymax_valid = min(max(0, ymax), canvas.shape[0] - 1) # print(ymin_valid,ymax_valid,xmin_valid,xmax_valid) """ look = np.fmax( 1 - distance_map[ ymin_valid-ymin:ymax_valid-ymax+height, xmin_valid-xmin:xmax_valid-xmax+width], canvas[ymin_valid:ymax_valid + 1, xmin_valid:xmax_valid + 1]) print(look) """ canvas[ymin_valid:ymax_valid + 1, xmin_valid:xmax_valid + 1] = np.fmax( 1 - distance_map[ymin_valid - ymin:ymax_valid - ymax + height, xmin_valid - xmin:xmax_valid - xmax + width], canvas[ymin_valid:ymax_valid + 1, xmin_valid:xmax_valid + 1])
def offset(self, r): r = pyclipper.scale_to_clipper(r) t = time.time() pco = pyclipper.PyclipperOffset() pco.AddPaths(pyclipper.scale_to_clipper(self.items), pyclipper.JT_SQUARE, pyclipper.ET_CLOSEDPOLYGON) res = pyclipper.scale_from_clipper(pco.Execute(r)) return res
def offset(self, amount: float, *, tree: bool = False) -> "Paths": offset = pyclipper.PyclipperOffset() offset.AddPaths(self._toClipper(), pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) if tree: return Paths()._fromClipperTree(offset.Execute2(amount * 1000.0)) else: return Paths()._fromClipper(offset.Execute(amount * 1000.0))
def __init__(self, config, plotting = False): self.config = config self.inflator = pyclipper.PyclipperOffset() # Define environment based on wheter or not to plot if plotting: self.env = PlottingEnvironment(plotting_dir='plotted_paths') else: self.env = PolygonEnvironment()
def get_offset_contour(cs, offset): """ get_ffset_contour(cs, -4) """ pco = pyclipper.PyclipperOffset() pco.AddPaths(cs, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) ncs = pco.Execute(offset) return ncs
def offset(paths, amount): pco = pyclipper.PyclipperOffset() pco.ArcTolerance = SCALING_FACTOR / 40 paths = pyclipper.scale_to_clipper(paths, SCALING_FACTOR) pco.AddPaths(paths, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) outpaths = pco.Execute(amount * SCALING_FACTOR) outpaths = pyclipper.scale_from_clipper(outpaths, SCALING_FACTOR) return outpaths
def _smoothen_hull( hull: np.ndarray, x_min: float, x_max: float, y_min: float, y_max: float ) -> np.ndarray: """ Expand hull a bit away from the cluster and smoothen it """ # scale hull between 0 and 1 in both directions - help to produce the hull # with equal distance from the cluster when axes have different scaling x, y = hull[:, 0:1], hull[:, 1:2] x_diff, y_diff = (x_max - x_min), (y_max - y_min) hull = np.hstack(((x - x_min) / x_diff, (y - y_min) / y_diff)) # buffer the line for 3 * dist_from_cluster and move it back for # 2 * dist_from_cluster. It will make a hull smother. # pyclipper work with integer so points need to be scaled first scaling_factor = 1000 dist_from_cluster = 0.03 scaled_hull = pyclipper.scale_to_clipper(hull, scaling_factor) # buffer the hull for dist_from_cluster * 3 pco1 = pyclipper.PyclipperOffset() pco1.AddPath(scaled_hull, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) im_solution = pco1.Execute(dist_from_cluster * scaling_factor * 3) if len(im_solution) == 0: # when the solution is empty it means that polygon either consist of # one point, two points or all points are in line # ET_CLOSEDPOLYGON can't offset those polygons but ET_OPENROUND can pco1 = pyclipper.PyclipperOffset() pco1.AddPath(scaled_hull, pyclipper.JT_ROUND, pyclipper.ET_OPENROUND) im_solution = pco1.Execute(dist_from_cluster * scaling_factor * 3) # buffer the hull for dist_from_cluster * -2 pco2 = pyclipper.PyclipperOffset() pco2.AddPath(im_solution[0], pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) solution = pyclipper.scale_from_clipper( pco2.Execute(dist_from_cluster * scaling_factor * (-2)), scaling_factor ) solution = np.array(solution).reshape(-1, 2) # scale the hue back for its original space return np.hstack( (solution[:, 0:1] * x_diff + x_min, solution[:, 1:2] * y_diff + y_min) )
def poly_offset(img, poly, dis): subj_poly = np.array(poly) # Polygon(subj_poly).area, Polygon(subj_poly).length pco = pyclipper.PyclipperOffset() pco.AddPath(subj_poly, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) solution = pco.Execute(-1.0 * dis) ss = np.array(solution) cv2.fillPoly(img, ss.astype(np.int32), 1) return img
def shrink_polygon(pnt, di_n): pco = pyclipper.PyclipperOffset() pco.AddPath(pnt, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) shrink_pnt_n = [] for di in di_n: shrink_pnt = pco.Execute(-int(di)) shrink_pnt_n.append(shrink_pnt) return shrink_pnt_n
def getOffset(self, polys, offset): pco = pyclipper.PyclipperOffset() bigPolys = self.scaleToClipper(polys, 100000.) pco.AddPaths(bigPolys, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON) offsetPolys = self.scaleFromClipper(pco.Execute(offset * 100000.), 1 / 100000.) for poly in offsetPolys: poly.append(poly[0]) return offsetPolys
def offset_poly(path, toolrad): c_osp = pyclipper.PyclipperOffset() c_osp.AddPaths(path, pyclipper.JT_SQUARE, pyclipper.ET_CLOSEDPOLYGON) polyclip = c_osp.Execute(toolrad) polyclip = pyclipper.CleanPolygons(polyclip) c_osp.Clear() return polyclip
def get_coast_polygons(self): # Turns all of the disjoint lines into polygons, but I need to expand for it to work. pco = pyclipper.PyclipperOffset() for line in self.parse_coasts(): path = list(line) + [(line[0][0] + 1, line[0][1])] pco.AddPath(path, pyclipper.JT_SQUARE, pyclipper.ET_CLOSEDPOLYGON) solution = pco.Execute2(1) # Undo the expansion. pco = pyclipper.PyclipperOffset() for polygon in solution.Childs: pco.AddPath(polygon.Contour, pyclipper.JT_SQUARE, pyclipper.ET_CLOSEDPOLYGON) solution2 = pco.Execute2(-1) # I only want the external polygons, this gets rid of lakes and such. for polygon2 in solution2.Childs: yield polygon2.Contour
def offset(self, radius=0, rounding=0.0): offset = [] clip = pyclipper.PyclipperOffset() #Pyclipper polyclipper = pyclipper.Pyclipper() #Pyclipper for pat in self.polygons: outPoly = [[int(self.scaling * p[0]), int(self.scaling * p[1])] for p in pat] #Pyclipper outPoly = pyclipper.SimplifyPolygons([outPoly]) try: polyclipper.AddPaths(outPoly, poly_type=pyclipper.PT_SUBJECT, closed=True) except: None #print "path invalid", outPoly poly = polyclipper.Execute(pyclipper.CT_UNION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) clip.AddPaths(poly, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) offset = clip.Execute(-int((radius + rounding) * self.scaling)) offset = pyclipper.SimplifyPolygons(offset) if rounding > 0.0: roundclipper = pyclipper.PyclipperOffset() roundclipper.AddPaths(offset, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) offset = roundclipper.Execute(int(rounding * self.scaling)) offset = pyclipper.CleanPolygons(offset, distance=self.scaling * self.precision) #print (len(offset)) result = PolygonGroup(scaling=self.scaling, precision=self.precision, zlevel=self.zlevel) result.polygons = [] for poly in offset: if len(poly) > 0: output_poly = [[ float(x[0]) / self.scaling, float(x[1]) / self.scaling, self.zlevel ] for x in poly] result.addPolygon(output_poly) return result
def process(self, data): ''' requied keys: image, polygons, ignore_tags, filename adding keys: mask ''' image = data['image'] polygons = data['polygons'] ignore_tags = data['ignore_tags'] image = data['image'] filename = data['filename'] h, w = image.shape[:2] if data['is_training']: polygons, ignore_tags = self.validate_polygons( polygons, ignore_tags, h, w) gt = np.zeros((1, h, w), dtype=np.float32) mask = np.ones((h, w), dtype=np.float32) for i in range(len(polygons)): polygon = polygons[i] height = max(polygon[:, 1]) - min(polygon[:, 1]) width = max(polygon[:, 0]) - min(polygon[:, 0]) # height = min(np.linalg.norm(polygon[0] - polygon[3]), # np.linalg.norm(polygon[1] - polygon[2])) # width = min(np.linalg.norm(polygon[0] - polygon[1]), # np.linalg.norm(polygon[2] - polygon[3])) if ignore_tags[i] or min(height, width) < self.min_text_size: cv2.fillPoly(mask, polygon.astype(np.int32)[np.newaxis, :, :], 0) ignore_tags[i] = True else: polygon_shape = Polygon(polygon) distance = polygon_shape.area * \ (1 - np.power(self.shrink_ratio, 2)) / polygon_shape.length subject = [tuple(l) for l in polygons[i]] padding = pyclipper.PyclipperOffset() padding.AddPath(subject, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) shrinked = padding.Execute(-distance) if shrinked == []: cv2.fillPoly(mask, polygon.astype(np.int32)[np.newaxis, :, :], 0) ignore_tags[i] = True continue shrinked = np.array(shrinked[0]).reshape(-1, 2) cv2.fillPoly(gt[0], [shrinked.astype(np.int32)], 1) if filename is None: filename = '' data.update(image=image, polygons=polygons, gt=gt, mask=mask, filename=filename) return data
def __call__(self, data, *args, **kwargs): ''' data: a dict typically returned from `MakeICDARData`, where the following keys are contrains: image*, polygons*, ignore_tags*, shape, filename * means required. ''' image = data['image'] polygons = data['polygons'] ignore_tags = data['ignore_tags'] image = data['image'] filename = data['filename'] h, w = image.shape[:2] polygons, ignore_tags = self.validate_polygons(polygons, ignore_tags, h, w) gt = np.zeros((1, h, w), dtype=np.float32) mask = np.ones((h, w), dtype=np.float32) for i in range(polygons.shape[0]): polygon = polygons[i] height = min(np.linalg.norm(polygon[0] - polygon[3]), np.linalg.norm(polygon[1] - polygon[2])) width = min(np.linalg.norm(polygon[0] - polygon[1]), np.linalg.norm(polygon[2] - polygon[3])) if ignore_tags[i] or min(height, width) < self.min_text_size: cv2.fillPoly(mask, polygon.astype(np.int32)[np.newaxis, :, :], 0) ignore_tags[i] = True else: polygon_shape = Polygon(polygon) distance = polygon_shape.area * \ (1 - np.power(self.shrink_ratio, 2)) / polygon_shape.length subject = [tuple(l) for l in polygons[i]] padding = pyclipper.PyclipperOffset() padding.AddPath(subject, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) shrinked = padding.Execute(-distance) if shrinked == []: # fillPoly(img, pts, color[, lineType[, shift[, offset]]]) -> img # 填充被多边形约束的区域。 color为 Polygon color cv2.fillPoly(mask, polygon.astype(np.int32)[np.newaxis, :, :], 0) ignore_tags[i] = True continue shrinked = np.array(shrinked[0]).reshape(-1, 2) cv2.fillPoly(gt[0], [shrinked.astype(np.int32)], 1) if filename is None: filename = '' data.update(image=image, polygons=polygons, gt=gt, mask=mask, filename=filename) return data
def offset_polygon(self, polygon, margin): obstacle = () for i in range(len(polygon[0])): obstacle = ((int(polygon[0, i] * 100), int( polygon[1, i] * 100)), ) + obstacle pco = pyclipper.PyclipperOffset() pco.AddPath(obstacle, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) solution = pco.Execute(margin) solution = np.array(solution[0]) / 100. return solution.tolist()
def __call__(self, data: dict): assert 'polygon' in data, f'{self} need polygon to generate ' \ f'shrink map' shrink_maps = [] mask_maps = [] polygons = data['polygon'] image = data['input'] tags = data['tags'] h, w = image.shape[:2] for ratio in self.ratios: ratio = 1 - ratio**2 current_shrink_map = np.zeros(shape=(h, w, 1), dtype=np.float32) current_mask_map = np.ones(shape=(h, w, 1), dtype=np.float32) for idx, polygon in enumerate(polygons): polygon = np.array(polygon).reshape(-1, 2) height = max(polygon[:, 1]) - min(polygon[:, 1]) width = max(polygon[:, 0]) - min(polygon[:, 0]) if not tags[idx] or min(height, width) < self.min_text_size: tags[idx] = False cv2.fillPoly(current_mask_map[:, :, 0], [polygon.astype(np.int32)], 0) continue p_polygon = Polygon(polygon) area = p_polygon.area perimeter = p_polygon.length pco = pyclipper.PyclipperOffset() pco.AddPath(polygon, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) offset = min(area * ratio / perimeter + 0.5, self.max_shr) shrink_box = pco.Execute(-offset) if not shrink_box or len(shrink_box[0]) <= 2: shrink_box = polygon shrink_box = np.array(shrink_box[0]).reshape(-1, 2) cv2.fillPoly(current_shrink_map[:, :, 0], [shrink_box.astype(np.int32)], 1) shrink_maps.append(current_shrink_map) mask_maps.append(current_mask_map) # TO DO, not list, but np.ndarray data[self.prefix + '_map'] = shrink_maps data[self.prefix + '_mask'] = mask_maps data['mask_type'].append(self.prefix + '_map') data['mask_type'].append(self.prefix + '_mask') # print(data) #for id, item in enumerate(data['text_map']): # cv2.imshow('map', item) # cv2.waitKey() # print(data[self.prefix + '_map'][0].shape) #cv2.imshow('map', data[self.prefix + '_map'][0]) #cv2.waitKey() #print(data[self.prefix + '_map'][0].shape) #cv2.imshow('mask', data[self.prefix + '_mask'][0]) #cv2.waitKey() return data
def computePath(leader_waypoints, offset_id = 1): leader_waypoints = [[w[0], w[1]] for w in leader_waypoints] OFFSET_CONSTANT = 2 * 70000 ARC_TOLERANCE = 2000 scaled_waypoints = [] print leader_waypoints for wypt in leader_waypoints: scaled_waypoints.append([pyclipper.scale_to_clipper(wypt[0]), pyclipper.scale_to_clipper(wypt[1])]) pco = pyclipper.PyclipperOffset(0, ARC_TOLERANCE) pco.AddPath(scaled_waypoints, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) scaled_path = pco.Execute(offset_id * OFFSET_CONSTANT) #pyclipper.scale_to_clipper(OFFSET_CONSTANT)) unscaled_path = [] for wypt in scaled_path[0]: unscaled_path.append([pyclipper.scale_from_clipper(wypt[0]), pyclipper.scale_from_clipper(wypt[1])]) print scaled_path # gaphing here for visual check of correctness ''' leader_x = [] leader_y = [] for waypoint in leader_waypoints: leader_x.append(waypoint[0]) leader_y.append(waypoint[1]) follower1_x = [] follower1_y = [] for waypoint in unscaled_path: follower1_x.append(waypoint[0]) follower1_y.append(waypoint[1]) for i in range(0, len(leader_x)): plt.plot(leader_x[i:i+2], leader_y[i:i+2], 'ro-') for i in range(0, len(follower1_x)): plt.plot(follower1_x[i:i+2], follower1_y[i:i+2], 'go-') plt.show() ''' total_distance = 0 for i in range(len(unscaled_path) - 1): total_distance += getDistanceMeters(unscaled_path[i][0], unscaled_path[i][1], unscaled_path[i + 1][0], unscaled_path[i + 1][1]) shifted_unscaled_path = unscaled_path[16:] + unscaled_path[:16] output = { 'waypoints': shifted_unscaled_path, 'distance': total_distance } return output