コード例 #1
0
 def test_make_eroded(self):
     max_extent = Box.make_square(0, 0, 10)
     box = Box(1, 1, 3, 4)
     buffer_size = erosion_size = 1
     eroded_box = box.make_buffer(buffer_size, max_extent) \
                     .make_eroded(erosion_size)
     self.assertEqual(eroded_box, box)
コード例 #2
0
def read_labels(geojson, extent=None):
    """Convert GeoJSON to ChipClassificationLabels.

    If the GeoJSON already contains a grid of cells, then it can be constructed
    in a straightforward manner without having to infer the class of cells.

    If extent is given, only labels that intersect with the extent are returned.

    Args:
        geojson: dict in normalized GeoJSON format (see VectorSource)
        extent: Box in pixel coords

    Returns:
       ChipClassificationLabels
    """
    labels = ChipClassificationLabels()

    for f in geojson['features']:
        geom = shape(f['geometry'])
        (xmin, ymin, xmax, ymax) = geom.bounds
        cell = Box(ymin, xmin, ymax, xmax)
        if extent is not None and not cell.to_shapely().intersects(
                extent.to_shapely()):
            continue

        props = f['properties']
        class_id = props['class_id']
        scores = props.get('scores')
        labels.set_cell(cell, class_id, scores)

    return labels
コード例 #3
0
    def test_get_overlapping(self):
        window = Box.make_square(0, 0, 2.01)
        labels = ObjectDetectionLabels.get_overlapping(self.labels, window)
        labels.assert_equal(self.labels)

        window = Box.make_square(0, 0, 3)
        labels = ObjectDetectionLabels.get_overlapping(self.labels,
                                                       window,
                                                       ioa_thresh=0.5)
        npboxes = np.array([[0., 0., 2., 2.]])
        class_ids = np.array([0])
        scores = np.array([0.9])
        expected_labels = ObjectDetectionLabels(npboxes,
                                                class_ids,
                                                scores=scores)
        labels.assert_equal(expected_labels)

        window = Box.make_square(0, 0, 3)
        labels = ObjectDetectionLabels.get_overlapping(self.labels,
                                                       window,
                                                       ioa_thresh=0.1,
                                                       clip=True)
        expected_npboxes = np.array([
            [0., 0., 2., 2.],
            [2., 2., 3., 3.],
        ])
        expected_labels = ObjectDetectionLabels(expected_npboxes,
                                                self.class_ids,
                                                scores=self.scores)
        labels.assert_equal(expected_labels)
コード例 #4
0
 def setUp(self):
     self.windows = [Box.make_square(0, 0, 10), Box.make_square(0, 10, 10)]
     self.label_arr0 = np.random.choice([0, 1], (10, 10))
     self.label_arr1 = np.random.choice([0, 1], (10, 10))
     self.labels = SemanticSegmentationLabels()
     self.labels.set_label_arr(self.windows[0], self.label_arr0)
     self.labels.set_label_arr(self.windows[1], self.label_arr1)
コード例 #5
0
 def test_make_random_square(self):
     window = Box(5, 5, 15, 15)
     size = 5
     nb_tests = 100
     for _ in range(nb_tests):
         box = window.make_random_square(size)
         self.assertEqual(box.get_width(), box.get_height())
         self.assertEqual(box.get_width(), size)
         self.assertTrue(window.to_shapely().contains(box.to_shapely()))
コード例 #6
0
    def setUp(self):
        self.labels = ChipClassificationLabels()

        self.cell1 = Box.make_square(0, 0, 2)
        self.class_id1 = 1
        self.labels.set_cell(self.cell1, self.class_id1)

        self.cell2 = Box.make_square(0, 2, 2)
        self.class_id2 = 2
        self.labels.set_cell(self.cell2, self.class_id2)
コード例 #7
0
    def setUp(self):
        self.crs_transformer = DoubleCRSTransformer()
        self.geojson = {
            'type':
            'FeatureCollection',
            'features': [{
                'type': 'Feature',
                'geometry': {
                    'type':
                    'MultiPolygon',
                    'coordinates': [[[[0., 0.], [0., 2.], [2., 2.], [2., 0.],
                                      [0., 0.]]]]
                },
                'properties': {
                    'class_name': 'car',
                    'class_id': 0,
                    'score': 0.0
                }
            }, {
                'type': 'Feature',
                'geometry': {
                    'type':
                    'Polygon',
                    'coordinates': [[[2., 2.], [2., 4.], [4., 4.], [4., 2.],
                                     [2., 2.]]]
                },
                'properties': {
                    'score': 0.0,
                    'class_name': 'house',
                    'class_id': 1
                }
            }]
        }

        self.class_config = ClassConfig(names=['car', 'house'])

        self.box1 = Box.make_square(0, 0, 4)
        self.box2 = Box.make_square(4, 4, 4)
        self.class_id1 = 0
        self.class_id2 = 1
        self.background_class_id = 2

        geoms = []
        for f in self.geojson['features']:
            g = shape(f['geometry'])
            g.class_id = f['properties']['class_id']
            geoms.append(g)
        self.str_tree = STRtree(geoms)

        self.file_name = 'labels.json'
        self.tmp_dir = rv_config.get_tmp_dir()
        self.uri = os.path.join(self.tmp_dir.name, self.file_name)
        json_to_file(self.geojson, self.uri)
コード例 #8
0
    def test_make_buffer(self):
        buffer_size = 1
        max_extent = Box.make_square(0, 0, 3)
        buffer_box = Box(0, 0, 3, 3)
        output_buffer_box = self.box.make_buffer(buffer_size, max_extent)
        self.assertEqual(output_buffer_box, buffer_box)

        buffer_size = 0.5
        max_extent = Box.make_square(0, 0, 5)
        buffer_box = Box(0, 0, 3, 5)
        output_buffer_box = self.box.make_buffer(buffer_size, max_extent)
        self.assertEqual(output_buffer_box, buffer_box)
コード例 #9
0
    def test_filter_by_aoi(self):
        aois = [Box.make_square(0, 0, 2).to_shapely()]
        filt_labels = self.labels.filter_by_aoi(aois)

        npboxes = np.array([[0., 0., 2., 2.]])
        class_ids = np.array([0])
        scores = np.array([0.9])
        exp_labels = ObjectDetectionLabels(npboxes, class_ids, scores=scores)
        self.assertEqual(filt_labels, exp_labels)

        aois = [Box.make_square(4, 4, 2).to_shapely()]
        filt_labels = self.labels.filter_by_aoi(aois)
        exp_labels = ObjectDetectionLabels.make_empty()
        self.assertEqual(filt_labels, exp_labels)
コード例 #10
0
    def test_filter_by_aoi(self):
        aois = [Box.make_square(0, 0, 2).to_shapely()]
        filt_labels = self.labels.filter_by_aoi(aois)

        exp_labels = ChipClassificationLabels()
        cell1 = Box.make_square(0, 0, 2)
        class_id1 = 1
        exp_labels.set_cell(cell1, class_id1)
        self.assertEqual(filt_labels, exp_labels)

        aois = [Box.make_square(4, 4, 2).to_shapely()]
        filt_labels = self.labels.filter_by_aoi(aois)

        exp_labels = ChipClassificationLabels()
        self.assertEqual(filt_labels, exp_labels)
コード例 #11
0
    def __init__(self,
                 uris,
                 raster_transformers,
                 tmp_dir,
                 channel_order=None,
                 x_shift=0.0,
                 y_shift=0.0):
        """Constructor.

        This RasterSource can read any file that can be opened by Rasterio/GDAL
        including georeferenced formats such as GeoTIFF and non-georeferenced formats
        such as JPG. See https://www.gdal.org/formats_list.html for more details.

        If channel_order is None, then use non-alpha channels. This also sets any
        masked or NODATA pixel values to be zeros.

        Args:
            channel_order: list of indices of channels to extract from raw imagery
        """
        self.uris = uris
        self.tmp_dir = tmp_dir
        self.image_tmp_dir = None
        self.image_dataset = None
        self.x_shift = x_shift
        self.y_shift = y_shift

        num_channels = None

        # Activate in order to get information out of the raster
        with self.activate():
            num_channels = self.image_dataset.count
            if channel_order is None:
                colorinterp = self.image_dataset.colorinterp
                if colorinterp:
                    channel_order = [
                        i for i, color_interp in enumerate(colorinterp)
                        if color_interp != ColorInterp.alpha
                    ]
                else:
                    channel_order = list(range(0, num_channels))
            self.validate_channel_order(channel_order, num_channels)

            mask_flags = self.image_dataset.mask_flag_enums
            self.is_masked = any(
                [m for m in mask_flags if m != MaskFlags.all_valid])

            self.height = self.image_dataset.height
            self.width = self.image_dataset.width

            # Get 1x1 chip and apply raster transformers to test dtype.
            test_chip = self.get_raw_chip(Box.make_square(0, 0, 1))
            test_chip = test_chip[:, :, channel_order]
            for transformer in raster_transformers:
                test_chip = transformer.transform(test_chip, channel_order)
            self.dtype = test_chip.dtype

            self._set_crs_transformer()

        super().__init__(channel_order, num_channels, raster_transformers)
コード例 #12
0
    def get_predict_windows(self, extent: Box) -> List[Box]:
        """Returns windows to compute predictions for.

        Args:
            extent: extent of RasterSource
        """
        chip_sz = stride = self.config.predict_chip_sz
        return extent.get_windows(chip_sz, stride)
コード例 #13
0
    def test_normalized_to_local(self):
        norm_npboxes = np.array([[0., 0., 0.2, 0.02], [0.2, 0.02, 0.4, 0.04]])
        window = Box(0, 0, 10, 100)
        local_npboxes = ObjectDetectionLabels.normalized_to_local(
            norm_npboxes, window)

        expected_local_npboxes = np.array([[0., 0., 2., 2.], [2., 2., 4., 4.]])
        np.testing.assert_array_equal(local_npboxes, expected_local_npboxes)
コード例 #14
0
    def test_global_to_local(self):
        global_npboxes = np.array([[10., 10., 12., 12.], [12., 12., 14., 14.]])
        window = Box.make_square(10, 10, 10)
        local_npboxes = ObjectDetectionLabels.global_to_local(
            global_npboxes, window)

        expected_local_npboxes = np.array([[0., 0., 2., 2.], [2., 2., 4., 4.]])
        np.testing.assert_array_equal(local_npboxes, expected_local_npboxes)
コード例 #15
0
    def test_extend(self):
        labels = ChipClassificationLabels()
        cell3 = Box.make_square(0, 4, 2)
        class_id3 = 1
        labels.set_cell(cell3, class_id3)

        self.labels.extend(labels)
        cells = self.labels.get_cells()
        self.assertEqual(len(cells), 3)
        self.assertTrue(cell3 in cells)
コード例 #16
0
    def test_get_cell(self):
        cell = Box.make_square(0, 2, 3)
        class_id = self.labels.get_cell_class_id(cell)
        self.assertEqual(class_id, None)

        class_id = self.labels.get_cell_class_id(self.cell1)
        self.assertEqual(class_id, self.class_id1)

        class_id = self.labels.get_cell_class_id(self.cell2)
        self.assertEqual(class_id, self.class_id2)
コード例 #17
0
 def filter_by_aoi(self, aoi_polygons):
     result = ChipClassificationLabels()
     for cell in self.cell_to_class_id:
         cell_box = Box.from_tuple(cell)
         cell_poly = cell_box.to_shapely()
         for aoi in aoi_polygons:
             if cell_poly.within(aoi):
                 (class_id, scores) = self.cell_to_class_id[cell]
                 result.set_cell(cell_box, class_id, scores)
     return result
コード例 #18
0
    def test_get_with_aoi(self):
        null_class_id = 2

        aoi_polygons = [Box.make_square(5, 15, 2).to_shapely()]
        exp_label_arr = np.full(self.label_arr1.shape, null_class_id)
        exp_label_arr[5:7, 5:7] = self.label_arr1[5:7, 5:7]

        labels = self.labels.filter_by_aoi(aoi_polygons, null_class_id)
        label_arr = labels.get_label_arr(self.windows[1])
        np.testing.assert_array_equal(label_arr, exp_label_arr)
        self.assertEqual(1, len(labels.window_to_label_arr))
コード例 #19
0
def get_train_windows(scene, chip_size):
    train_windows = []
    extent = scene.raster_source.get_extent()
    stride = chip_size
    windows = extent.get_windows(chip_size, stride)
    if scene.aoi_polygons:
        windows = Box.filter_by_aoi(windows, scene.aoi_polygons)
    for window in windows:
        chip = scene.raster_source.get_chip(window)
        if np.sum(chip.ravel()) > 0:
            train_windows.append(window)
    return train_windows
コード例 #20
0
    def test_infer_cell3(self):
        # Only box 2 is in cell, but IOA isn't high enough.
        cell = Box.make_square(3, 3, 3)
        ioa_thresh = 0.5
        use_intersection_over_cell = False
        background_class_id = None
        pick_min_class_id = False

        class_id = infer_cell(cell, self.str_tree, ioa_thresh,
                              use_intersection_over_cell, background_class_id,
                              pick_min_class_id)
        self.assertEqual(class_id, None)
コード例 #21
0
    def test_infer_cell2(self):
        # More of box 2 is in cell.
        cell = Box.make_square(1, 1, 3)
        ioa_thresh = 0.5
        use_intersection_over_cell = False
        background_class_id = None
        pick_min_class_id = False

        class_id = infer_cell(cell, self.str_tree, ioa_thresh,
                              use_intersection_over_cell, background_class_id,
                              pick_min_class_id)
        self.assertEqual(class_id, self.class_id2)
コード例 #22
0
    def test_infer_cell7(self):
        # Cell doesn't overlap with any boxes.
        cell = Box.make_square(10, 10, 1)
        ioa_thresh = 0.5
        use_intersection_over_cell = True
        background_class_id = None
        pick_min_class_id = False

        class_id = infer_cell(cell, self.str_tree, ioa_thresh,
                              use_intersection_over_cell, background_class_id,
                              pick_min_class_id)
        self.assertEqual(class_id, None)
コード例 #23
0
    def test_infer_cell6(self):
        # No boxes overlap enough, use background_class_id
        cell = Box.make_square(0, 0, 10)
        ioa_thresh = 0.5
        use_intersection_over_cell = True
        background_class_id = self.background_class_id
        pick_min_class_id = False

        class_id = infer_cell(cell, self.str_tree, ioa_thresh,
                              use_intersection_over_cell, background_class_id,
                              pick_min_class_id)
        self.assertEqual(class_id, self.background_class_id)
コード例 #24
0
    def filter_windows(windows):
        if scene.aoi_polygons:
            windows = Box.filter_by_aoi(windows, scene.aoi_polygons)

            filt_windows = []
            for w in windows:
                label_arr = label_source.get_labels(w).get_label_arr(w)
                null_inds = (
                    label_arr.ravel() == class_config.get_null_class_id())
                if not np.all(null_inds):
                    filt_windows.append(w)
            windows = filt_windows
        return windows
コード例 #25
0
    def test_infer_cell8(self):
        # box2 overlaps more than box1, but using pick_min_class_id, so
        # picks box1.
        cell = Box.make_square(1, 1, 3)
        ioa_thresh = 0.5
        use_intersection_over_cell = False
        background_class_id = None
        pick_min_class_id = True

        class_id = infer_cell(cell, self.str_tree, ioa_thresh,
                              use_intersection_over_cell, background_class_id,
                              pick_min_class_id)
        self.assertEqual(class_id, self.class_id2)
コード例 #26
0
    def test_infer_cell5(self):
        # More of box1 in cell, using intersection_over_cell with the
        # IOA high enough.
        cell = Box.make_square(0, 0, 3)
        ioa_thresh = 0.4
        use_intersection_over_cell = True
        background_class_id = None
        pick_min_class_id = False

        class_id = infer_cell(cell, self.str_tree, ioa_thresh,
                              use_intersection_over_cell, background_class_id,
                              pick_min_class_id)
        self.assertEqual(class_id, self.class_id1)
コード例 #27
0
    def test_infer_cell4(self):
        # Both boxes inside cell, but using intersection_over_cell,
        # the IOA isn't high enough.
        cell = Box.make_square(0, 0, 10)
        ioa_thresh = 0.5
        use_intersection_over_cell = True
        background_class_id = None
        pick_min_class_id = False

        class_id = infer_cell(cell, self.str_tree, ioa_thresh,
                              use_intersection_over_cell, background_class_id,
                              pick_min_class_id)
        self.assertEqual(class_id, None)
コード例 #28
0
    def test_get_labels_inferred(self):
        extent = Box.make_square(0, 0, 8)

        config = ChipClassificationLabelSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(uri=self.uri,
                                                    default_class_id=None),
            ioa_thresh=0.5,
            use_intersection_over_cell=False,
            pick_min_class_id=False,
            background_class_id=self.background_class_id,
            infer_cells=True,
            cell_sz=4)
        source = config.build(self.class_config, self.crs_transformer, extent,
                              self.tmp_dir.name)
        labels = source.get_labels()
        cells = labels.get_cells()

        self.assertEqual(len(cells), 4)
        self.assertEqual(labels.get_cell_class_id(self.box1), self.class_id1)
        self.assertEqual(labels.get_cell_class_id(self.box2), self.class_id2)
        self.assertEqual(labels.get_cell_class_id(Box.make_square(0, 4, 4)),
                         self.background_class_id)
        self.assertEqual(labels.get_cell_class_id(Box.make_square(4, 0, 4)),
                         self.background_class_id)
コード例 #29
0
def geoms_to_raster(str_tree, rasterizer_config, window, extent):
    background_class_id = rasterizer_config.background_class_id
    all_touched = rasterizer_config.all_touched

    log.debug('Cropping shapes to window...')
    # Crop shapes against window, remove empty shapes, and put in window frame of
    # reference.
    window_geom = window.to_shapely()
    shapes = str_tree.query(window_geom)
    shapes = [(s, s.class_id) for s in shapes]
    shapes = [(s.intersection(window_geom), c) for s, c in shapes]
    shapes = [(s, c) for s, c in shapes if not s.is_empty]

    def to_window_frame(x, y, z=None):
        return (x - window.xmin, y - window.ymin)

    shapes = [(transform(to_window_frame, s), c) for s, c in shapes]
    log.debug('# of shapes in window: {}'.format(len(shapes)))

    out_shape = (window.get_height(), window.get_width())

    # rasterize needs to be passed >= 1 shapes.
    if shapes:
        log.debug('rasterio.rasterize()...')
        raster = rasterize(
            shapes,
            out_shape=out_shape,
            fill=background_class_id,
            dtype=np.uint8,
            all_touched=all_touched)
    else:
        raster = np.full(out_shape, background_class_id, dtype=np.uint8)

    # Ensure that parts of window outside of extent have zero values which are counted as
    # the don't-care class for segmentation.
    valid_window = window_geom.intersection(extent.to_shapely())
    if valid_window.is_empty:
        raster[:, :] = 0
    else:
        vw = transform(to_window_frame, valid_window)
        vw = Box.from_shapely(vw).to_int()
        new_raster = np.zeros(out_shape)
        new_raster[vw.ymin:vw.ymax, vw.xmin:vw.xmax] = \
            raster[vw.ymin:vw.ymax, vw.xmin:vw.xmax]
        raster = new_raster

    return raster
コード例 #30
0
    def test_get_labels(self):
        # Extent contains both boxes.
        extent = Box.make_square(0, 0, 8)

        config = ChipClassificationLabelSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(uri=self.uri,
                                                    default_class_id=None))
        source = config.build(self.class_config, self.crs_transformer, extent,
                              self.tmp_dir.name)
        labels = source.get_labels()

        cells = labels.get_cells()
        self.assertEqual(len(cells), 2)
        class_id = labels.get_cell_class_id(self.box1)
        self.assertEqual(class_id, self.class_id1)
        class_id = labels.get_cell_class_id(self.box2)
        self.assertEqual(class_id, self.class_id2)