Esempio n. 1
0
    def test_read_with_extent(self):
        # Extent only includes the first box.
        extent = Box.make_square(0, 0, 3)
        config = ObjectDetectionLabelSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(
                uri=self.file_path, default_class_id=None))
        source = config.build(
            self.class_config, self.crs_transformer, extent, self.tmp_dir.name)
        labels = source.get_labels()

        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)

        # Extent includes both boxes, but clips the second.
        extent = Box.make_square(0, 0, 3.9)
        config = ObjectDetectionLabelSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(
                uri=self.file_path, default_class_id=None))
        source = config.build(
            self.class_config, self.crs_transformer, extent, self.tmp_dir.name)
        labels = source.get_labels()

        npboxes = np.array([[0., 0., 2., 2.], [2., 2., 3.9, 3.9]])
        class_ids = np.array([0, 1])
        scores = np.array([0.9, 0.9])
        expected_labels = ObjectDetectionLabels(
            npboxes, class_ids, scores=scores)
        labels.assert_equal(expected_labels)
Esempio n. 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
Esempio n. 3
0
 def make_ground_truth_labels(self):
     size = 100
     nw = Box.make_square(0, 0, size)
     ne = Box.make_square(0, 200, size)
     se = Box.make_square(200, 200, size)
     sw = Box.make_square(200, 0, size)
     npboxes = Box.to_npboxes([nw, ne, se, sw])
     class_ids = np.array([0, 0, 1, 1])
     return ObjectDetectionLabels(npboxes, class_ids)
Esempio n. 4
0
 def make_predicted_labels(self):
     size = 100
     # Predicted labels are only there for three of the ground truth boxes,
     # and are offset by 10 pixels.
     nw = Box.make_square(10, 0, size)
     ne = Box.make_square(10, 200, size)
     se = Box.make_square(210, 200, size)
     npboxes = Box.to_npboxes([nw, ne, se])
     class_ids = np.array([0, 0, 1])
     scores = np.ones(class_ids.shape)
     return ObjectDetectionLabels(npboxes, class_ids, scores=scores)
Esempio n. 5
0
    def set_return_vals(self, raster=None):
        self.mock.get_extent.return_value = Box.make_square(0, 0, 2)
        self.mock.get_dtype.return_value = np.uint8
        self.mock.get_crs_transformer.return_value = IdentityCRSTransformer()
        self.mock._get_chip.return_value = np.random.rand(1, 2, 2, 3)

        if raster is not None:
            self.mock.get_extent.return_value = Box(0, 0, raster.shape[0],
                                                    raster.shape[1])
            self.mock.get_dtype.return_value = raster.dtype

            def get_chip(window):
                return raster[window.ymin:window.ymax,
                              window.xmin:window.xmax, :]

            self.mock._get_chip.side_effect = get_chip
Esempio n. 6
0
 def test_enough_target_pixels_true(self):
     data = np.zeros((10, 10, 1), dtype=np.uint8)
     data[4:, 4:, :] = 1
     raster_source = MockRasterSource([0], 1)
     raster_source.set_raster(data)
     label_source = SemanticSegmentationLabelSource(
         raster_source=raster_source)
     with label_source.activate():
         extent = Box(0, 0, 10, 10)
         self.assertTrue(label_source.enough_target_pixels(extent, 30, [1]))
Esempio n. 7
0
 def setUp(self):
     self.crs_transformer = IdentityCRSTransformer()
     self.extent = Box.make_square(0, 0, 10)
     self.tmp_dir_obj = rv_config.get_tmp_dir()
     self.tmp_dir = self.tmp_dir_obj.name
     self.class_id = 0
     self.background_class_id = 1
     self.line_buffer = 1
     self.class_config = ClassConfig(names=['a'])
     self.uri = join(self.tmp_dir, 'tmp.json')
Esempio n. 8
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
Esempio n. 9
0
 def test_get_labels(self):
     data = np.zeros((10, 10, 1), dtype=np.uint8)
     data[7:, 7:, 0] = 1
     raster_source = MockRasterSource([0], 1)
     raster_source.set_raster(data)
     label_source = SemanticSegmentationLabelSource(
         raster_source=raster_source)
     with label_source.activate():
         window = Box.make_square(7, 7, 3)
         labels = label_source.get_labels(window=window)
         label_arr = labels.get_label_arr(window)
         expected_label_arr = np.ones((3, 3))
         np.testing.assert_array_equal(label_arr, expected_label_arr)
Esempio n. 10
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
Esempio n. 11
0
 def test_get_labels_rgb(self):
     data = np.zeros((10, 10, 3), dtype=np.uint8)
     data[7:, 7:, :] = [1, 1, 1]
     raster_source = MockRasterSource([0, 1, 2], 3)
     raster_source.set_raster(data)
     rgb_class_config = ClassConfig(names=['a'], colors=['#010101'])
     rgb_class_config.ensure_null_class()
     label_source = SemanticSegmentationLabelSource(
         raster_source=raster_source, rgb_class_config=rgb_class_config)
     with label_source.activate():
         window = Box.make_square(7, 7, 3)
         labels = label_source.get_labels(window=window)
         label_arr = labels.get_label_arr(window)
         expected_label_arr = np.zeros((3, 3))
         np.testing.assert_array_equal(label_arr, expected_label_arr)
Esempio n. 12
0
    def test_get_chip_no_polygons(self):
        geojson = {'type': 'FeatureCollection', 'features': []}

        source = self.build_source(geojson)
        with source.activate():
            # Get chip that partially overlaps extent. Expect that chip has zeros
            # outside of extent, and background_class_id otherwise.
            self.assertEqual(source.get_extent(), self.extent)
            chip = source.get_chip(Box.make_square(5, 5, 10))
            self.assertEqual(chip.shape, (10, 10, 1))

            expected_chip = np.zeros((10, 10, 1))
            expected_chip[0:5, 0:5, :] = self.background_class_id

            np.testing.assert_array_equal(chip, expected_chip)
Esempio n. 13
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 = [(shapely.ops.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 = shapely.ops.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
Esempio n. 14
0
    def setUp(self):
        self.file_name = 'labels.json'
        self.tmp_dir = rv_config.get_tmp_dir()
        self.file_path = os.path.join(self.tmp_dir.name, self.file_name)

        self.crs_transformer = DoubleCRSTransformer()
        self.geojson = {
            'type':
            'FeatureCollection',
            'features': [{
                'type': 'Feature',
                'geometry': {
                    'type':
                    'Polygon',
                    'coordinates': [[[0., 0.], [0., 1.], [1., 1.], [1., 0.],
                                     [0., 0.]]]
                },
                'properties': {
                    'class_id': 0,
                    'score': 0.9
                }
            }, {
                'type': 'Feature',
                'geometry': {
                    'type':
                    'Polygon',
                    'coordinates': [[[1., 1.], [1., 2.], [2., 2.], [2., 1.],
                                     [1., 1.]]]
                },
                'properties': {
                    'score': 0.9,
                    'class_id': 1
                }
            }]
        }

        self.extent = Box.make_square(0, 0, 10)
        self.class_config = ClassConfig(names=['car', 'house'])
        json_to_file(self.geojson, self.file_path)
    def get_vector_scene(self, class_id, use_aoi=False):
        gt_uri = data_file_path('{}-gt-polygons.geojson'.format(class_id))
        pred_uri = data_file_path('{}-pred-polygons.geojson'.format(class_id))

        scene_id = str(class_id)
        rs = MockRasterSource(channel_order=[0, 1, 3], num_channels=3)
        rs.set_raster(np.zeros((10, 10, 3)))

        crs_transformer = IdentityCRSTransformer()
        extent = Box.make_square(0, 0, 360)

        config = RasterizedSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(uri=gt_uri,
                                                    default_class_id=0),
            rasterizer_config=RasterizerConfig(background_class_id=1))
        gt_rs = config.build(self.class_config, crs_transformer, extent)
        gt_ls = SemanticSegmentationLabelSource(raster_source=gt_rs)

        config = RasterizedSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(uri=pred_uri,
                                                    default_class_id=0),
            rasterizer_config=RasterizerConfig(background_class_id=1))
        pred_rs = config.build(self.class_config, crs_transformer, extent)
        pred_ls = SemanticSegmentationLabelSource(raster_source=pred_rs)
        pred_ls.vector_output = [
            PolygonVectorOutputConfig(uri=pred_uri,
                                      denoise=0,
                                      class_id=class_id)
        ]

        if use_aoi:
            aoi_uri = data_file_path('{}-aoi.geojson'.format(class_id))
            aoi_geojson = file_to_json(aoi_uri)
            aoi_polygons = [shape(aoi_geojson['features'][0]['geometry'])]
            return Scene(scene_id, rs, gt_ls, pred_ls, aoi_polygons)

        return Scene(scene_id, rs, gt_ls, pred_ls)
Esempio n. 16
0
    def make_labels(self, class_ids):
        """Make 2x2 grid label store.

        Args:
            class_ids: 2x2 array of class_ids to use
        """
        cell_size = 200
        y_cells = 2
        x_cells = 2
        labels = ChipClassificationLabels()

        for yind in range(y_cells):
            for xind in range(x_cells):
                ymin = yind * cell_size
                xmin = xind * cell_size
                ymax = ymin + cell_size
                xmax = xmin + cell_size
                window = Box(ymin, xmin, ymax, xmax)
                class_id = class_ids[yind][xind]
                new_labels = ChipClassificationLabels()
                new_labels.set_cell(window, class_id)
                labels.extend(new_labels)

        return labels
 def filter_windows(windows):
     if scene.aoi_polygons:
         windows = Box.filter_by_aoi(windows, scene.aoi_polygons)
     return windows
Esempio n. 18
0
def save_image_crop(image_uri,
                    image_crop_uri,
                    label_uri=None,
                    label_crop_uri=None,
                    size=600,
                    min_features=10,
                    vector_labels=True,
                    class_config=None):
    """Save a crop of an image to use for testing.

    If label_uri is set, the crop needs to cover >= min_features.

    Args:
        image_uri: URI of original image
        image_crop_uri: URI of cropped image to save
        label_uri: optional URI of label file
        label_crop_uri: optional URI of cropped labels to save
        size: height and width of crop

    Raises:
        ValueError if cannot find a crop satisfying min_features constraint.
    """
    if not file_exists(image_crop_uri):
        print('Saving test crop to {}...'.format(image_crop_uri))
        old_environ = os.environ.copy()
        try:
            request_payer = S3FileSystem.get_request_payer()
            if request_payer == 'requester':
                os.environ['AWS_REQUEST_PAYER'] = request_payer
            im_dataset = rasterio.open(image_uri)
            h, w = im_dataset.height, im_dataset.width

            extent = Box(0, 0, h, w)
            windows = extent.get_windows(size, size)
            if label_uri and vector_labels:
                crs_transformer = RasterioCRSTransformer.from_dataset(
                    im_dataset)
                geojson_vs_config = GeoJSONVectorSourceConfig(uri=label_uri)
                vs = geojson_vs_config.build(class_config, crs_transformer)
                geojson = vs.get_geojson()
                geoms = []
                for f in geojson['features']:
                    g = shape(f['geometry'])
                    geoms.append(g)
                tree = STRtree(geoms)

            def p2m(x, y, z=None):
                return crs_transformer.pixel_to_map((x, y))

            for w in windows:
                use_window = True
                if label_uri and vector_labels:
                    w_polys = tree.query(w.to_shapely())
                    use_window = len(w_polys) >= min_features
                    if use_window and label_crop_uri is not None:
                        print('Saving test crop labels to {}...'.format(
                            label_crop_uri))

                        label_crop_features = [
                            mapping(transform(p2m, wp)) for wp in w_polys
                        ]
                        label_crop_json = {
                            'type':
                            'FeatureCollection',
                            'features': [{
                                'geometry': f
                            } for f in label_crop_features]
                        }
                        json_to_file(label_crop_json, label_crop_uri)

                if use_window:
                    crop_image(image_uri, w, image_crop_uri)

                    if not vector_labels and label_uri and label_crop_uri:
                        crop_image(label_uri, w, label_crop_uri)

                    break

            if not use_window:
                raise ValueError('Could not find a good crop.')
        finally:
            os.environ.clear()
            os.environ.update(old_environ)