def crop_bboxes(self, bboxes, canvas_bbox): kept_bboxes = [] kept_inx = [] canvas_poly = eval_utils.box2polygon(canvas_bbox) tl = canvas_bbox[0:2] for idx, bbox in enumerate(bboxes): poly = eval_utils.box2polygon(bbox) area, inters = eval_utils.poly_intersection(poly, canvas_poly, return_poly=True) if area == 0: continue xmin, ymin, xmax, ymax = inters.bounds kept_bboxes += [ np.array( [xmin - tl[0], ymin - tl[1], xmax - tl[0], ymax - tl[1]], dtype=np.float32) ] kept_inx += [idx] if len(kept_inx) == 0: return np.array([]).astype(np.float32).reshape(0, 4), kept_inx return np.stack(kept_bboxes), kept_inx
def test_poly_intersection(): # test unsupported type with pytest.raises(AssertionError): utils.poly_intersection(0, 1) # test non-overlapping polygons points = [0, 0, 0, 1, 1, 1, 1, 0] points1 = [10, 20, 30, 40, 50, 60, 70, 80] poly = utils.points2polygon(points) poly1 = utils.points2polygon(points1) area_inters, _ = utils.poly_intersection(poly, poly1) assert area_inters == 0 # test overlapping polygons area_inters, _ = utils.poly_intersection(poly, poly) assert area_inters == 1
def random_crop_flip(self, results): image = results['img'] polygons = results['gt_masks'].masks ignore_polygons = results['gt_masks_ignore'].masks all_polygons = polygons + ignore_polygons if len(polygons) == 0: return results if np.random.random() >= self.crop_ratio: return results h, w, _ = results['img_shape'] area = h * w pad_h = int(h * self.pad_ratio) pad_w = int(w * self.pad_ratio) h_axis, w_axis = self.generate_crop_target(image, all_polygons, pad_h, pad_w) if len(h_axis) == 0 or len(w_axis) == 0: return results attempt = 0 while attempt < 10: attempt += 1 polys_keep = [] polys_new = [] ign_polys_keep = [] ign_polys_new = [] xx = np.random.choice(w_axis, size=2) xmin = np.min(xx) - pad_w xmax = np.max(xx) - pad_w xmin = np.clip(xmin, 0, w - 1) xmax = np.clip(xmax, 0, w - 1) yy = np.random.choice(h_axis, size=2) ymin = np.min(yy) - pad_h ymax = np.max(yy) - pad_h ymin = np.clip(ymin, 0, h - 1) ymax = np.clip(ymax, 0, h - 1) if (xmax - xmin) * (ymax - ymin) < area * self.min_area_ratio: # area too small continue pts = np.stack([[xmin, xmax, xmax, xmin], [ymin, ymin, ymax, ymax]]).T.astype(np.int32) pp = plg(pts) fail_flag = False for polygon in polygons: ppi = plg(polygon[0].reshape(-1, 2)) ppiou = eval_utils.poly_intersection(ppi, pp) if np.abs(ppiou - float(ppi.area)) > self.epsilon and \ np.abs(ppiou) > self.epsilon: fail_flag = True break elif np.abs(ppiou - float(ppi.area)) < self.epsilon: polys_new.append(polygon) else: polys_keep.append(polygon) for polygon in ignore_polygons: ppi = plg(polygon[0].reshape(-1, 2)) ppiou = eval_utils.poly_intersection(ppi, pp) if np.abs(ppiou - float(ppi.area)) > self.epsilon and \ np.abs(ppiou) > self.epsilon: fail_flag = True break elif np.abs(ppiou - float(ppi.area)) < self.epsilon: ign_polys_new.append(polygon) else: ign_polys_keep.append(polygon) if fail_flag: continue else: break cropped = image[ymin:ymax, xmin:xmax, :] select_type = np.random.randint(3) if select_type == 0: img = np.ascontiguousarray(cropped[:, ::-1]) elif select_type == 1: img = np.ascontiguousarray(cropped[::-1, :]) else: img = np.ascontiguousarray(cropped[::-1, ::-1]) image[ymin:ymax, xmin:xmax, :] = img results['img'] = image if len(polys_new) + len(ign_polys_new) != 0: height, width, _ = cropped.shape if select_type == 0: for idx, polygon in enumerate(polys_new): poly = polygon[0].reshape(-1, 2) poly[:, 0] = width - poly[:, 0] + 2 * xmin polys_new[idx] = [poly.reshape(-1, )] for idx, polygon in enumerate(ign_polys_new): poly = polygon[0].reshape(-1, 2) poly[:, 0] = width - poly[:, 0] + 2 * xmin ign_polys_new[idx] = [poly.reshape(-1, )] elif select_type == 1: for idx, polygon in enumerate(polys_new): poly = polygon[0].reshape(-1, 2) poly[:, 1] = height - poly[:, 1] + 2 * ymin polys_new[idx] = [poly.reshape(-1, )] for idx, polygon in enumerate(ign_polys_new): poly = polygon[0].reshape(-1, 2) poly[:, 1] = height - poly[:, 1] + 2 * ymin ign_polys_new[idx] = [poly.reshape(-1, )] else: for idx, polygon in enumerate(polys_new): poly = polygon[0].reshape(-1, 2) poly[:, 0] = width - poly[:, 0] + 2 * xmin poly[:, 1] = height - poly[:, 1] + 2 * ymin polys_new[idx] = [poly.reshape(-1, )] for idx, polygon in enumerate(ign_polys_new): poly = polygon[0].reshape(-1, 2) poly[:, 0] = width - poly[:, 0] + 2 * xmin poly[:, 1] = height - poly[:, 1] + 2 * ymin ign_polys_new[idx] = [poly.reshape(-1, )] polygons = polys_keep + polys_new ignore_polygons = ign_polys_keep + ign_polys_new results['gt_masks'] = PolygonMasks(polygons, *(image.shape[:2])) results['gt_masks_ignore'] = PolygonMasks(ignore_polygons, *(image.shape[:2])) return results
def test_poly_intersection(): # test unsupported type with pytest.raises(AssertionError): utils.poly_intersection(0, 1) # test non-overlapping polygons points = [0, 0, 0, 1, 1, 1, 1, 0] points1 = [10, 20, 30, 40, 50, 60, 70, 80] points2 = [0, 0, 0, 0, 0, 0, 0, 0] # Invalid polygon points3 = [0, 0, 0, 1, 1, 0, 1, 1] # Self-intersected polygon points4 = [0.5, 0, 1.5, 0, 1.5, 1, 0.5, 1] poly = utils.points2polygon(points) poly1 = utils.points2polygon(points1) poly2 = utils.points2polygon(points2) poly3 = utils.points2polygon(points3) poly4 = utils.points2polygon(points4) area_inters = utils.poly_intersection(poly, poly1) assert area_inters == 0 # test overlapping polygons area_inters = utils.poly_intersection(poly, poly) assert area_inters == 1 area_inters = utils.poly_intersection(poly, poly4) assert area_inters == 0.5 # test invalid polygons assert utils.poly_intersection(poly2, poly2) == 0 assert utils.poly_intersection(poly3, poly3, invalid_ret=1) == 1 # The return value depends on the implementation of the package assert utils.poly_intersection(poly3, poly3, invalid_ret=None) == 0.25 # test poly return _, poly = utils.poly_intersection(poly, poly4, return_poly=True) assert isinstance(poly, Polygon) _, poly = utils.poly_intersection( poly3, poly3, invalid_ret=None, return_poly=True) assert isinstance(poly, Polygon) _, poly = utils.poly_intersection( poly2, poly3, invalid_ret=1, return_poly=True) assert poly is None