def nodata_transform(min_val, in_path, out_path):
    """Convert values less than min_val to 0/NODATA.

    This script was developed to deal with imagery over Belize City which contains values
    that appear to be NODATA values on the periphery of the image, but are actually very
    small values < 7. This script converts those small values to zeros which Raster
    Vision knows to ignore when making predictions.
    """
    min_val = float(min_val)
    chip_size = 1000
    with rasterio.open(in_path, 'r') as in_data:
        with rasterio.open(out_path, 'w', **in_data.profile) as out_data:
            extent = Box(0, 0, in_data.height, in_data.width)
            windows = extent.get_windows(chip_size, chip_size)
            for w in windows:
                # Avoid going off edge of array.
                if w.ymax > in_data.height:
                    w.ymax = in_data.height
                if w.xmax > in_data.width:
                    w.xmax = in_data.width

                print('.', end='', flush=True)
                w = w.rasterio_format()
                im = in_data.read(window=w)

                nodata_mask = np.all(im < min_val, axis=0)

                for b in range(im.shape[0]):
                    band = im[b, :, :]
                    band[nodata_mask] = 0
                    out_data.write_band(b + 1, band, window=w)
Esempio n. 2
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, default_class_id=0, ignore_crs_field=True)
                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)
def save_image_crop(image_uri,
                    crop_uri,
                    label_uri=None,
                    size=600,
                    min_features=10):
    """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
        crop_uri: URI of cropped image to save
        label_uri: optional URI of GeoJSON file
        size: height and width of crop

    Raises:
        ValueError if cannot find a crop satisfying min_features constraint.
    """
    if not file_exists(crop_uri):
        print('Saving test crop to {}...'.format(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 is not None:
                crs_transformer = RasterioCRSTransformer.from_dataset(
                    im_dataset)
                vs = GeoJSONVectorSource(label_uri, crs_transformer)
                geojson = vs.get_geojson()
                geoms = []
                for f in geojson['features']:
                    g = shape(f['geometry'])
                    geoms.append(g)
                tree = STRtree(geoms)

            for w in windows:
                use_window = True
                if label_uri is not None:
                    w_polys = tree.query(w.to_shapely())
                    use_window = len(w_polys) >= min_features

                if use_window:
                    w = w.rasterio_format()
                    im = im_dataset.read(window=w)

                    if np.mean(np.sum(im, axis=2).ravel() == 0) < 0.9:
                        with tempfile.TemporaryDirectory() as tmp_dir:
                            crop_path = get_local_path(crop_uri, tmp_dir)
                            make_dir(crop_path, use_dirname=True)

                            meta = im_dataset.meta
                            meta['width'], meta['height'] = size, size
                            meta['transform'] = rasterio.windows.transform(
                                w, im_dataset.transform)

                            with rasterio.open(crop_path, 'w', **meta) as dst:
                                dst.colorinterp = im_dataset.colorinterp
                                dst.write(im)

                            upload_or_copy(crop_path, crop_uri)
                        break

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