def clean_polygon(self, polygon): """清多边形 Args: polygon ([type]): [description] Returns: [type]: [description] """ simple = pyclipper.SimplifyPolygon(polygon, pyclipper.PFT_NONZERO) if simple is None or len(simple) == 0: return None biggest = simple[0] biggest_area = pyclipper.Area(biggest) for i in range(1, len(simple)): area = abs(pyclipper.Area(simple[i])) if area > biggest_area: biggest = simple[i] biggest_area = area clean = pyclipper.CleanPolygon(biggest, self.config['curveTolerance']) if clean is None or len(clean) == 0: return None return clean
def test_area(self): # area less than 0 because orientation is False area_neg = pyclipper.Area(PATH_SUBJ_1) area_pos = pyclipper.Area(PATH_SUBJ_1[::-1]) self.assertLess(area_neg, 0) self.assertGreater(area_pos, 0) self.assertEqual(abs(area_neg), area_pos)
def softnms(boxes, box_scores, char_scores=None, overlapThresh=0.3, threshold=0.8, neighbourThresh=0.5, num_neig=0): scores = box_scores.copy() new_boxes = boxes[:, 0: 8].copy() if char_scores is not None: new_char_scores = char_scores.copy() polygons = [pyclipper.scale_to_clipper(poly.reshape((-1, 2))) for poly in new_boxes] areas = [pyclipper.scale_from_clipper(pyclipper.scale_from_clipper( pyclipper.Area(poly))) for poly in polygons] areas = [abs(_) for _ in areas] N = boxes.shape[0] order = np.arange(N) i = 0 while i < N: max_pos = scores[order[i: N]].argmax() + i order[i], order[max_pos] = order[max_pos], order[i] pos = i + 1 neighbours = list() while pos < N: try: pc = pyclipper.Pyclipper() pc.AddPath(polygons[order[i]], pyclipper.PT_CLIP, True) pc.AddPaths([polygons[order[pos]]], pyclipper.PT_SUBJECT, True) solution = pc.Execute(pyclipper.CT_INTERSECTION) if len(solution) == 0: inter = 0 else: inter = pyclipper.scale_from_clipper( pyclipper.scale_from_clipper( pyclipper.Area(solution[0]))) except Exception: inter = 0 union = areas[order[i]] + areas[order[pos]] - inter iou = inter / union if union > 0 else 0 if iou > neighbourThresh: neighbours.append(order[pos]) weight = np.exp(-(iou **2) / 0.5) scores[order[pos]] *= weight if scores[order[pos]] < threshold: order[pos], order[N - 1] = order[N - 1], order[pos] N -= 1 pos -= 1 pos += 1 if len(neighbours) >= num_neig: neighbours.append(order[i]) temp_scores = box_scores[neighbours].reshape((-1, 1)) new_boxes[order[i], :8] = (boxes[neighbours, :8] * temp_scores).sum(axis=0) / temp_scores.sum() if char_scores is not None: new_char_scores[order[i], :] = (char_scores[neighbours, :] * temp_scores).sum(axis=0) / temp_scores.sum() else: order[i], order[N - 1] = order[N - 1], order[i] N -= 1 i -= 1 i += 1 keep = [order[_] for _ in range(N)] if char_scores is not None: return keep, new_boxes, new_char_scores else: return keep, new_boxes
def area(vset): """ This function calculates the area of the set of FRV or ARV """ # Initialize A as it could be calculated iteratively A = 0 # Check multiple exteriors if type(vset[0][0]) == list: # Calc every exterior separately for i in range(len(vset)): A += pyclipper.scale_from_clipper(pyclipper.scale_from_clipper(pyclipper.Area(pyclipper.scale_to_clipper(vset[i])))) else: # Single exterior A = pyclipper.scale_from_clipper(pyclipper.scale_from_clipper(pyclipper.Area(pyclipper.scale_to_clipper(vset)))) return A
def iou_clipper(p1, p2): pc = pyclipper.Pyclipper() pc.AddPath(to_coords(p1), pyclipper.PT_CLIP, True) pc.AddPath(to_coords(p2), pyclipper.PT_SUBJECT, True) I = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) if len(I) > 0: U = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) Ia = pyclipper.Area(I[0]) Ua = pyclipper.Area(U[0]) IoU = Ia / Ua else: IoU = 0.0 return IoU
def nms_poly(polys, scores, overlapThresh, neighbourThresh=0.5, minScore=0, num_neig=0): pick = list() suppressed = [False for _ in range(len(polys))] polygons = [ pyclipper.scale_to_clipper(poly.reshape((-1, 2))) for poly in polys ] areas = [ pyclipper.scale_from_clipper( pyclipper.scale_from_clipper(pyclipper.Area(poly))) for poly in polygons ] areas = [abs(_) for _ in areas] order = np.array(scores).argsort()[::-1] for _i, i in enumerate(order): if suppressed[i] is False: pick.append(i) neighbours = list() for j in order[_i + 1:]: if suppressed[j] is False: try: pc = pyclipper.Pyclipper() pc.AddPath(polygons[i], pyclipper.PT_CLIP, True) pc.AddPaths([polygons[j]], pyclipper.PT_SUBJECT, True) solution = pc.Execute(pyclipper.CT_INTERSECTION) if len(solution) == 0: inter = 0 else: inter = pyclipper.scale_from_clipper( pyclipper.scale_from_clipper( pyclipper.Area(solution[0]))) except Exception as e: inter = 0 union = areas[i] + areas[j] - inter iou = inter / union if union > 0 else 0 if union > 0 and iou > overlapThresh: suppressed[j] = True if iou > neighbourThresh: neighbours.append(j) if len(neighbours) < num_neig: for ni in neighbours: suppressed[ni] = False pick.pop() return pick
def moveForwardToCutThreshold(cleared, stepDistance, toReachArea, maxArea): global last_gui_update passes=0 while True: if not moveForward(stepDistance): #reached the end of current path if not nextPath(): #reached the end of all paths passes=passes+1 if passes>1: return False cpt, dr = getCurrentPoint() toolInPos = translatePath(toolGeometry,cpt) #move tool to current position # calculate cut area in the current poisiton cp.Clear() cp.AddPath(toolInPos, pyclipper.PT_SUBJECT, True) cp.AddPaths(cleared, pyclipper.PT_CLIP, True) cuttingPolygon=cp.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) tryCuttingArea = 0 if time.time() - last_gui_update > GuiUtils.GUI_UPDATE_PERIOD: GuiUtils.sceneClearPaths("POLY") GuiUtils.sceneDrawFilledTool( "POLY", cpt, scale_factor, (0, 1, 0)) GuiUtils.sceneUpdateGui() last_gui_update = time.time() for poly in cuttingPolygon: tryCuttingArea = tryCuttingArea + math.fabs(pyclipper.Area(poly)) if tryCuttingArea > toReachArea and tryCuttingArea<maxArea: return True
def check_and_validate_polys(polys, tags, xxx_todo_changeme): ''' check so that the text poly is in the same direction, and also filter some invalid polygons :param polys: :param tags: :return: ''' (h, w) = xxx_todo_changeme if polys.shape[0] == 0: return [], [] polys[:, :, 0] = np.clip(polys[:, :, 0], 0, w - 1) polys[:, :, 1] = np.clip(polys[:, :, 1], 0, h - 1) validated_polys = [] validated_tags = [] for poly, tag in zip(polys, tags): if abs(pyclipper.Area(poly)) < 1: continue #clockwise if pyclipper.Orientation(poly): poly = poly[::-1] validated_polys.append(poly) validated_tags.append(tag) return np.array(validated_polys), np.array(validated_tags)
def calcCutingArea(toolPos, newToolPos, toolRadiusScaled, cleared): dist = GeomUtils.magnitude(GeomUtils.sub2v(newToolPos, toolPos)) if dist == 0: return 0, 0 toolCoverArea = getToolCuttingShape(toolPos, newToolPos, toolRadiusScaled) if GeomUtils.anyValidPath(toolCoverArea): #calculate area cp.Clear() cp.AddPaths(toolCoverArea, pyclipper.PT_SUBJECT, True) cp.AddPaths(cleared, pyclipper.PT_CLIP, True) cuttingPolygon = cp.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) cuttingArea = 0 cuttingAreaPerDist = 0 for poly in cuttingPolygon: cuttingArea = cuttingArea + math.fabs(pyclipper.Area(poly)) cuttingAreaPerDist = cuttingArea / dist return cuttingArea, cuttingAreaPerDist else: return 0, 0
def shrink_poly(polys, ratio=0.5): if type(polys) == list: polys = np.array(polys) if ratio == 1: return polys """ 收缩多边形 :param polys: 多边形 :param ratio: 收缩比例 :return: """ area = abs(pyclipper.Area(polys)) # 面积 _perimeter = perimeter(polys) # 周长 pco = pyclipper.PyclipperOffset() if _perimeter: # TODO:不知道为何这样计算??? d = area * (1 - ratio * ratio) / _perimeter pco.AddPath(polys, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) # 缩小后返回多边形 polys_shrink = pco.Execute(-d) else: logger.warning("多边形周长为0") return None if len(polys_shrink) == 0: logger.debug("收缩多边形[面积=%f]失败,使用原有坐标", area) return polys shrinked_bbox = np.array(polys_shrink[0]) return shrinked_bbox
def nms_with_char_cls(boxes, char_scores, overlapThresh, neighbourThresh=0.5, minScore=0, num_neig=0): new_boxes = np.zeros_like(boxes) new_char_scores = np.zeros_like(char_scores) pick = [] suppressed = [False for _ in range(boxes.shape[0])] areas = [ Polygon([(b[0], b[1]), (b[2], b[3]), (b[4], b[5]), (b[6], b[7])]).area for b in boxes ] polygons = pyclipper.scale_to_clipper(boxes[:, :8].reshape((-1, 4, 2))) order = boxes[:, 8].argsort()[::-1] for _i, i in enumerate(order): if suppressed[i] is False: pick.append(i) neighbours = list() for j in order[_i + 1:]: if suppressed[j] is False: try: pc = pyclipper.Pyclipper() pc.AddPath(polygons[i], pyclipper.PT_CLIP, True) pc.AddPaths([polygons[j]], pyclipper.PT_SUBJECT, True) solution = pc.Execute(pyclipper.CT_INTERSECTION) if len(solution) == 0: inter = 0 else: inter = pyclipper.scale_from_clipper( pyclipper.scale_from_clipper( pyclipper.Area(solution[0]))) except: inter = 0 union = areas[i] + areas[j] - inter iou = inter / union if union > 0 else 0 if union > 0 and iou > overlapThresh: suppressed[j] = True if iou > neighbourThresh: neighbours.append(j) if len(neighbours) >= num_neig: neighbours.append(i) temp_scores = (boxes[neighbours, 8] - minScore).reshape( (-1, 1)) new_boxes[i, :8] = (boxes[neighbours, :8] * temp_scores).sum( axis=0) / temp_scores.sum() new_boxes[i, 8] = boxes[i, 8] new_char_scores[i, :] = (char_scores[neighbours, :] * temp_scores).sum( axis=0) / temp_scores.sum() else: for ni in neighbours: suppressed[ni] = False pick.pop() return pick, new_boxes, new_char_scores
def clean_polygon(self, polygon): simple = pyclipper.SimplifyPolygon(polygon, pyclipper.PFT_NONZERO) if simple is None or len(simple) == 0: return None biggest = simple[0] biggest_area = pyclipper.Area( biggest) # 给出端点,求多边形面积,端点顺序一定要是逆时针的,否则结果为负 for i in range(1, len(simple)): area = abs(pyclipper.Area(simple[i])) if area > biggest_area: biggest = simple[i] biggest_area = area clean = pyclipper.CleanPolygon(biggest, self.config['curveTolerance']) if clean is None or len(clean) == 0: return None return clean
def generate_seg(im_size, polys, tags, image_name, scale_ratio): ''' 标签生成 :param im_size: 输入图片尺寸 :param polys: 输入文本区域 :param tags: 忽略的文本区域 tags :param image_name: 图片名称 :param scale_ratio:ground truth的收缩比例饿, 默认值为[0.5, 0.6, 0.7, 0.8, 0.9, 1.0] :return: seg_maps: 不同收缩比例的分割结果,保存在不同的通道中 training_mask: 忽略文本区域的mask ''' h, w = im_size #mark different text poly seg_maps = np.zeros((h, w, 6), dtype=np.uint8) # mask used during traning, to ignore some hard areas training_mask = np.ones((h, w), dtype=np.uint8) ignore_poly_mark = [] for i in range(len(scale_ratio)): seg_map = np.zeros((h, w), dtype=np.uint8) for poly_idx, poly_tag in enumerate(zip(polys, tags)): poly = poly_tag[0] tag = poly_tag[1] # 忽略'*','###','?'等文本区域 if i == 0 and tag: cv2.fillPoly(training_mask, poly.astype(np.int32)[np.newaxis, :, :], 0) ignore_poly_mark.append(poly_idx) # seg map shrinked_polys = [] if poly_idx not in ignore_poly_mark: shrinked_polys = shrink_poly(poly.copy(), scale_ratio[i]) #收缩区域坐标计算 if not len(shrinked_polys) and poly_idx not in ignore_poly_mark: logger.info( "before shrink poly area:{} len(shrinked_poly) is 0,image {}" .format(abs(pyclipper.Area(poly)), image_name)) # if the poly is too small, then ignore it during training cv2.fillPoly(training_mask, poly.astype(np.int32)[np.newaxis, :, :], 0) ignore_poly_mark.append(poly_idx) continue for shrinked_poly in shrinked_polys: seg_map = cv2.fillPoly( seg_map, [np.array(shrinked_poly).astype(np.int32)], 1) seg_maps[..., i] = seg_map return seg_maps, training_mask
def store_to_gd(gerber_data, tracks, pads, regions, apertures, tracksize, isDark): # Stores the existing set of layer data as polygonal data points # This is the equivalent of rasterisation of the draw commands li = len(gerber_data.layers) / 3 # Expand tracks from centrelines based on aperture track_outlines = [] for seg in range(len(tracks)): for vert in range(len(tracks[seg]) - 1): xstart = tracks[seg][vert][0] xend = tracks[seg][vert + 1][0] ystart = tracks[seg][vert][1] yend = tracks[seg][vert + 1][1] singletrack = pyclipper.MinkowskiSum(apertures[tracksize[seg]], \ [[xstart, ystart], [xend, yend]], -1) if len(singletrack) > 1: biggest = [] myarea = 0 for mypath in singletrack: newarea = pyclipper.Area(mypath) if newarea > myarea: biggest = mypath myarea = newarea singletrack = [[]] singletrack[0] = (biggest) track_outlines.extend(singletrack) mergedBounds = union_boundary(track_outlines + pads, regions) # Store data into layers. gerber_data.layers.append( GerberLayer(isDark, str(li) + "_Tracks", track_outlines, type=GerberLayer.TYPE_TRACK)) gerber_data.layers.append( GerberLayer(isDark, str(li) + "_Boundaries", mergedBounds, False, False, "blue", GerberLayer.TYPE_BOUNDARY)) # gerber_data.layers.append(GerberLayer(isDark, str(li) + "_Boundaries", track_outlines + pads, False, False, "blue")) gerber_data.layers.append( GerberLayer(isDark, str(li) + "_Regions", regions, type=GerberLayer.TYPE_REGION)) gerber_data.layers.append( GerberLayer(isDark, str(li) + "_Pads", pads, type=GerberLayer.TYPE_PAD, color="#009000"))
def clipExecute(subjectContours, clipContours, operation, subjectFillType="nonZero", clipFillType="nonZero"): pc = pyclipper.Pyclipper() for i, subjectContour in enumerate(subjectContours): try: pc.AddPath(subjectContour, pyclipper.PT_SUBJECT) except pyclipper.ClipperException: # skip invalid paths with no area if pyclipper.Area(subjectContour) != 0: raise InvalidSubjectContourError( "contour %d is invalid for clipping" % i) for j, clipContour in enumerate(clipContours): try: pc.AddPath(clipContour, pyclipper.PT_CLIP) except pyclipper.ClipperException: # skip invalid paths with no area if pyclipper.Area(clipContour) == 0: raise InvalidClippingContourError( "contour %d is invalid for clipping" % j) bounds = pc.GetBounds() if (bounds.bottom, bounds.left, bounds.top, bounds.right) == (0, 0, 0, 0): # do nothing if there are no paths return [] try: solution = pc.Execute(_operationMap[operation], _fillTypeMap[subjectFillType], _fillTypeMap[clipFillType]) except pyclipper.ClipperException as exc: raise ExecutionError(exc) return [[tuple(p) for p in path] for path in solution]
def shrink_poly(poly, r): try: area_poly = abs(pyclipper.Area(poly)) perimeter_poly = perimeter(poly) poly_s = [] pco = pyclipper.PyclipperOffset() if perimeter_poly: d = area_poly * (1 - r * r) / perimeter_poly pco.AddPath(poly, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) poly_s = pco.Execute(-d) return poly_s except Exception as e: traceback.print_exc() raise e
def generate_seg(im_size, polys, tags, image_name, scale_ratio): ''' :param im_size: input image size :param polys: input text regions :param tags: ignore text regions tags :param image_index: for log :param scale_ratio:ground truth scale ratio, default[0.5, 0.6, 0.7, 0.8, 0.9, 1.0] :return: seg_maps: segmentation results with different scale ratio, save in different channel training_mask: ignore text regions ''' h, w = im_size #mark different text poly seg_maps = np.zeros((h, w, 6), dtype=np.uint8) # mask used during traning, to ignore some hard areas training_mask = np.ones((h, w), dtype=np.uint8) ignore_poly_mark = [] for i in range(len(scale_ratio)): seg_map = np.zeros((h, w), dtype=np.uint8) for poly_idx, poly_tag in enumerate(zip(polys, tags)): poly = poly_tag[0] tag = poly_tag[1] # ignore ### if i == 0 and tag: cv2.fillPoly(training_mask, poly.astype(np.int32)[np.newaxis, :, :], 0) ignore_poly_mark.append(poly_idx) # seg map shrinked_polys = [] if poly_idx not in ignore_poly_mark: shrinked_polys = shrink_poly(poly.copy(), scale_ratio[i]) if not len(shrinked_polys) and poly_idx not in ignore_poly_mark: logger.info( "before shrink poly area:{} len(shrinked_poly) is 0,image {}" .format(abs(pyclipper.Area(poly)), image_name)) # if the poly is too small, then ignore it during training cv2.fillPoly(training_mask, poly.astype(np.int32)[np.newaxis, :, :], 0) ignore_poly_mark.append(poly_idx) continue for shrinked_poly in shrinked_polys: seg_map = cv2.fillPoly( seg_map, [np.array(shrinked_poly).astype(np.int32)], 1) seg_maps[..., i] = seg_map return seg_maps, training_mask
def centerOfMass( polygon ): x = 0 y = 0 p0 = polygon[len(polygon)-1]; for p1 in polygon: second_factor = ((p0[0] * p1[1]) - (p1[0] * p0[1])) x += (p0[0] + p1[0]) * second_factor y += (p0[1] + p1[1]) * second_factor p0 = p1 area = pyclipper.Area(polygon); x = x / 6 / area; y = y / 6 / area; if (x < 0): x = -x; y = -y; return (x,y);
def appendToolPathCheckCollision(of, cp, toolPaths, passToolPath, toolRadiusScaled, cleared, close=False): #appending pass toolpath to the list of cuts #checking the jump line for obstacles global output_point_count if len(passToolPath) < 1: return jumpType = 1 # assume no lift nextPoint = passToolPath[0] if len(toolPaths) != 0 and len( toolPaths[-1]) > 0: #if this is first path: lift to safe height lastPath = toolPaths[-1] lastPoint = lastPath[-1] #make tool shape from last point to next point of = pyclipper.PyclipperOffset() of.AddPath([lastPoint, nextPoint], pyclipper.JT_ROUND, pyclipper.ET_OPENROUND) toolShape = of.Execute(toolRadiusScaled - 2) #check clearance cp.Clear() cp.AddPaths(toolShape, pyclipper.PT_SUBJECT, True) cp.AddPaths(cleared, pyclipper.PT_CLIP, True) crossing = cp.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) collisionArea = 0 for path in crossing: collisionArea = collisionArea + math.fabs(pyclipper.Area(path)) if collisionArea > 0: jumpType = 2 toolPaths.append([[lastPoint[0], lastPoint[1], jumpType], [nextPoint[0], nextPoint[1], jumpType]]) #passToolPath = pyclipper.CleanPolygon(passToolPath,0.7) # this messes up the start point (adds a point to the start of path) output_point_count = output_point_count + len(passToolPath) if len(passToolPath) > 0: if close: passToolPath = GeomUtils.closePath(passToolPath) toolPaths.append(passToolPath)
def create_mask(self, datafield, myCell): named_layers = defaultdict(dict) for l1 in self.points: Polygon = namedtuple('Polygon', ['area', 'points']) pp = Polygon(area=pyclipper.Area(l1), points=l1) if pp.area < 0: if 'holes' in named_layers: named_layers['holes'].append(pp) else: named_layers['holes'] = [pp] elif pp.area > 0: if 'polygon' in named_layers: named_layers['polygon'].append(pp) else: named_layers['polygon'] = [pp] else: raise ValueError('polygon area cannot be zero') for poly in named_layers['polygon']: add_to_mask = True for hole in named_layers['holes']: if abs(hole.area) < abs(poly.area): if utils.is_nested_polygons(hole, poly): datafield.add(poly.points, self.key, holes=hole.points, model='model') myCell.add(gdspy.Polygon(hole.points, layer=81)) add_to_mask = False else: datafield.add(poly.points, self.key, model='model') add_to_mask = False if add_to_mask: datafield.add(poly.points, self.key, model='model') myCell.add(gdspy.Polygon(poly.points, self.key[0], verbose=False))
def process_row(self, row): if row.object_name not in self.classes: return None # Deal with excluded areas row_poly = [(row.xmin, row.ymin), (row.xmin, row.ymax), (row.xmax, row.ymax), (row.xmax, row.ymin)] row_area = (row.xmax - row.xmin) * (row.ymax - row.ymin) for poly in self.exclude: pc = pyclipper.Pyclipper() pc.AddPath(poly, pyclipper.PT_CLIP, True) pc.AddPath(row_poly, pyclipper.PT_SUBJECT, True) inter = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) if len(inter) == 0: continue inter_area = pyclipper.Area(inter[0]) if inter_area / row_area > 0.6: return None # Deal w/ crop crop = self.crop # lazy if not crop: return row if row.xmax < crop.xmin or crop.xmax < row.xmin or \ row.ymax < crop.ymin or crop.ymax < row.ymin: return None xA = min(row.xmax, crop.xmax) yA = min(row.ymax, crop.ymax) xB = max(row.xmin, crop.xmin) yB = max(row.ymin, crop.ymin) inter_area = (xA - xB) * (yA - yB) row_area = (row.xmax - row.xmin) * (row.ymax - row.ymin) if inter_area / row_area < 0.25: return None else: return row
def Execute(op, obj, feat_num, feat, p_scale_factor): global toolGeometry global optimalCutAreaPerDist global iteration_limit_count global total_point_count global total_iteration_count global topZ global toolRadiusScaled global output_point_count global cache_hit_count global cache_pot_count global cache global cp global of global scale_factor scale_factor = p_scale_factor if RELOAD_MODULES: reload(Interpolation) reload(EngagementPoint) reload(GeomUtils) toolDiaScaled = op.tool.Diameter * scale_factor toolRadiusScaled = toolDiaScaled / 2 perf_start_time = time.time() perf_total_len = 0.0 print "toolRadiusScaled: ", toolRadiusScaled helixDiameter = min( op.tool.Diameter, 1000.0 if obj.HelixDiameterLimit.Value == 0.0 else obj.HelixDiameterLimit.Value) print "Helix diameter: ", helixDiameter helixDiameterScaled = helixDiameter * scale_factor stepOver = 0.01 * obj.StepOver # percentage to factor stepOverDistanceScaled = toolDiaScaled * stepOver finishPassOffset = 1.0 * obj.Tolerance / 2 cache_hit_count = 0 cache_pot_count = 0 cache = {} output_point_count = 0 topZ = op.stock.Shape.BoundBox.ZMax #initialization of = pyclipper.PyclipperOffset() cp = pyclipper.Pyclipper() toleranceScaled = int(obj.Tolerance * scale_factor) stepScaled = 10 toolGeometry = genToolGeometry(toolRadiusScaled + 1) # intitalization = calculate slot cutting area per step i.e. 100% step over sceneInit(toolRadiusScaled, topZ, scale_factor) distScaled = toolRadiusScaled / 2 slotStep = translatePath(toolGeometry, [0, distScaled]) cp.Clear() cp.AddPath(toolGeometry, pyclipper.PT_SUBJECT, True) cp.AddPath(slotStep, pyclipper.PT_CLIP, True) crossing = cp.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) referenceCutArea = pyclipper.Area(crossing[0]) fullSlotAreaPerDist = referenceCutArea / distScaled bound_extend = int(toolDiaScaled) #optimalCutAreaPerDistance (in scaled units) optimalCutAreaPerDist = stepOver * fullSlotAreaPerDist print "Optimal APD: ", optimalCutAreaPerDist, " Clipper scale factor: ", scale_factor, " Tolerance: ", obj.Tolerance, " Tolerance scaled: ", toleranceScaled try: # find cut region toolpath polygons of.Clear() of.AddPaths(feat, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) cut_region_tp = of.Execute(-int(finishPassOffset * scale_factor) - toolRadiusScaled) cut_region_tp_polytree = of.Execute2( -int(finishPassOffset * scale_factor) - toolRadiusScaled) cut_region_tp = pyclipper.CleanPolygons(cut_region_tp) sceneDrawPaths("BOUNDARY", cut_region_tp, scale_factor, (1, 0, 0), True) cleared, startPoint = findStartPoint(op, feat_num, cut_region_tp, cut_region_tp_polytree, helixDiameterScaled / 2, toolRadiusScaled, scale_factor) if cleared == None: return [], [0, 0] cleared = pyclipper.CleanPolygons(cleared) toolPos = startPoint of.Clear() of.AddPath([startPoint, startPoint], pyclipper.JT_ROUND, pyclipper.ET_OPENROUND) helixTp = of.Execute(helixDiameterScaled / 2) sceneDrawPaths("TOOLPATH", helixTp, scale_factor, (0, 0, 1), True) EngagementPoint.Initialize(cut_region_tp, toolRadiusScaled, stepScaled, scale_factor) total_point_count = 1 total_iteration_count = 0 iteration_limit_count = 0 toolPaths = [] no_cut_count = 0 over_cut_count = 0 toolPos = [startPoint[0], startPoint[1] - helixDiameterScaled / 2] toolDir = [1.0, 0.0] firstEngagePoint = True last_tool_gui_update = 0 pas = 0 while True: pas = pas + 1 #print "pass:"******"finding next pass engange point... pas:"******"Pass: %d\n"%pas) if toolPos == None: Console.PrintMessage("next engage point not found\n") break #nothing more to cut passToolPath = [] toClearPath = [] cumulativeCuttingArea = 0 no_cut_count = 0 reachedBoundaryPoint = None isOutside = False gyro = [toolDir] * 5 toolDir = GeomUtils.normalize(GeomUtils.sumv(gyro)) if SHOW_MARKERS: sceneClearPaths("ENGAGE") sceneDrawToolDir("ENGAGE", toolPos, toolDir, scale_factor, (0, 1, 0)) engagePoint = toolPos #iteration through the points on path/pass i = 0 deflectionAngle = math.pi #init del deflectionAngleHistory[:] distToBoundary = 0 while True: #points i = i + 1 sceneUpdateGui() if obj.StopProcessing: break #Console.PrintMessage("findNextPoint: %d =================================================================\n"%i) total_point_count = total_point_count + 1 toolDir = GeomUtils.normalize(GeomUtils.sumv(gyro)) #distance to the boundary line #if distToBoundary<toolRadiusScaled: clp, distToBoundary = GeomUtils.getClosestPointOnPaths( cut_region_tp, toolPos) distToEngagePoint = GeomUtils.magnitude( GeomUtils.sub2v(toolPos, engagePoint)) relDistToBoundary = 2.0 * distToBoundary / toolRadiusScaled minCutAreaPerDist = optimalCutAreaPerDist / 3 + 1 #if we are away from end boundary line, try making the optimal cut if relDistToBoundary > 1 or distToEngagePoint < toolRadiusScaled: targetArea = optimalCutAreaPerDist else: #decrease the cut area if we are close to boundary, adds a little bit of smoothing to the end of cut targetArea = relDistToBoundary * \ (optimalCutAreaPerDist-minCutAreaPerDist) + minCutAreaPerDist if distToBoundary < toolRadiusScaled or distToEngagePoint < toolRadiusScaled: stepScaled = toleranceScaled * 2 elif math.fabs(deflectionAngle) > 0.0001: stepScaled = 4.0 / deflectionAngle else: stepScaled = toleranceScaled * 4 if stepScaled < toleranceScaled * 2: stepScaled = toleranceScaled * 2 if stepScaled > toolRadiusScaled / 2: stepScaled = toolRadiusScaled / 2 # # Find next point with optimal cut # bound_box = [ [toolPos[0] - bound_extend, toolPos[1] - bound_extend], [toolPos[0] + bound_extend, toolPos[1] - bound_extend], [toolPos[0] + bound_extend, toolPos[1] + bound_extend], [toolPos[0] - bound_extend, toolPos[1] + bound_extend] ] cp.Clear() cp.AddPath(bound_box, pyclipper.PT_SUBJECT, True) cp.AddPaths(cleared, pyclipper.PT_CLIP, True) cleared_bounded = cp.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) if not GeomUtils.anyValidPath(cleared_bounded): cleared_bounded = cleared newToolPos, newToolDir, cuttingAreaPerDist, cuttingArea, deflectionAngle = findNextPoint( obj, op, of, cp, cleared_bounded, toolPos, toolDir, toolRadiusScaled, stepScaled, targetArea, scale_factor) # # CHECK if we reached the the boundary # if distToBoundary < toolRadiusScaled and isOutsideCutRegion( newToolPos, cut_region_tp_polytree, True): isOutside = True reachedBoundaryPoint = GeomUtils.getIntersectionPointLWP( [toolPos, newToolPos], cut_region_tp) if reachedBoundaryPoint != None: #print "reachedBoundaryPoint:", reachedBoundaryPoint #showTool("TL", reachedBoundaryPoint, scale_factor, (1, 0, 0)) newToolPos = reachedBoundaryPoint else: newToolPos = toolPos cuttingArea, cuttingAreaPerDist = calcCutingArea( toolPos, newToolPos, toolRadiusScaled, cleared_bounded) if cuttingArea > 3 * cuttingAreaPerDist + 10 and cuttingAreaPerDist > 2 * optimalCutAreaPerDist + 10: over_cut_count = over_cut_count + 1 Console.PrintMessage("Break: over cut (%d %f/%f)\n" % (over_cut_count, cuttingAreaPerDist, optimalCutAreaPerDist)) break else: over_cut_count = 0 if len(toClearPath) == 0: toClearPath.append(toolPos) toClearPath.append(newToolPos) if firstEngagePoint: if len(toClearPath) > 10: of.Clear() of.AddPath(toClearPath, pyclipper.JT_ROUND, pyclipper.ET_OPENROUND) toolCoverArea = of.Execute(toolRadiusScaled + 1)[0] cleared = expandClearedArea(cp, toolCoverArea, cleared) toClearPath = [] if cuttingArea > 0: # cut is OK, record it cumulativeCuttingArea = cumulativeCuttingArea + cuttingArea if time.time() - last_tool_gui_update > GUI_UPDATE_PERIOD: if SHOW_MARKERS: sceneClearPaths("TP") sceneDrawFilledTool("TP", newToolPos, scale_factor, (0, 0, 1)) sceneDrawToolDir("TP", newToolPos, newToolDir, scale_factor, (0, 0, 1)) sceneClearPaths("PTP") sceneDrawPath("PTP", passToolPath, scale_factor, (0, 0, 1)) # sceneClearPaths("CL_BOUNDED") # sceneDrawPaths("CL_BOUNDED", cleared_bounded,scale_factor,(1,1,0),True) last_tool_gui_update = time.time() #append next point to toolpath perf_total_len = perf_total_len + stepScaled if i == 0: passToolPath.append( toolPos) #append first point to toolpath passToolPath.append(newToolPos) toolPos = newToolPos gyro.append(newToolDir) gyro.pop(0) no_cut_count = 0 else: #no cut #print "no cut:", no_cut_count no_cut_count = no_cut_count + 1 newToolDir = toolDir break # if no_cut_count > 1: # print "break: no cut" # break if isOutside: # next valid cut not found #print "Breaking: reached boundary" break #distToBoundary = distToBoundary-stepScaled #END OF POINTS INTERATION #expand cleared area if len(toClearPath) > 0: of.Clear() of.AddPath(toClearPath, pyclipper.JT_ROUND, pyclipper.ET_OPENROUND) toolCoverArea = of.Execute(toolRadiusScaled + 1)[0] cleared = expandClearedArea(cp, toolCoverArea, cleared) toClearPath = [] if cumulativeCuttingArea > stepScaled * stepOver * referenceCutArea / 40: #did we cut something significant? sceneClearPaths("PTP") sceneDrawPath("TOOLPATH", passToolPath, scale_factor) passToolPath = GeomUtils.cleanPath(passToolPath, CLEAN_PATH_TOLERANCE) appendToolPathCheckCollision(of, cp, toolPaths, passToolPath, toolRadiusScaled, cleared) if over_cut_count > 5: Console.PrintError( "Break: WARNING: resulting toolpath may be incomplete! (Hint: try changing numeric precision or StepOver)\n" ) break #FIND NEXT ENGAGING POINT if firstEngagePoint: EngagementPoint.moveToClosestPoint(newToolPos) firstEngagePoint = False else: moveDistance = stepOverDistanceScaled / 4 + 1 if not EngagementPoint.moveForwardToCutThreshold( cleared, moveDistance, moveDistance * 2, 1.5 * optimalCutAreaPerDist * moveDistance): break #clear around the engagement point toolPos, toolDir = EngagementPoint.getCurrentPoint() performance = 1.0 * perf_total_len / scale_factor / ( time.time() - perf_start_time) # mm/s Console.PrintMessage( "Passes: %s, Toolpaths: %d, Output Points: %d, Processed Points: %d, Avg.Iterations: %f, Exceeded: %d, Perf.: %f mm/s, Cut shape cache hit: %d/%d (%f perc.)\n" % (pas, len(toolPaths), output_point_count, total_point_count, 1.0 * total_iteration_count / total_point_count, iteration_limit_count, performance, cache_hit_count, cache_pot_count, 100 * cache_hit_count / (cache_pot_count + 0.1))) #generate finishing pass sceneUpdateGui() passToolPath = [] of.Clear() of.AddPaths(feat, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) finishing = of.Execute2(-toolRadiusScaled) # add only paths containing the startPoint and their childs for child in finishing.Childs: if pyclipper.PointInPolygon(startPoint, child.Contour) != 0: appendToolPathCheckCollision( of, cp, toolPaths, GeomUtils.cleanPath(child.Contour, CLEAN_PATH_TOLERANCE / 2), toolRadiusScaled, cleared, True) for hole in child.Childs: appendToolPathCheckCollision( of, cp, toolPaths, GeomUtils.cleanPath(hole.Contour, CLEAN_PATH_TOLERANCE / 2), toolRadiusScaled, cleared, True) # append the return to the initial point (and check collision) if len(toolPaths) > 0 and len(toolPaths[0]) > 0: appendToolPathCheckCollision( of, cp, toolPaths, [[toolPaths[0][0][0], toolPaths[0][0][1]]], toolRadiusScaled, cleared, True) except: sceneClean() raise sceneClean() return toolPaths, startPoint
def parse(f): dxf = ezdxf.readfile(f) mds = dxf.blocks listShapes = [] for e in mds.__iter__(): s = Shape() dicLayerPolyline = {1: s.cutPolyline, 14: s.shapePolyline} polylineFragments = [] noDuplicates = [] s.fileName = e.name for ez in e.__iter__(): """ This will ignore layer which are not a number TODO: change it later when we need a better dxf parser """ try: layer = int(ez.get_dxf_attrib("layer")) except: continue if ez.dxftype() == "POLYLINE": vertList = list(ez.points()) p = Polyline() p.listToPolyline(vertList) if pyclipper.Area(p.polylineToTuple()) < 0: vertList = vertList[::-1] if ez.is_closed: # closing polyline if the attribute is_closed is true vertList.append(vertList[0]) if layer == 8: # if layer is non permanant marking s.dicMarkings[8].append(Polyline()) dicLayerPolyline[8] = s.dicMarkings[8][-1] if (layer in dicLayerPolyline and len(dicLayerPolyline[layer].vertices) > 2): polylineFragments.append(vertList) else: if ( layer not in dicLayerPolyline ): # if layer is not in a specific layer of shape (unusedLayer) pUnused = Polyline() if layer not in s.unusedLayer: s.unusedLayer[layer] = [pUnused] for idx, v in enumerate(vertList): if v == vertList[ idx - 1] and idx != 0: # skip duplicate vertex continue if layer in dicLayerPolyline: addVertexToLayer(dicLayerPolyline[layer], convert2Vertex(v)) else: # add to unused layer addVertexToLayer(pUnused, convert2Vertex(v)) elif ez.dxftype() == "POINT": if layer == 13: # adding marking points which are in layer 13 s.dicMarkings[13].append(Polyline()) dicLayerPolyline[13] = s.dicMarkings[13][-1] addVertexToLayer(dicLayerPolyline[13], convert2Vertex(ez.dxf.location)) addVertexToLayer( dicLayerPolyline[13], convert2Vertex(ez.dxf.location) ) # need to add it twice to have the points in the polyline elif (ez.dxftype() == "TEXT" and layer != 19 and ez.get_dxf_attrib("text")[0] == "#"): coord = ez.get_dxf_attrib("insert") tag = ez.get_dxf_attrib("text") newTextVertex = Vertex(coord[0], coord[1], tag) duplicate = False # avoid duplicate vertex for v in noDuplicates: if ( newTextVertex.is_equal(v) and newTextVertex.name == v.name and layer not in [4, 80, 81, 82, 83] ): # if duplicate point in notch don't set it to duplicate duplicate = True continue for mark in s.dicMarkings[8] + s.dicMarkings[13]: for v in mark.vertices: if newTextVertex.is_equal(v): v.name = newTextVertex.name if ( duplicate ): # If vertex is a duplicate, do not append to notches or textMarkings continue if int(layer) in [4, 80, 81, 82, 83] and isNotchValid( newTextVertex, s.notches): s.notches.append( Notch( _x=newTextVertex.x, _y=newTextVertex.y, _name=newTextVertex.name, )) else: s.textMarkings.append(newTextVertex) noDuplicates.append(newTextVertex) elif ez.dxftype() == "LINE" and layer == 7: v1 = Vertex(ez.dxf.start[0], ez.dxf.start[1]) v2 = Vertex(ez.dxf.end[0], ez.dxf.end[1]) s.grainPolyline.vertices = [v1, v2] if polylineFragments: frags = [] for p in polylineFragments: poly = [] for v in p: poly.append(convert2Vertex(v)) frags.append(poly) frags.insert(0, s.cutPolyline.vertices) s.cutPolyline.vertices = mergePolylinesFragments(frags) # Assign rules to polylines in each layer: for layer in s.allPolyLayers: content = eval("s." + layer) if type(content) == type([]): for p in content: for tag in s.textMarkings: assignRulToShape(p, tag) else: for tag in s.textMarkings: assignRulToShape(content, tag) for layer in list(s.dicMarkings.keys()): s.markings.extend(s.dicMarkings[layer]) if (len(s.cutPolyline.vertices) or s.markings ): # adding to the listShapes only if the shape has vertices listShapes.append(s) return listShapes
def test_area(self): with self.assertWarns(DeprecationWarning): pyclipper.Area(PATH_SUBJ_1)
def lf_non_max_suppression_area(lf_xy_positions, confidences, overlap_range, overlap_thresh): # lf_xy_positions = np.concatenate([l.data.cpu().numpy()[None,...] for l in lf_xy_positions]) # lf_xy_positions = lf_xy_positions[:,:,:2,:2] # print lf_xy_positions # raw_input() lf_xy_positions = [l[:, :2, :2] for l in lf_xy_positions] #this assumes equal length positions # lf_xy_positions = np.concatenate([l[None,...] for l in lf_xy_positions]) # lf_xy_positions = lf_xy_positions[:,:,:2,:2] c = confidences bboxes = [] center_lines = [] scales = [] for i in range(len(lf_xy_positions)): pts = lf_xy_positions[i] # for i in xrange(lf_xy_positions.shape[1]): # pts = lf_xy_positions[:,i,:] if overlap_range is not None: pts = pts[overlap_range[0]:overlap_range[1]] f = pts[0] delta = f[:, 0] - f[:, 1] scale = np.sqrt((delta**2).sum()) scales.append(scale) # ls = pts[:,:,0].tolist() + pts[:,:,1][::-1].tolist() # ls = [[int(x[0]), int(x[1])] for x in ls] # poly_regions.append(ls) center_lines.append((pts[:, :, 0] + pts[:, :, 1]) / 2.0) min_x = pts[:, 0].min() max_x = pts[:, 0].max() min_y = pts[:, 1].min() max_y = pts[:, 1].max() bboxes.append((min_x, min_y, max_x, max_y)) bboxes = np.array(bboxes) if len(bboxes.shape) < 2: return [] x1 = bboxes[:, 0] y1 = bboxes[:, 1] x2 = bboxes[:, 2] y2 = bboxes[:, 3] area = (x2 - x1 + 1) * (y2 - y1 + 1) idxs = np.argsort(c) overlapping_regions = [] pick = [] while len(idxs) > 0: last = len(idxs) - 1 i = idxs[last] pick.append(i) xx1 = np.maximum(x1[i], x1[idxs[:last]]) yy1 = np.maximum(y1[i], y1[idxs[:last]]) xx2 = np.minimum(x2[i], x2[idxs[:last]]) yy2 = np.minimum(y2[i], y2[idxs[:last]]) # compute the width and height of the bounding box w = np.maximum(0, xx2 - xx1 + 1) h = np.maximum(0, yy2 - yy1 + 1) # compute the ratio of overlap overlap_bb = (w * h) / area[idxs[:last]] overlap = [] for step, j in enumerate(idxs[:last]): #Skip anything that does't actually have any overlap if overlap_bb[step] < 0.1: overlap.append(0) continue path0 = center_lines[i] path1 = center_lines[j] path = np.concatenate([path0, path1[::-1]]) path = [[int(x[0]), int(x[1])] for x in path] expected_scale = (scales[i] + scales[j]) / 2.0 one_off_area = expected_scale**2 * (path0.shape[0] + path1.shape[0]) / 2.0 simple_path = pyclipper.SimplifyPolygon(path, pyclipper.PFT_NONZERO) inter_area = 0 for path in simple_path: inter_area += abs(pyclipper.Area(path)) area_ratio = inter_area / one_off_area area_ratio = 1.0 - area_ratio overlap.append(area_ratio) overlap = np.array(overlap) to_delete = np.concatenate( ([last], np.where(overlap > overlap_thresh)[0])) idxs = np.delete(idxs, to_delete) return pick
def nms_with_char_cls(boxes, char_scores, overlapThresh, neighbourThresh=0.5, minScore=0, num_neig=0): new_boxes = np.zeros_like(boxes) new_char_scores = np.zeros_like(char_scores) pick = [] suppressed = [False for _ in range(boxes.shape[0])] areas = [ Polygon([(b[0], b[1]), (b[2], b[3]), (b[4], b[5]), (b[6], b[7])]).area for b in boxes ] polygons = pyclipper.scale_to_clipper(boxes[:, :8].reshape((-1, 4, 2))) centers = [[(p[0][0] + p[1][0] + p[2][0] + p[3][0]) / 4, (p[0][1] + p[1][1] + p[2][1] + p[3][1]) / 4] for p in polygons] sides = [] for p in polygons: x_coordinates = [p[0][0], p[1][0], p[2][0], p[3][0]] y_coordinates = [p[0][1], p[1][1], p[2][1], p[3][1]] side_x = max(x_coordinates) - min(x_coordinates) side_y = max(y_coordinates) - min(y_coordinates) sides.append([side_x, side_y]) order = boxes[:, 8].argsort()[::-1] print('nms with char cls...') for _i, i in enumerate(tqdm(order)): if suppressed[i] is False: pick.append(i) neighbours = list() for j in order[_i + 1:]: var_x = ((sides[i][0] + sides[j][0]) / 2 - abs(centers[i][0] - centers[j][0])) > 0 var_y = ((sides[i][1] + sides[j][1]) / 2 - abs(centers[i][1] - centers[j][1])) > 0 if var_x and var_y and (suppressed[j] is False): pc = pyclipper.Pyclipper() pc.AddPath(polygons[i], pyclipper.PT_CLIP, True) pc.AddPaths([polygons[j]], pyclipper.PT_SUBJECT, True) solution = pc.Execute(pyclipper.CT_INTERSECTION) if len(solution) == 0: inter = 0 else: inter = pyclipper.scale_from_clipper( pyclipper.scale_from_clipper( pyclipper.Area(solution[0]))) union = areas[i] + areas[j] - inter iou = inter / union if union > 0 else 0 if union > 0 and iou > overlapThresh: suppressed[j] = True if iou > neighbourThresh: neighbours.append(j) if len(neighbours) >= num_neig: neighbours.append(i) temp_scores = (boxes[neighbours, 8] - minScore).reshape( (-1, 1)) new_boxes[i, :8] = (boxes[neighbours, :8] * temp_scores).sum( axis=0) / temp_scores.sum() new_boxes[i, 8] = boxes[i, 8] new_char_scores[i, :] = (char_scores[neighbours, :] * temp_scores).sum( axis=0) / temp_scores.sum() else: for ni in neighbours: suppressed[ni] = False pick.pop() return pick, new_boxes, new_char_scores
import pyclipper import numpy as np subj = [253, 285, 824, 296, 833, 435, 283, 413] clipp = [215, 267, 853, 296, 826, 449, 246, 414] subj = np.array(subj, dtype=np.float) clipp = np.array(clipp, dtype=np.float) subj = subj.reshape((4, 2)) clipp = clipp.reshape((4, 2)) pc = pyclipper.Pyclipper() invalid = False try: bool_subj = pc.AddPath(subj, pyclipper.PT_SUBJECT, True) bool_clipp = pc.AddPath(clipp, pyclipper.PT_CLIP, True) except pyclipper.ClipperException as e: invalid = True if not invalid: inter_path = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD) union_path = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_EVENODD) inter = pyclipper.Area(inter_path[0]) if len(inter_path) > 0 else .0 uunion = pyclipper.Area(union_path[0]) if len(union_path) > 0 else .0 ovr = inter / max(uunion, 1.) # 防止0除溢出 else: ovr = .0 pc.Clear() print("IoU: {:3f}".format(ovr))
def evaluate_polygonal_results(ground_truth, detection_results, iou_thresh=0.5): """Evaluate polygonal text detection results and return TP, FP, FN. # Arguments ground_truth: List of ground truth polygonal with shape (objects, 4 x xy) detection_results: List of corresponding detection polygonal with shape (objects, 4 x xy) image_size: Input size of detector network. iou_thresh: Minimum intersection over union required to associate a detected polygon box to a ground truth polygon box. # Returns TP: True Positive detections FP: False Positive detections FN: False Negative detections """ # we do not sort by confidence here # all detections are of class text gt = ground_truth dt = detection_results TP = [] FP = [] FN_sum = 0 num_groundtruth_boxes = 0 # has to be TP_sum + FN_sum num_detections = 0 for i in range(len(gt)): # samples gt_polys = [ np.reshape(gt[i][j, :], (-1, 2)) for j in range(len(gt[i])) ] dt_polys = [ np.reshape(dt[i][j, :], (-1, 2)) for j in range(len(dt[i])) ] # prepare polygones, pyclipper, is much faster scale = 1e5 gt_polys = [np.asarray(p * scale, dtype=np.int64) for p in gt_polys] dt_polys = [np.asarray(p * scale, dtype=np.int64) for p in dt_polys] # perpare polygones, shapely #gt_polys = [geometry.Polygon(p) for p in gt_polys] #dt_polys = [geometry.Polygon(p) for p in dt_polys] num_dt = len(dt_polys) num_gt = len(gt_polys) num_groundtruth_boxes += num_gt num_detections += num_dt TP_img = np.zeros(num_dt) FP_img = np.zeros(num_dt) assignement = np.zeros(num_gt, dtype=np.bool) for k in range(len(dt[i])): # dt poly1 = dt_polys[k] gt_iou = [] for j in range(len(gt[i])): # gt poly2 = gt_polys[j] # intersection over union, pyclipper pc = pyclipper.Pyclipper() pc.AddPath(poly1, pyclipper.PT_CLIP, True) pc.AddPath(poly2, pyclipper.PT_SUBJECT, True) I = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) if len(I) > 0: U = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD) Ia = pyclipper.Area(I[0]) Ua = pyclipper.Area(U[0]) IoU = Ia / Ua else: IoU = 0.0 # intersection over union, shapely, much slower #I = poly1.intersection(poly2) #if not I.is_empty: # Ia = I.area # Ua = poly1.area + poly2.area - Ia # IoU = Ia / Ua #else: # IoU = 0.0 gt_iou.append(IoU) #print(IoU) gt_iou = np.array(gt_iou) max_gt_idx = np.argmax(gt_iou) dt_idx = k if gt_iou[max_gt_idx] > iou_thresh: if not assignement[ max_gt_idx]: # todo: use highest iou, not first TP_img[dt_idx] = 1 assignement[max_gt_idx] = True continue FP_img[dt_idx] = 1 FN_img_sum = np.sum(np.logical_not(assignement)) TP.append(TP_img) FP.append(FP_img) FN_sum += FN_img_sum TP = np.concatenate(TP) FP = np.concatenate(FP) TP_sum = np.sum(TP) FP_sum = np.sum(FP) return TP_sum, FP_sum, FN_sum recall = TP_sum / (TP_sum + FN_sum) precision = TP_sum / (TP_sum + FP_sum) print('TP %i FP %i FN %i' % (TP_sum, FP_sum, FN_sum)) print('precision, recall, f-measure: %.2f, %.2f, %.2f' % (precision, recall, fscore(precision, recall)))
def assign_path_to_region(out, regions): trimmed_polys = e2e_postprocessing.get_trimmed_polygons(out) polys = [] for t in trimmed_polys: p = t[:, :2, 0].tolist() + t[::-1, :2, 1].tolist() polys.append(p) scores = [] for i, r in enumerate(regions): region_poly = r['bounding_poly'] scores_i = [] scores.append(scores_i) for p in polys: pc = pyclipper.Pyclipper() try: pc.AddPath(p, pyclipper.PT_CLIP, True) except: scores_i.append(0) # print p print("Failed to assign text line, probably not an issue") continue pc.AddPath(region_poly, pyclipper.PT_SUBJECT, True) solution = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) # pts = np.array(region_poly, np.int32) # pts = pts.reshape((-1,1,2)) # cv2.polylines(img,[pts],True,(0,0,255), thickness=3) area = 0 for path in solution: area += pyclipper.Area(path) scores_i.append(area) background_scores = [] total_areas = [] for p in polys: pc = pyclipper.Pyclipper() try: pc.AddPath(p, pyclipper.PT_CLIP, True) except: total_areas.append(np.inf) background_scores.append(np.inf) # print p print("Failed to assign text line, probably not an issue") continue pc.AddPaths([r['bounding_poly'] for r in regions], pyclipper.PT_SUBJECT, True) solution = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) area = 0 for path in solution: area += pyclipper.Area(path) simple_path = pyclipper.SimplifyPolygon(p, pyclipper.PFT_NONZERO) total_area = 0 for path in simple_path: total_area += pyclipper.Area(path) total_areas.append(total_area) background_score = total_area - area background_scores.append(background_score) return np.array(scores), np.array(background_scores), np.array(total_areas)