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)
def setUp(self): self.windows = [ Box.make_square(0, 0, 10), Box.make_square(0, 5, 10), Box.make_square(0, 10, 10) ] self.num_classes = 3 self.scores_left = make_random_scores(self.num_classes, 10, 10) self.scores_mid = make_random_scores(self.num_classes, 10, 10) self.scores_right = make_random_scores(self.num_classes, 10, 10) self.scores_left = self.scores_left.astype(np.float16) self.scores_mid = self.scores_mid.astype(np.float16) self.scores_right = self.scores_right.astype(np.float16) self.extent = Box(0, 0, 10, 20) self.labels = SemanticSegmentationSmoothLabels( extent=self.extent, num_classes=self.num_classes) self.labels[self.windows[0]] = self.scores_left self.labels[self.windows[1]] = self.scores_mid self.labels[self.windows[2]] = self.scores_right arr = np.zeros((self.num_classes, 10, 20), dtype=np.float16) arr[..., :10] += self.scores_left arr[..., 5:15] += self.scores_mid arr[..., 10:] += self.scores_right self.expected_scores = arr hits = np.zeros((10, 20), dtype=np.uint8) hits[..., :10] += 1 hits[..., 5:15] += 1 hits[..., 10:] += 1 self.expected_hits = hits
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 = SemanticSegmentationDiscreteLabels() self.labels[self.windows[0]] = self.label_arr0 self.labels[self.windows[1]] = self.label_arr1
def test_get_labels_inferred(self): extent = Box.make_square(0, 0, 8) msg = rv.LabelSourceConfig.builder(rv.CHIP_CLASSIFICATION) \ .with_uri(self.uri) \ .with_ioa_thresh(0.5) \ .with_use_intersection_over_cell(False) \ .with_pick_min_class_id(False) \ .with_background_class_id(self.background_class_id) \ .with_infer_cells(True) \ .with_cell_size(4) \ .build().to_proto() config = rv.LabelSourceConfig.builder(rv.CHIP_CLASSIFICATION) \ .from_proto(msg).build() source = config.create_source(self.task_config, extent, self.crs_transformer, self.temp_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)
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([1]) 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)
def test_read_with_extent(self): # Extent only includes the first box. extent = Box.make_square(0, 0, 3) store = ObjectDetectionLabelSource(self.file_path, self.crs_transformer, self.class_map, extent=extent) labels = store.get_labels() npboxes = np.array([[0., 0., 2., 2.]]) class_ids = np.array([1]) 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) store = ObjectDetectionLabelSource(self.file_path, self.crs_transformer, self.class_map, extent=extent) labels = store.get_labels() npboxes = np.array([[0., 0., 2., 2.], [2., 2., 3.9, 3.9]]) class_ids = np.array([1, 2]) scores = np.array([0.9, 0.9]) expected_labels = ObjectDetectionLabels(npboxes, class_ids, scores=scores) labels.assert_equal(expected_labels)
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': 1, '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': 2 } }] } self.class_map = ClassMap([ClassItem(1, 'car'), ClassItem(2, 'house')]) class MockTaskConfig(): def __init__(self, class_map): self.class_map = class_map self.task_config = MockTaskConfig(self.class_map) self.box1 = Box.make_square(0, 0, 4) self.box2 = Box.make_square(4, 4, 4) self.class_id1 = 1 self.class_id2 = 2 self.background_class_id = 3 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.temp_dir = RVConfig.get_tmp_dir() self.uri = os.path.join(self.temp_dir.name, self.file_name) json_to_file(self.geojson, self.uri)
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([1, 1, 2, 2]) return ObjectDetectionLabels(npboxes, class_ids)
def test_filter_by_aoi(self): windows = [Box.make_square(0, 0, 2), Box.make_square(0, 2, 2)] aoi_polygons = [Box.make_square(0, 0, 3).to_shapely()] filt_windows = Box.filter_by_aoi(windows, aoi_polygons, within=False) self.assertListEqual(filt_windows, windows) filt_windows = Box.filter_by_aoi(windows, aoi_polygons, within=True) self.assertListEqual(filt_windows, windows[0:1])
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)
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([1, 1, 2]) scores = np.ones(class_ids.shape) return ObjectDetectionLabels(npboxes, class_ids, scores=scores)
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)
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)
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([1]) 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)
def test_get_windows(self): extent = Box(0, 0, 100, 100) windows = list(extent.get_windows(10, 10)) self.assertEqual(len(windows), 100) extent = Box(0, 0, 100, 100) windows = list(extent.get_windows(10, 5)) self.assertEqual(len(windows), 400) extent = Box(0, 0, 20, 20) windows = set( [window.tuple_format() for window in extent.get_windows(10, 10)]) expected_windows = [ Box.make_square(0, 0, 10), Box.make_square(10, 0, 10), Box.make_square(0, 10, 10), Box.make_square(10, 10, 10) ] expected_windows = set( [window.tuple_format() for window in expected_windows]) self.assertSetEqual(windows, expected_windows) extent = Box(10, 10, 20, 20) windows = set( [window.tuple_format() for window in extent.get_windows(6, 6)]) expected_windows = [ Box.make_square(10, 10, 6), Box.make_square(10, 16, 6), Box.make_square(16, 10, 6), Box.make_square(16, 16, 6) ] expected_windows = set( [window.tuple_format() for window in expected_windows]) self.assertSetEqual(windows, expected_windows)
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)
def setUp(self): self.windows = [Box.make_square(0, 0, 10), Box.make_square(0, 10, 10)] self.label_arr0 = np.random.choice([1, 2], (10, 10)) self.label_arr1 = np.random.choice([1, 2], (10, 10)) def label_fn(window): if window == self.windows[0]: return self.label_arr0.copy() elif window == self.windows[1]: return self.label_arr1.copy() else: raise ValueError('Unknown window: {}'.format(window)) self.label_fn = label_fn self.labels = SemanticSegmentationLabels(self.windows, label_fn)
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 self.do_shift = self.x_shift != 0.0 or self.y_shift != 0.0 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)
def test_constructor_save(self): # Read it, write it using label_store, read it again, and compare. extent = Box.make_square(0, 0, 10) msg = rv.LabelStoreConfig.builder(rv.CHIP_CLASSIFICATION_GEOJSON) \ .with_uri(self.uri) \ .build().to_proto() config = rv.LabelStoreConfig.builder(rv.CHIP_CLASSIFICATION_GEOJSON) \ .from_proto(msg).build() label_store = config.create_store(self.task_config, extent, self.crs_transformer, self.temp_dir.name) labels1 = label_store.get_labels() new_uri = os.path.join(self.temp_dir.name, 'test_save_reload.json') msg = rv.LabelStoreConfig.builder(rv.CHIP_CLASSIFICATION_GEOJSON) \ .with_uri(new_uri) \ .build().to_proto() config = rv.LabelStoreConfig.builder(rv.CHIP_CLASSIFICATION_GEOJSON) \ .from_proto(msg).build() label_store = config.create_store(self.task_config, extent, self.crs_transformer, self.temp_dir.name) label_store.save(labels1) labels2 = label_store.get_labels() self.assertDictEqual(labels1.cell_to_class_id, labels2.cell_to_class_id)
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)
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)
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)
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)
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))
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)
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)
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)
def test_get_labels(self): data = np.zeros((10, 10, 1), dtype=np.uint8) data[7:, 7:, 0] = 1 raster_source = MockRasterSource([0, 1, 2], 3) raster_source.set_raster(data) label_source = SemanticSegmentationLabelSource(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)
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)
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)