def setUp(self):
        self.tmp_dir = rv_config.get_tmp_dir()

        self.class_config = ClassConfig(names=['one', 'two'])
        self.class_config.update()
        self.class_config.ensure_null_class()
        self.null_class_id = self.class_config.get_null_class_id()
    def _test_class_inf(self, props, exp_class_ids, default_class_id=None):
        geojson = {
            'type':
            'FeatureCollection',
            'features': [{
                'properties': props,
                'geometry': {
                    'type': 'Point',
                    'coordinates': [1, 1]
                }
            }]
        }
        json_to_file(geojson, self.uri)

        class_config = ClassConfig(names=['building', 'car', 'tree'])
        class_id_to_filter = {
            0: ['==', 'type', 'building'],
            1: ['any', ['==', 'type', 'car'], ['==', 'type', 'auto']]
        }
        vs_cfg = GeoJSONVectorSourceConfig(
            uri=self.uri,
            class_id_to_filter=class_id_to_filter,
            default_class_id=default_class_id)
        vs = vs_cfg.build(class_config, IdentityCRSTransformer())
        trans_geojson = vs.get_geojson()
        class_ids = [
            f['properties']['class_id'] for f in trans_geojson['features']
        ]
        self.assertEqual(class_ids, exp_class_ids)
    def test_accounts_for_aoi(self):
        class_config = ClassConfig(names=['car', 'building', 'background'])

        label_source_uri = data_file_path('evaluator/cc-label-filtered.json')
        label_source_cfg = ChipClassificationLabelSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(
                uri=label_source_uri, default_class_id=None))

        label_store_uri = data_file_path('evaluator/cc-label-full.json')
        label_store_cfg = ChipClassificationGeoJSONStoreConfig(
            uri=label_store_uri)

        raster_source_uri = data_file_path('evaluator/cc-label-img-blank.tif')
        raster_source_cfg = RasterioSourceConfig(uris=[raster_source_uri])

        aoi_uri = data_file_path('evaluator/cc-label-aoi.json')
        s = SceneConfig(
            id='test',
            raster_source=raster_source_cfg,
            label_source=label_source_cfg,
            label_store=label_store_cfg,
            aoi_uris=[aoi_uri])

        with rv_config.get_tmp_dir() as tmp_dir:
            scene = s.build(class_config, tmp_dir)
            output_uri = os.path.join(tmp_dir, 'eval.json')

            evaluator = ChipClassificationEvaluatorConfig(
                output_uri=output_uri).build(class_config)
            evaluator.process([scene], tmp_dir)

            overall = file_to_json(output_uri)['overall']
            for item in overall:
                self.assertEqual(item['f1'], 1.0)
 def test_get_labels_rgb(self):
     data = np.zeros((10, 10, 3), dtype=np.uint8)
     data[7:, 7:, :] = [1, 1, 1]
     null_class_id = 2
     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, null_class_id, 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)
Пример #5
0
 def test_rgb_class_config_null_class(self):
     raster_source_cfg = RasterioSourceConfig(uris=['/abc/def.tif'])
     rgb_class_config = ClassConfig(names=['a'], colors=['#010101'])
     cfg = SemanticSegmentationLabelSourceConfig(
         raster_source=raster_source_cfg, rgb_class_config=rgb_class_config)
     cfg.update()
     self.assertEqual(len(cfg.rgb_class_config), 2)
     self.assertIn('null', cfg.rgb_class_config.names)
    def test_compute_ignore_class(self):
        class_config = ClassConfig(names=['one', 'two'])
        class_config.update()
        class_config.ensure_null_class()
        null_class_id = class_config.get_null_class_id()

        gt_array = np.zeros((4, 4, 1), dtype=np.uint8)
        gt_array[0, 0, 0] = 2
        gt_raster = MockRasterSource([0], 1)
        gt_raster.set_raster(gt_array)
        gt_label_source = SemanticSegmentationLabelSource(
            gt_raster, null_class_id)

        pred_array = np.zeros((4, 4, 1), dtype=np.uint8)
        pred_array[0, 0, 0] = 1
        pred_raster = MockRasterSource([0], 1)
        pred_raster.set_raster(pred_array)
        pred_label_source = SemanticSegmentationLabelSource(
            pred_raster, null_class_id)

        eval = SemanticSegmentationEvaluation(class_config)
        eval.compute(gt_label_source.get_labels(),
                     pred_label_source.get_labels())
        self.assertAlmostEqual(1.0, eval.class_to_eval_item[0].f1)
        self.assertAlmostEqual(1.0, eval.avg_item.f1)
Пример #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')
Пример #8
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)
    def test_compute(self):
        class_config = ClassConfig(names=['one', 'two'])
        class_config.update()
        class_config.ensure_null_class()
        null_class_id = class_config.get_null_class_id()

        gt_array = np.zeros((4, 4, 1), dtype=np.uint8)
        gt_array[2, 2, 0] = 1
        gt_array[0, 0, 0] = 2
        gt_raster = MockRasterSource([0], 1)
        gt_raster.set_raster(gt_array)
        gt_label_source = SemanticSegmentationLabelSource(
            gt_raster, null_class_id)

        p_array = np.zeros((4, 4, 1), dtype=np.uint8)
        p_array[1, 1, 0] = 1
        p_raster = MockRasterSource([0], 1)
        p_raster.set_raster(p_array)
        p_label_source = SemanticSegmentationLabelSource(
            p_raster, null_class_id)

        eval = SemanticSegmentationEvaluation(class_config)
        eval.compute(gt_label_source.get_labels(), p_label_source.get_labels())

        tp0 = 16 - 3  # 4*4 - 3 true positives for class 0
        fp0 = 1  # 1 false positive (2,2) and one don't care at (0,0)
        fn0 = 1  # one false negative (1,1)
        precision0 = float(tp0) / (tp0 + fp0)
        recall0 = float(tp0) / (tp0 + fn0)
        f10 = 2 * float(precision0 * recall0) / (precision0 + recall0)

        tp1 = 0  # 0 true positives for class 1
        fn1 = 1  # one false negative (2,2)
        precision1 = 0  # float(tp1) / (tp1 + fp1) where fp1 == 1
        recall1 = float(tp1) / (tp1 + fn1)
        f11 = None

        self.assertAlmostEqual(precision0,
                               eval.class_to_eval_item[0].precision)
        self.assertAlmostEqual(recall0, eval.class_to_eval_item[0].recall)
        self.assertAlmostEqual(f10, eval.class_to_eval_item[0].f1)

        self.assertEqual(precision1, eval.class_to_eval_item[1].precision)
        self.assertAlmostEqual(recall1, eval.class_to_eval_item[1].recall)
        self.assertAlmostEqual(f11, eval.class_to_eval_item[1].f1)

        avg_conf_mat = np.array([[0, 0, 0], [13., 1, 0], [1, 0, 0]])
        avg_recall = (14 / 15) * recall0 + (1 / 15) * recall1
        self.assertTrue(np.array_equal(avg_conf_mat, eval.avg_item.conf_mat))
        self.assertEqual(avg_recall, eval.avg_item.recall)
 def transform_geojson(self,
                       geojson,
                       line_bufs=None,
                       point_bufs=None,
                       crs_transformer=None,
                       to_map_coords=False):
     if crs_transformer is None:
         crs_transformer = IdentityCRSTransformer()
     class_config = ClassConfig(names=['building'])
     json_to_file(geojson, self.uri)
     cfg = GeoJSONVectorSourceConfig(
         uri=self.uri,
         line_bufs=line_bufs,
         point_bufs=point_bufs,
         default_class_id=0)
     source = cfg.build(class_config, crs_transformer)
     return source.get_geojson(to_map_coords=to_map_coords)
    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 test_vector_compute(self):
        class_config = ClassConfig(names=['one', 'two'])
        class_config.update()
        class_config.ensure_null_class()

        gt_uri = data_file_path('2-gt-polygons.geojson')
        pred_uri = data_file_path('2-pred-polygons.geojson')

        eval = SemanticSegmentationEvaluation(class_config)
        eval.compute_vector(gt_uri, pred_uri, 'polygons', 0)

        # NOTE: The  two geojson files referenced  above contain three
        # unique geometries total, each  file contains two geometries,
        # and there is one geometry shared between the two.
        tp = 1.0
        fp = 1.0
        fn = 1.0
        precision = float(tp) / (tp + fp)
        recall = float(tp) / (tp + fn)

        self.assertAlmostEqual(precision, eval.class_to_eval_item[0].precision)
        self.assertAlmostEqual(recall, eval.class_to_eval_item[0].recall)
Пример #13
0
def get_config(runner, root_uri, data_uri=None, full_train=False):
    def get_path(part):
        if full_train:
            return join(data_uri, part)
        else:
            return join(dirname(__file__), part)

    class_config = ClassConfig(names=['red', 'green'], colors=['red', 'green'])

    def make_scene(id, img_path, label_path):
        raster_source = RasterioSourceConfig(channel_order=[0, 1, 2],
                                             uris=[img_path])
        label_source = SemanticSegmentationLabelSourceConfig(
            rgb_class_config=class_config,
            raster_source=RasterioSourceConfig(uris=[label_path]))
        label_store = SemanticSegmentationLabelStoreConfig(
            rgb=True,
            vector_output=[
                PolygonVectorOutputConfig(class_id=0),
                BuildingVectorOutputConfig(class_id=1)
            ])

        return SceneConfig(id=id,
                           raster_source=raster_source,
                           label_source=label_source,
                           label_store=label_store)

    chip_sz = 300
    img_sz = chip_sz
    data = SemanticSegmentationImageDataConfig(img_sz=img_sz, augmentors=[])

    if full_train:
        model = SemanticSegmentationModelConfig(backbone=Backbone.resnet50)
        solver = SolverConfig(lr=1e-4,
                              num_epochs=300,
                              batch_sz=8,
                              one_cycle=True,
                              sync_interval=300)
    else:
        pretrained_uri = (
            'https://github.com/azavea/raster-vision-data/releases/download/v0.12/'
            'semantic-segmentation.pth')
        model = SemanticSegmentationModelConfig(backbone=Backbone.resnet50,
                                                init_weights=pretrained_uri)
        solver = SolverConfig(lr=1e-9,
                              num_epochs=1,
                              batch_sz=2,
                              one_cycle=True,
                              sync_interval=200)
    backend = PyTorchSemanticSegmentationConfig(data=data,
                                                model=model,
                                                solver=solver,
                                                log_tensorboard=False,
                                                run_tensorboard=False)

    scenes = [
        make_scene('test-scene', get_path('scene/image.tif'),
                   get_path('scene/labels.tif')),
        make_scene('test-scene2', get_path('scene/image2.tif'),
                   get_path('scene/labels2.tif'))
    ]
    scene_dataset = DatasetConfig(class_config=class_config,
                                  train_scenes=scenes,
                                  validation_scenes=scenes)

    chip_options = SemanticSegmentationChipOptions(
        window_method=SemanticSegmentationWindowMethod.sliding, stride=chip_sz)

    return SemanticSegmentationConfig(root_uri=root_uri,
                                      dataset=scene_dataset,
                                      backend=backend,
                                      train_chip_sz=chip_sz,
                                      predict_chip_sz=chip_sz,
                                      chip_options=chip_options)
Пример #14
0
def get_config(runner,
               raw_uri: str,
               processed_uri: str,
               root_uri: str,
               test: bool = False) -> SemanticSegmentationConfig:
    """Generate the pipeline config for this task. This function will be called
    by RV, with arguments from the command line, when this example is run.

    Args:
        runner (Runner): Runner for the pipeline.
        raw_uri (str): Directory where the raw data resides
        processed_uri (str): Directory for storing processed data. 
                             E.g. crops for testing.
        root_uri (str): Directory where all the output will be written.
        test (bool, optional): Whether to run in test mode. Defaults to False.

    Returns:
        SemanticSegmentationConfig: A pipeline config.
    """
    if not test:
        train_ids, val_ids = TRAIN_IDS, VAL_IDS
    else:
        train_ids, val_ids = TEST_MODE_TRAIN_IDS, TEST_MODE_VAL_IDS

    raw_uri = UriPath(raw_uri)
    processed_uri = UriPath(processed_uri)

    # -------------------------------
    # Configure dataset generation
    # -------------------------------
    class_config = ClassConfig(names=CLASS_NAMES, colors=CLASS_COLORS)

    chip_options = SemanticSegmentationChipOptions(
        window_method=SemanticSegmentationWindowMethod.sliding,
        stride=CHIP_SIZE)

    _make_scene = partial(make_scene,
                          raw_uri,
                          processed_uri,
                          class_config,
                          test_mode=test)

    dataset_config = DatasetConfig(
        class_config=class_config,
        train_scenes=[_make_scene(scene_id) for scene_id in train_ids],
        validation_scenes=[_make_scene(scene_id) for scene_id in val_ids])

    # --------------------------------------------
    # Configure PyTorch backend and training
    # --------------------------------------------
    model_config = SemanticSegmentationModelConfig(backbone=Backbone.resnet50)

    solver_config = SolverConfig(lr=LR,
                                 num_epochs=NUM_EPOCHS,
                                 batch_sz=BATCH_SIZE,
                                 test_num_epochs=TEST_MODE_NUM_EPOCHS,
                                 test_batch_sz=TEST_MODE_BATCH_SIZE,
                                 one_cycle=ONE_CYCLE)

    backend_config = PyTorchSemanticSegmentationConfig(
        model=model_config,
        solver=solver_config,
        log_tensorboard=LOG_TENSORBOARD,
        run_tensorboard=RUN_TENSORBOARD,
        test_mode=test)

    # -----------------------------------------------
    # Pass configurations to the pipeline config
    # -----------------------------------------------
    pipeline_config = SemanticSegmentationConfig(
        root_uri=root_uri,
        train_chip_sz=CHIP_SIZE,
        predict_chip_sz=CHIP_SIZE,
        chip_options=chip_options,
        dataset=dataset_config,
        backend=backend_config,
        channel_display_groups=CHANNEL_DISPLAY_GROUPS)

    return pipeline_config
Пример #15
0
def get_config(runner,
               root_uri,
               analyze_uri,
               chip_uri,
               json,
               chip_sz=512,
               batch_sz=32,
               epochs=33,
               preshrink=1,
               small_test=False,
               architecture='cheaplab',
               level='L1C'):

    chip_sz = int(chip_sz)
    epochs = int(epochs)
    batch_sz = int(batch_sz)
    preshrink = int(preshrink)
    assert (architecture in ['cheaplab', 'fpn-resnet18'])
    assert (level in ['L1C', 'L2A'])

    if level == 'L1C':
        channel_order = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    elif level == 'L2A':
        channel_order = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

    num_channels = len(channel_order)

    class_config = ClassConfig(names=["background", "cloud"],
                               colors=["brown", "white"])

    class_id_filter_dict = {
        0: ['==', 'default', 'Background'],
        1: ['==', 'default', 'Cloud'],
    }

    train_crops = []
    val_crops = []
    for x in range(0, 5):
        for y in range(0, 5):
            x_start = x / 5.0
            x_end = 0.80 - x_start
            y_start = y / 5.0
            y_end = 0.80 - y_start
            crop = [x_start, y_start, x_end, y_end]
            if x == y:
                val_crops.append(crop)
            else:
                train_crops.append(crop)

    scenes = get_scenes(json,
                        channel_order,
                        class_config,
                        class_id_filter_dict,
                        level,
                        train_crops=train_crops,
                        val_crops=val_crops)

    train_scenes, validation_scenes = scenes

    if small_test:
        train_scenes = train_scenes[0:2]
        validation_scenes = validation_scenes[0:2]

    print(f"{len(train_scenes)} training scenes")
    print(f"{len(validation_scenes)} validation scenes")

    dataset = DatasetConfig(
        class_config=class_config,
        train_scenes=train_scenes,
        validation_scenes=validation_scenes,
    )

    if architecture == 'fpn-resnet18':
        external_def = ExternalModuleConfig(
            github_repo='AdeelH/pytorch-fpn:0.1',
            name='pytorch-fpn',
            entrypoint='make_segm_fpn_resnet',
            entrypoint_kwargs={
                'name': 'resnet18',
                'fpn_type': 'fpn',
                'num_classes': 2,
                'fpn_channels': 256,
                'in_channels': len(channel_order),
                'out_size': (chip_sz, chip_sz)
            })
    else:
        external_def = ExternalModuleConfig(
            github_repo='jamesmcclain/CheapLab:08d260b',
            name='cheaplab',
            entrypoint='make_cheaplab_model',
            entrypoint_kwargs={
                'preshrink': preshrink,
                'num_channels': num_channels
            })

    model = SemanticSegmentationModelConfig(external_def=external_def)

    external_loss_def = ExternalModuleConfig(
        github_repo='jamesmcclain/CheapLab:08d260b',
        name='bce_loss',
        entrypoint='make_bce_loss',
        force_reload=False,
        entrypoint_kwargs={})

    backend = PyTorchSemanticSegmentationConfig(
        model=model,
        solver=SolverConfig(lr=1e-4,
                            num_epochs=epochs,
                            batch_sz=batch_sz,
                            external_loss_def=external_loss_def,
                            ignore_last_class='force'),
        log_tensorboard=False,
        run_tensorboard=False,
        num_workers=0,
        preview_batch_limit=8)

    chip_options = SemanticSegmentationChipOptions(
        window_method=SemanticSegmentationWindowMethod.sliding, stride=chip_sz)

    return SemanticSegmentationConfig(root_uri=root_uri,
                                      analyze_uri=analyze_uri,
                                      chip_uri=chip_uri,
                                      dataset=dataset,
                                      backend=backend,
                                      train_chip_sz=chip_sz,
                                      predict_chip_sz=chip_sz,
                                      chip_options=chip_options,
                                      chip_nodata_threshold=.75,
                                      img_format='npy',
                                      label_format='npy')
Пример #16
0
def get_config(runner, root_uri, data_uri=None, full_train=False):
    def get_path(part):
        if full_train:
            return join(data_uri, part)
        else:
            return join(dirname(__file__), part)

    class_config = ClassConfig(names=['car', 'building', 'background'],
                               colors=['red', 'blue', 'black'])

    def make_scene(img_path, label_path):
        id = basename(img_path)
        label_source = ChipClassificationLabelSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(uri=label_path,
                                                    default_class_id=None,
                                                    ignore_crs_field=True),
            ioa_thresh=0.5,
            use_intersection_over_cell=False,
            pick_min_class_id=True,
            background_class_id=2,
            infer_cells=True)

        raster_source = RasterioSourceConfig(
            channel_order=[0, 1, 2],
            uris=[img_path],
            transformers=[StatsTransformerConfig()])

        return SceneConfig(id=id,
                           raster_source=raster_source,
                           label_source=label_source)

    scenes = [
        make_scene(get_path('scene/image.tif'), get_path('scene/labels.json')),
        make_scene(get_path('scene/image2.tif'),
                   get_path('scene/labels2.json'))
    ]
    scene_dataset = DatasetConfig(class_config=class_config,
                                  train_scenes=scenes,
                                  validation_scenes=scenes)

    chip_sz = 200
    img_sz = chip_sz
    data = ClassificationImageDataConfig(img_sz=img_sz, augmentors=[])

    if full_train:
        model = ClassificationModelConfig(backbone=Backbone.resnet18)
        solver = SolverConfig(lr=1e-4,
                              num_epochs=300,
                              batch_sz=8,
                              one_cycle=True,
                              sync_interval=300)
    else:
        pretrained_uri = (
            'https://github.com/azavea/raster-vision-data/releases/download/v0.12/'
            'chip-classification.pth')
        model = ClassificationModelConfig(backbone=Backbone.resnet18,
                                          init_weights=pretrained_uri)
        solver = SolverConfig(lr=1e-9,
                              num_epochs=1,
                              batch_sz=2,
                              one_cycle=True,
                              sync_interval=200)
    backend = PyTorchChipClassificationConfig(data=data,
                                              model=model,
                                              solver=solver,
                                              log_tensorboard=False,
                                              run_tensorboard=False)

    config = ChipClassificationConfig(root_uri=root_uri,
                                      dataset=scene_dataset,
                                      backend=backend,
                                      train_chip_sz=chip_sz,
                                      predict_chip_sz=chip_sz)

    return config
class TestSemanticSegmentationEvaluator(unittest.TestCase):
    def setUp(self):
        self.tmp_dir = rv_config.get_tmp_dir()

        self.class_config = ClassConfig(names=['one', 'two'])
        self.class_config.update()
        self.class_config.ensure_null_class()
        self.null_class_id = self.class_config.get_null_class_id()

    def tearDown(self):
        self.tmp_dir.cleanup()

    def get_scene(self, class_id):
        # Make scene where ground truth is all set to class_id
        # and predictions are set to half 0's and half 1's
        scene_id = str(class_id)
        rs = MockRasterSource(channel_order=[0, 1, 2], num_channels=3)
        rs.set_raster(np.zeros((10, 10, 3)))

        gt_rs = MockRasterSource(channel_order=[0], num_channels=1)
        gt_arr = np.full((10, 10, 1), class_id)
        gt_rs.set_raster(gt_arr)
        gt_ls = SemanticSegmentationLabelSource(gt_rs, self.null_class_id)

        pred_rs = MockRasterSource(channel_order=[0], num_channels=1)
        pred_arr = np.zeros((10, 10, 1))
        pred_arr[5:10, :, :] = 1
        pred_rs.set_raster(pred_arr)
        pred_ls = SemanticSegmentationLabelSource(pred_rs, self.null_class_id)

        return Scene(scene_id, rs, gt_ls, pred_ls)

    def test_evaluator(self):
        output_uri = join(self.tmp_dir.name, 'out.json')
        scenes = [self.get_scene(0), self.get_scene(1)]
        evaluator = SemanticSegmentationEvaluator(self.class_config,
                                                  output_uri, None)
        evaluator.process(scenes, self.tmp_dir.name)
        eval_json = file_to_json(output_uri)
        exp_eval_json = file_to_json(data_file_path('expected-eval.json'))
        self.assertDictEqual(eval_json, exp_eval_json)

    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(gt_rs, self.null_class_id)

        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(pred_rs, self.null_class_id)
        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)

    def test_vector_evaluator(self):
        output_uri = join(self.tmp_dir.name, 'raster-out.json')
        vector_output_uri = join(self.tmp_dir.name, 'vector-out.json')
        scenes = [self.get_vector_scene(0), self.get_vector_scene(1)]
        evaluator = SemanticSegmentationEvaluator(self.class_config,
                                                  output_uri,
                                                  vector_output_uri)
        evaluator.process(scenes, self.tmp_dir.name)
        vector_eval_json = file_to_json(vector_output_uri)
        exp_vector_eval_json = file_to_json(
            data_file_path('expected-vector-eval.json'))

        # NOTE:  The precision  and recall  values found  in the  file
        # `expected-vector-eval.json`  are equal to fractions of  the
        # form (n-1)/n for  n <= 7 which  can be seen to  be (and have
        # been manually verified to be) correct.
        self.assertDictEqual(vector_eval_json, exp_vector_eval_json)

    def test_vector_evaluator_with_aoi(self):
        output_uri = join(self.tmp_dir.name, 'raster-out.json')
        vector_output_uri = join(self.tmp_dir.name, 'vector-out.json')
        scenes = [self.get_vector_scene(0, use_aoi=True)]
        evaluator = SemanticSegmentationEvaluator(self.class_config,
                                                  output_uri,
                                                  vector_output_uri)
        evaluator.process(scenes, self.tmp_dir.name)
        vector_eval_json = file_to_json(vector_output_uri)
        exp_vector_eval_json = file_to_json(
            data_file_path('expected-vector-eval-with-aoi.json'))

        # NOTE:  The precision  and recall  values found  in the  file
        # `expected-vector-eval.json`  are equal to fractions of  the
        # form (n-1)/n for  n <= 7 which  can be seen to  be (and have
        # been manually verified to be) correct.
        self.assertDictEqual(vector_eval_json, exp_vector_eval_json)
Пример #18
0
def get_config(runner, root_uri, data_uri=None, full_train=False):
    def get_path(part):
        if full_train:
            return join(data_uri, part)
        else:
            return join(dirname(__file__), part)

    class_config = ClassConfig(names=['car', 'building'],
                               colors=['blue', 'red'])

    def make_scene(scene_id, img_path, label_path):
        raster_source = RasterioSourceConfig(channel_order=[0, 1, 2],
                                             uris=[img_path])
        label_source = ObjectDetectionLabelSourceConfig(
            vector_source=GeoJSONVectorSourceConfig(uri=label_path,
                                                    default_class_id=None))
        return SceneConfig(id=scene_id,
                           raster_source=raster_source,
                           label_source=label_source)

    chip_sz = 300
    img_sz = chip_sz
    data = ObjectDetectionImageDataConfig(img_sz=img_sz, augmentors=[])

    if full_train:
        model = ObjectDetectionModelConfig(backbone=Backbone.resnet18)
        solver = SolverConfig(lr=1e-4,
                              num_epochs=300,
                              batch_sz=8,
                              one_cycle=True,
                              sync_interval=300)
    else:
        pretrained_uri = (
            'https://github.com/azavea/raster-vision-data/releases/download/v0.12/'
            'object-detection.pth')
        model = ObjectDetectionModelConfig(backbone=Backbone.resnet18,
                                           init_weights=pretrained_uri)
        solver = SolverConfig(lr=1e-9,
                              num_epochs=1,
                              batch_sz=2,
                              one_cycle=True,
                              sync_interval=200)
    backend = PyTorchObjectDetectionConfig(data=data,
                                           model=model,
                                           solver=solver,
                                           log_tensorboard=False,
                                           run_tensorboard=False)

    scenes = [
        make_scene('od_test', get_path('scene/image.tif'),
                   get_path('scene/labels.json')),
        make_scene('od_test-2', get_path('scene/image2.tif'),
                   get_path('scene/labels2.json'))
    ]
    scene_dataset = DatasetConfig(class_config=class_config,
                                  train_scenes=scenes,
                                  validation_scenes=scenes)

    chip_options = ObjectDetectionChipOptions(neg_ratio=1.0, ioa_thresh=1.0)
    predict_options = ObjectDetectionPredictOptions(merge_thresh=0.1,
                                                    score_thresh=0.5)

    return ObjectDetectionConfig(root_uri=root_uri,
                                 dataset=scene_dataset,
                                 backend=backend,
                                 train_chip_sz=chip_sz,
                                 predict_chip_sz=chip_sz,
                                 chip_options=chip_options,
                                 predict_options=predict_options)
Пример #19
0
def get_config(runner,
               raw_uri: str,
               processed_uri: str,
               root_uri: str,
               nochip: bool = True,
               test: bool = False) -> SemanticSegmentationConfig:
    """Generate the pipeline config for this task. This function will be called
    by RV, with arguments from the command line, when this example is run.

    Args:
        runner (Runner): Runner for the pipeline.
        raw_uri (str): Directory where the raw data resides
        processed_uri (str): Directory for storing processed data.
                             E.g. crops for testing.
        root_uri (str): Directory where all the output will be written.
        nochip (bool, optional): If True, read directly from the TIFF during
            training instead of from pre-generated chips. The analyze and chip
            commands should not be run, if this is set to True. Defaults to
            True.
        test (bool, optional): If True, does the following simplifications:
            (1) Uses only the first 2 scenes
            (2) Uses only a 600x600 crop of the scenes
            (3) Enables test mode in the learner, which makes it use the
                test_batch_sz and test_num_epochs, among other things.
            Defaults to False.

    Returns:
        SemanticSegmentationConfig: A pipeline config.
    """
    if not test:
        train_ids, val_ids = TRAIN_IDS, VAL_IDS
    else:
        train_ids, val_ids = TEST_MODE_TRAIN_IDS, TEST_MODE_VAL_IDS

    raw_uri = UriPath(raw_uri)
    processed_uri = UriPath(processed_uri)

    # -------------------------------
    # Configure dataset generation
    # -------------------------------
    class_config = ClassConfig(names=CLASS_NAMES, colors=CLASS_COLORS)

    _make_scene = partial(make_scene,
                          raw_uri,
                          processed_uri,
                          class_config,
                          test_mode=test)

    dataset_config = DatasetConfig(
        class_config=class_config,
        train_scenes=[_make_scene(scene_id) for scene_id in train_ids],
        validation_scenes=[_make_scene(scene_id) for scene_id in val_ids],
        img_channels=5)

    chip_options = SemanticSegmentationChipOptions(
        window_method=SemanticSegmentationWindowMethod.sliding,
        stride=CHIP_SIZE)

    if nochip:
        window_opts = GeoDataWindowConfig(method=GeoDataWindowMethod.sliding,
                                          size=CHIP_SIZE,
                                          stride=chip_options.stride)

        data = SemanticSegmentationGeoDataConfig(
            scene_dataset=dataset_config,
            window_opts=window_opts,
            img_sz=CHIP_SIZE,
            num_workers=4,
            channel_display_groups=CHANNEL_DISPLAY_GROUPS)
    else:
        data = SemanticSegmentationImageDataConfig(
            img_sz=CHIP_SIZE,
            num_workers=4,
            channel_display_groups=CHANNEL_DISPLAY_GROUPS)

    # --------------------------------------------
    # Configure PyTorch backend and training
    # --------------------------------------------
    model_config = SemanticSegmentationModelConfig(backbone=Backbone.resnet50)

    solver_config = SolverConfig(lr=LR,
                                 num_epochs=NUM_EPOCHS,
                                 batch_sz=BATCH_SIZE,
                                 test_num_epochs=TEST_MODE_NUM_EPOCHS,
                                 test_batch_sz=TEST_MODE_BATCH_SIZE,
                                 one_cycle=ONE_CYCLE)

    backend_config = PyTorchSemanticSegmentationConfig(
        data=data,
        model=model_config,
        solver=solver_config,
        log_tensorboard=LOG_TENSORBOARD,
        run_tensorboard=RUN_TENSORBOARD,
        test_mode=test)

    # -----------------------------------------------
    # Pass configurations to the pipeline config
    # -----------------------------------------------
    pipeline_config = SemanticSegmentationConfig(
        root_uri=root_uri,
        train_chip_sz=CHIP_SIZE,
        predict_chip_sz=CHIP_SIZE,
        chip_options=chip_options,
        dataset=dataset_config,
        backend=backend_config,
        channel_display_groups=CHANNEL_DISPLAY_GROUPS)

    return pipeline_config
Пример #20
0
def get_config(runner,
               root_uri,
               json,
               dataset,
               catalog_dir='/vsizip//workdir',
               imagery_dir='/opt/data',
               chip_sz=512,
               N=None):

    chip_sz = int(chip_sz)

    if dataset == 'cloud':
        class_config = ClassConfig(
            names=[
                'algal_bloom', 'normal_water', 'cloud', 'cloud_shadow', 'other'
            ],
            colors=['green', 'blue', 'white', 'gray', 'brown'])
        class_id_filter_dict = {
            0: ['==', 'default', 'Algal bloom'],
            1: ['==', 'default', 'Non-algal-bloomed water'],
            2: ['==', 'default', 'Cloud'],
            3: ['==', 'default', 'Cloud shadow'],
            0xff: ['==', 'default', 'Other '],
        }
    elif dataset == 'tree':
        class_config = ClassConfig(names=['green_stage', 'red_stage', 'other'],
                                   colors=['green', 'brown', 'cyan'])
        class_id_filter_dict = {
            0: ['==', 'default', "Green stage conifer"],
            1: ['==', 'default', "Red stage conifer"],
            0xff: ['==', 'default', "Other"],
        }
    else:
        raise Exception()

    train_crops = []
    val_crops = []
    for x in range(0, 5):
        for y in range(0, 5):
            x_start = x / 5.0
            x_end = 0.80 - x_start
            y_start = y / 5.0
            y_end = 0.80 - y_start
            crop = [x_start, y_start, x_end, y_end]
            if x == y:
                val_crops.append(crop)
            else:
                train_crops.append(crop)

    scenes = get_scenes(json,
                        class_config,
                        class_id_filter_dict,
                        catalog_dir,
                        imagery_dir,
                        train_crops=train_crops,
                        val_crops=val_crops,
                        N=N)

    train_scenes, validation_scenes = scenes

    print(f'{len(train_scenes)} training scenes')
    print(f'{len(validation_scenes)} validation scenes')

    dataset = DatasetConfig(
        class_config=class_config,
        train_scenes=train_scenes,
        validation_scenes=validation_scenes,
    )

    solver = SolverConfig()
    data = SemanticSegmentationImageDataConfig(img_sz=chip_sz,
                                               num_workers=0,
                                               preview_batch_limit=8)
    model = SemanticSegmentationModelConfig()

    backend = PyTorchSemanticSegmentationConfig(model=model,
                                                data=data,
                                                solver=solver)

    chip_options = SemanticSegmentationChipOptions(
        window_method=SemanticSegmentationWindowMethod.sliding, stride=chip_sz)

    return SemanticSegmentationConfig(root_uri=root_uri,
                                      dataset=dataset,
                                      backend=backend,
                                      train_chip_sz=chip_sz,
                                      predict_chip_sz=chip_sz,
                                      chip_options=chip_options,
                                      chip_nodata_threshold=.75,
                                      img_format='npy',
                                      label_format='png')