Ejemplo n.º 1
0
 def setUp(self):
     self.exterior = [[10, 10], [40, 10], [30, 40], [10, 30]]
     self.interiors = [[[20, 20], [30, 20], [30, 30], [20, 30]]]
     self.poly = Polygon(exterior=row_col_list_to_points(
         self.exterior, flip_row_col_order=True),
                         interior=[
                             row_col_list_to_points(self.interiors[0],
                                                    flip_row_col_order=True)
                         ])
Ejemplo n.º 2
0
 def draw_mask(exterior_p, interior_p, h, w):
     mask = np.zeros((h, w), dtype=np.uint8)
     poly = Polygon(exterior=row_col_list_to_points(exterior_p),
                    interior=[
                        row_col_list_to_points(interior)
                        for interior in interior_p
                    ])
     poly.draw(mask, color=1)
     return mask
Ejemplo n.º 3
0
 def approx_dp(self, epsilon):
     '''
     The function approx_dp approximates a polygonal curve with the specified precision
     :param epsilon: Parameter specifying the approximation accuracy. This is the maximum distance between the original curve and its approximation.
     :return: Poligon class object
     '''
     exterior_np = self._approx_ring_dp(self.exterior_np, epsilon, closed=True).tolist()
     interior_np = [self._approx_ring_dp(x, epsilon, closed=True).tolist() for x in self.interior_np]
     exterior = row_col_list_to_points(exterior_np, do_round=True)
     interior = [row_col_list_to_points(x, do_round=True) for x in interior_np]
     return Polygon(exterior, interior)
Ejemplo n.º 4
0
 def from_json(cls, data):
     '''
     The function from_json convert Poligon from json format to Poligon class object. If json format is not correct it generate exception error.
     :param data: input Poligon in json format
     :return: Poligon class object
     '''
     validation.validate_geometry_points_fields(data)
     labeler_login = data.get(LABELER_LOGIN, None)
     updated_at = data.get(UPDATED_AT, None)
     created_at = data.get(CREATED_AT, None)
     sly_id = data.get(ID, None)
     class_id = data.get(CLASS_ID, None)
     return cls(exterior=row_col_list_to_points(data[POINTS][EXTERIOR], flip_row_col_order=True),
                interior=[row_col_list_to_points(i, flip_row_col_order=True) for i in data[POINTS][INTERIOR]],
                sly_id=sly_id, class_id=class_id, labeler_login=labeler_login, updated_at=updated_at, created_at=created_at)
Ejemplo n.º 5
0
    def test_crop_by_border(self):
        exterior = [[10, 10], [40, 10], [40, 40], [10, 40]]
        interiors = [[[11, 11], [11, 20], [20, 11]],
                     [[20, 20], [21, 20], [20, 21]]]
        poly = Polygon(exterior=row_col_list_to_points(
            exterior, flip_row_col_order=True),
                       interior=[
                           row_col_list_to_points(interior,
                                                  flip_row_col_order=True)
                           for interior in interiors
                       ])

        crop_rect = Rectangle(0, 0, 100, 10)
        res_geoms = poly.crop(crop_rect)
        self.assertEqual(len(res_geoms), 0)
Ejemplo n.º 6
0
    def crop(self, rect):
        '''
        Crop the current Polyline with a given rectangle, if polyline cat't be cropped it generate exception error
        :param rect: Rectangle class object
        :return: list of Polyline class objects
        '''
        try:
            clipping_window = [[rect.top, rect.left], [rect.top, rect.right],
                               [rect.bottom, rect.right], [rect.bottom, rect.left]]
            clipping_window_shpl = ShapelyPolygon(clipping_window)

            exterior = self.exterior_np
            intersections_polygon = LineString(exterior).intersection(clipping_window_shpl)
            mapping_shpl = mapping(intersections_polygon)
        except Exception:
            logger.warn('Line cropping exception, shapely.', exc_info=False)
            raise

        res_lines_pts = shapely_figure_to_coords_list(mapping_shpl)

        # tiny hack to combine consecutive segments
        lines_combined = []
        for simple_l in res_lines_pts:
            if len(lines_combined) > 0:
                prev = lines_combined[-1]
                if prev[-1] == simple_l[0]:
                    lines_combined[-1] = list(prev) + list(simple_l[1:])
                    continue
            lines_combined.append(simple_l)

        return [Polyline(row_col_list_to_points(line)) for line in lines_combined]
Ejemplo n.º 7
0
    def crop(self, rect):
        '''
        Crop the current Polygon with a given rectangle, if polygon cat't be cropped it generate exception error
        :param rect: Rectangle class object
        :return: list of Poligon class objects
        '''
        from supervisely.geometry.point_location import PointLocation
        try:
            # points = [
            #     PointLocation(row=rect.top, col=rect.left),
            #     PointLocation(row=rect.top, col=rect.right + 1),
            #     PointLocation(row=rect.bottom + 1, col=rect.right + 1),
            #     PointLocation(row=rect.bottom + 1, col=rect.left)
            # ]
            points = [
                PointLocation(row=rect.top, col=rect.left),
                PointLocation(row=rect.top, col=rect.right),
                PointLocation(row=rect.bottom, col=rect.right),
                PointLocation(row=rect.bottom, col=rect.left)
            ]
            #points = rect.corners # old implementation with 1 pixel error (right bottom)
            # #@TODO: investigate here (critical issue)

            clipping_window_shpl = ShapelyPolygon(points_to_row_col_list(points))
            self_shpl = ShapelyPolygon(self.exterior_np, holes=self.interior_np)
            intersections_shpl = self_shpl.buffer(0).intersection(clipping_window_shpl)
            mapping_shpl = mapping(intersections_shpl)
        except Exception:
            logger.warn('Polygon cropping exception, shapely.', exc_info=True)
            # raise
            # if polygon is invalid, just print warning and skip it
            # @TODO: need more investigation here
            return []

        intersections = shapely_figure_to_coords_list(mapping_shpl)

        # Check for bad cropping cases (e.g. empty points list)
        out_polygons = []
        for intersection in intersections:
            if isinstance(intersection, list) and len(intersection) > 0 and len(intersection[0]) >= 3:
                exterior = row_col_list_to_points(intersection[0], do_round=True)
                interiors = []
                for interior_contour in intersection[1:]:
                    if len(interior_contour) > 2:
                        interiors.append(row_col_list_to_points(interior_contour, do_round=True))
                out_polygons.append(Polygon(exterior, interiors))
        return out_polygons
Ejemplo n.º 8
0
    def to_contours(self):
        '''
        The function to_contours get list of contours(in Polygon class objects) of all objects in Bitmap
        :return: list of contours
        '''

        origin, mask = self.origin, self.data
        if StrictVersion(cv2.__version__) >= StrictVersion('4.0.0'):
            contours, hier = cv2.findContours(
                mask.astype(np.uint8),
                mode=cv2.
                RETR_CCOMP,  # two-level hierarchy, to get polygons with holes
                method=cv2.CHAIN_APPROX_SIMPLE)
        else:
            _, contours, hier = cv2.findContours(
                mask.astype(np.uint8),
                mode=cv2.
                RETR_CCOMP,  # two-level hierarchy, to get polygons with holes
                method=cv2.CHAIN_APPROX_SIMPLE)
        if (hier is None) or (contours is None):
            return []

        res = []
        for idx, hier_pos in enumerate(hier[0]):
            next_idx, prev_idx, child_idx, parent_idx = hier_pos
            if parent_idx < 0:
                external = contours[idx][:, 0].tolist()
                internals = []
                while child_idx >= 0:
                    internals.append(contours[child_idx][:, 0])
                    child_idx = hier[0][child_idx][0]
                if len(external) > 2:
                    new_poly = Polygon(exterior=row_col_list_to_points(
                        external, flip_row_col_order=True),
                                       interior=[
                                           row_col_list_to_points(
                                               x, flip_row_col_order=True)
                                           for x in internals
                                       ])
                    res.append(new_poly)

        offset_row, offset_col = origin.row, origin.col
        res = [x.translate(offset_row, offset_col) for x in res]
        return res
Ejemplo n.º 9
0
    def test_complex_crop(self):
        # Crop generate GeometryCollection here
        exterior = [[0, 0], [0, 3], [5, 8], [5, 9], [5, 10], [0, 15], [10, 20],
                    [0, 25], [20, 25], [20, 0]]
        interiors = [[[2, 2], [4, 4], [4, 2]]]

        poly = Polygon(exterior=row_col_list_to_points(
            exterior, flip_row_col_order=True),
                       interior=[
                           row_col_list_to_points(interior,
                                                  flip_row_col_order=True)
                           for interior in interiors
                       ])

        crop_rect = Rectangle(0, 0, 30, 5)
        res_geoms = poly.crop(crop_rect)
        self.assertEqual(len(res_geoms), 3)
        self.assertPolyEquals(res_geoms[0], [[0, 0], [5, 0], [5, 8], [0, 3]],
                              interiors)
Ejemplo n.º 10
0
    def test_draw_contour(self):
        exterior = [[0, 0], [0, 6], [6, 6], [6, 0]]
        interiors = [[[2, 2], [2, 4], [4, 4], [4, 2]]]
        poly = Polygon(exterior=row_col_list_to_points(exterior),
                       interior=[
                           row_col_list_to_points(interior)
                           for interior in interiors
                       ])

        bitmap_1 = np.zeros((7, 7), dtype=np.uint8)
        poly.draw_contour(bitmap_1, color=1)

        expected_mask = np.array([[1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 1],
                                  [1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1],
                                  [1, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 1],
                                  [1, 1, 1, 1, 1, 1, 1]],
                                 dtype=np.uint8)
        self.assertTrue(np.array_equal(bitmap_1, expected_mask))

        # Extended test
        exterior = [[0, 0], [0, 6], [10, 6], [10, 0]]
        interiors = [[[1, 1], [1, 2], [2, 1]], [[2, 4], [3, 5], [4, 4], [3,
                                                                         3]],
                     [[6, 2], [8, 2], [8, 4], [6, 4]]]
        poly = Polygon(exterior=row_col_list_to_points(exterior),
                       interior=[
                           row_col_list_to_points(interior)
                           for interior in interiors
                       ])

        bitmap_2 = np.zeros((11, 7), dtype=np.uint8)
        poly.draw_contour(bitmap_2, color=1)

        expected_mask = np.array([[1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 0, 0, 0, 1],
                                  [1, 1, 0, 0, 1, 0, 1], [1, 0, 0, 1, 0, 1, 1],
                                  [1, 0, 0, 0, 1, 0, 1], [1, 0, 0, 0, 0, 0, 1],
                                  [1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1],
                                  [1, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 1],
                                  [1, 1, 1, 1, 1, 1, 1]],
                                 dtype=np.uint8)

        self.assertTrue(np.array_equal(bitmap_2, expected_mask))
Ejemplo n.º 11
0
    def from_json(cls, data):
        '''
        The function from_json convert Cuboid from json format to Cuboid class object. If json format is not correct it generate exception error.
        :param data: input Cuboid in json format
        :return: Cuboid class object
        '''
        for k in [POINTS, FACES]:
            if k not in data:
                raise ValueError(f'Field {k!r} not found in Cuboid JSON data.')

        points = row_col_list_to_points(data[POINTS], flip_row_col_order=True)
        faces = [CuboidFace.from_json(face_json) for face_json in data[FACES]]

        labeler_login = data.get(LABELER_LOGIN, None)
        updated_at = data.get(UPDATED_AT, None)
        created_at = data.get(CREATED_AT, None)
        sly_id = data.get(ID, None)
        class_id = data.get(CLASS_ID, None)
        return cls(points=points, faces=faces,
                   sly_id=sly_id, class_id=class_id, labeler_login=labeler_login, updated_at=updated_at, created_at=created_at)