def test_make_predict_windows_with_aoi(self): task_config = rv.TaskConfig.builder(rv.CHIP_CLASSIFICATION) \ .with_chip_size(200) \ .with_classes(['car', 'building', 'background']) \ .build() backend_config = rv.BackendConfig.builder(rv.KERAS_CLASSIFICATION) \ .with_task(task_config) \ .with_model_defaults(rv.RESNET50_IMAGENET) \ .with_pretrained_model(None) \ .build() label_source_uri = data_file_path('evaluator/cc-label-full.json') label_source = rv.LabelSourceConfig.builder(rv.CHIP_CLASSIFICATION_GEOJSON) \ .with_uri(label_source_uri) \ .build() label_source_2_uri = data_file_path('evaluator/cc-label-filtered.json') label_source_2 = rv.LabelSourceConfig.builder(rv.CHIP_CLASSIFICATION_GEOJSON) \ .with_uri(label_source_2_uri) \ .build() source_uri = data_file_path('evaluator/cc-label-img-blank.tif') raster_source = rv.RasterSourceConfig.builder(rv.RASTERIO_SOURCE) \ .with_uri(source_uri) \ .build() aoi_uri = data_file_path('evaluator/cc-label-aoi.json') s = rv.SceneConfig.builder() \ .with_id('test') \ .with_raster_source(raster_source) \ .with_label_source(label_source) \ .with_aoi_uri(aoi_uri) \ .build() with RVConfig.get_tmp_dir() as tmp_dir: scene = s.create_scene(task_config, tmp_dir) backend = backend_config.create_backend(task_config) task = task_config.create_task(backend) with scene.activate(): windows = task.get_train_windows(scene) from rastervision.data import (ChipClassificationLabels, ChipClassificationGeoJSONStore) labels = ChipClassificationLabels() for w in windows: labels.set_cell(w, 1) store = ChipClassificationGeoJSONStore( os.path.join(tmp_dir, 'test.json'), scene.raster_source.get_crs_transformer(), task_config.class_map) store.save(labels) ls = label_source_2.create_source( task_config, scene.raster_source.get_extent(), scene.raster_source.get_crs_transformer(), tmp_dir) actual = ls.get_labels().get_cells() self.assertEqual(len(windows), len(actual))
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
def infer_labels(geojson, extent, cell_size, ioa_thresh, use_intersection_over_cell, pick_min_class_id, background_class_id): """Infer ChipClassificationLabels grid from GeoJSON containing polygons. Given GeoJSON with polygons associated with class_ids, infer a grid of cells and class_ids that best captures the contents of each cell. See infer_cell for info on the args. Args: geojson: dict in normalized GeoJSON format (see VectorSource) extent: Box representing the bounds of the grid Returns: ChipClassificationLabels """ labels = ChipClassificationLabels() cells = extent.get_windows(cell_size, cell_size) # We need to associate class_id with each geom. Monkey-patching it onto the geom # seems like a bad idea, but it's the only straightforward way of doing this # that I've been able to find. geoms = [] for f in geojson['features']: g = shape(f['geometry']) g.class_id = f['properties']['class_id'] geoms.append(g) str_tree = STRtree(geoms) for cell in cells: class_id = infer_cell(cell, str_tree, ioa_thresh, use_intersection_over_cell, background_class_id, pick_min_class_id) labels.set_cell(cell, class_id) return labels
def predict(self, chips, windows, tmp_dir): """Predict on a set of chips and return a ChipClassificationLabels object with class and probabilities. Args: chips: 300x300 jpgs windows: list of int tmp_dir: temporary directory Returns: labels and probabilities """ # set compute environment depending on gpu availability ctx = [mx.gpu(0)] if gpu_enabled() else [mx.cpu(0)] # ensure model is loaded self.load_model(tmp_dir, ctx) # reshape the data to be consistent with how the model was trained data = np.transpose(chips, (0, 3, 2, 1)) # load data onto gpu/cpu, depending on context data = gluon.utils.split_and_load(data, ctx) # get list of predictions from the model. also convert to np ndarray # because that is what raster vision expects probs = [self.model(X).asnumpy() for X in data] labels = ChipClassificationLabels() for chip_probs, window in zip(probs[0], windows): # Add 1 to class_id since they start at 1. class_id = int(np.argmax(chip_probs) + 1) labels.set_cell(window, class_id, chip_probs) return labels
def predict(self, chips, windows, tmp_dir): from rastervision.backend.keras_classification.utils \ import predict # Ensure model is loaded self.load_model(tmp_dir) probs = predict(chips, self.model) labels = ChipClassificationLabels() for chip_probs, window in zip(probs, windows): # Add 1 to class_id since they start at 1. class_id = int(np.argmax(chip_probs) + 1) labels.set_cell(window, class_id, chip_probs) return labels