示例#1
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         rgb=('04', '03', '02'),
         tilesize=256):
    """Create mercator tile from Sentinel-2 data.

    Attributes
    ----------

    sceneid : str
        Sentinel-2 sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    rgb : tuple, str, optional (default: ('04', '03', '02'))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array
    """

    if not isinstance(rgb, tuple):
        rgb = tuple((rgb, ))

    scene_params = utils.sentinel_parse_scene_id(sceneid)
    sentinel_address = '{}/{}'.format(SENTINEL_BUCKET, scene_params['key'])

    sentinel_preview = '{}/preview.jp2'.format(sentinel_address)
    with rasterio.open(sentinel_preview) as src:
        wgs_bounds = transform_bounds(*[src.crs, 'epsg:4326'] +
                                      list(src.bounds),
                                      densify_pts=21)

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds('Tile {}/{}/{} is outside image bounds'.format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    addresses = ['{}/B{}.jp2'.format(sentinel_address, band) for band in rgb]

    _tiler = partial(utils.tile_band_worker,
                     bounds=tile_bounds,
                     tilesize=tilesize,
                     nodata=0)
    with futures.ThreadPoolExecutor(max_workers=3) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
示例#2
0
    def expression(self,
                   x: int,
                   y: int,
                   z: int,
                   expr: str,
                   tilesize: int = 256,
                   **kwargs: Any) -> Tuple[numpy.ndarray, numpy.ndarray]:
        """
        Read Tile from a COG and apply simple band math.

        Attributes
        ----------
            x : int
                X tile map index.
            y : int
                y tile map index
            z : int
                Z tile map index
            expr : str
                Band math expression.
            tilesize : int, optional
                Output tile size. Default is 256
            kwargs : Any, optional
                Additional options to forward to rio_tiler.utils._tile_read

        Returns
        -------
            tile : numpy.ndarray
                Tile data.
            mask : numpy.ndarray
                Mask data.

        """
        if not self.tile_exists(x, y, z):
            raise TileOutsideBounds(
                f"Tile {z}/{x}/{y} is outside image bounds")
        tile_bounds = mercantile.xy_bounds(mercantile.Tile(x=x, y=y, z=z))

        bands_names = tuple(set(re.findall(r"b(?P<bands>[0-9A]{1,2})", expr)))
        expr_bands = ["b{}".format(b) for b in bands_names]

        indexes = tuple(map(int, bands_names))
        tile, mask = _tile_read(self.src_dst,
                                tile_bounds,
                                tilesize,
                                indexes=indexes,
                                **kwargs)

        tile = dict(zip(expr_bands, tile))
        rgb = expr.split(",")
        return (
            numpy.array([
                numpy.nan_to_num(
                    numexpr.evaluate(bloc.strip(), local_dict=tile))
                for bloc in rgb
            ]),
            mask,
        )
示例#3
0
def tile(sceneid, tile_x, tile_y, tile_z, bands=("04", "03", "02"), tilesize=256):
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
    sceneid : str
        Sentinel-2 sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ('04', '03', '02'))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands,))

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName("{} is not a valid Sentinel band name".format(band))

    scene_params = _sentinel_parse_scene_id(sceneid)
    sentinel_address = "{}/{}".format(SENTINEL_BUCKET, scene_params["key"])

    sentinel_preview = "{}/preview.jp2".format(sentinel_address)
    with rasterio.open(sentinel_preview) as src:
        wgs_bounds = transform_bounds(
            *[src.crs, "epsg:4326"] + list(src.bounds), densify_pts=21
        )

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            "Tile {}/{}/{} is outside image bounds".format(tile_z, tile_x, tile_y)
        )

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    addresses = ["{}/B{}.jp2".format(sentinel_address, band) for band in bands]

    _tiler = partial(utils.tile_read, bounds=tile_bounds, tilesize=tilesize, nodata=0)
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
示例#4
0
def tile(address,
         tile_x,
         tile_y,
         tile_z,
         rgb=None,
         tilesize=256,
         nodata=None,
         alpha=None):
    """Create mercator tile from any images.

    Attributes
    ----------

    address : str
        file url.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    rgb : tuple, int, optional (default: (1, 2, 3))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    nodata: int or float, optional (defaults: None)
    alpha: int, optional (defaults: None)
        Force alphaband if not present in the dataset metadata

    Returns
    -------
    data : numpy ndarray
    mask: numpy array
    """

    with rasterio.open(address) as src:
        wgs_bounds = transform_bounds(*[src.crs, 'epsg:4326'] +
                                      list(src.bounds),
                                      densify_pts=21)
        nodata = nodata if nodata is not None else src.nodata
        if not rgb:
            rgb = src.indexes

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds('Tile {}/{}/{} is outside image bounds'.format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)
    return utils.tile_band_worker(address,
                                  tile_bounds,
                                  tilesize,
                                  indexes=rgb,
                                  nodata=nodata,
                                  alpha=alpha)
示例#5
0
文件: aws.py 项目: exlimit/rio-tiler
def tile(bucket, key, tile_x, tile_y, tile_z, rgb=(1, 2, 3),  tilesize=256,
         prefix='s3:/'):
    """Create mercator tile from AWS hosted images and encodes it in base64.

    Attributes
    ----------

    bucket : str
        AWS bucket's name.
    key : str
        AWS file's key.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    tileformat : str
        Image format to return (Accepted: "jpg" or "png")
    rgb : tuple, int, optional (default: (1, 2, 3))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    out : numpy ndarray
    """

    source_address = '{}/{}/{}'.format(prefix, bucket, key)

    with rasterio.open(source_address) as src:
        wgs_bounds = transform_bounds(
            *[src.crs, 'epsg:4326'] + list(src.bounds), densify_pts=21)
        nodata = src.nodata

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            'Tile {}/{}/{} is outside image bounds'.format(
                tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    w, s, e, n = tile_bounds

    out = utils.tile_band_worker(source_address,
                                 tile_bounds,
                                 tilesize,
                                 indexes=rgb,
                                 nodata=nodata)

    return out
示例#6
0
文件: main.py 项目: betatim/rio-tiler
def tile(address,
         tile_x,
         tile_y,
         tile_z,
         indexes=None,
         tilesize=256,
         nodata=None):
    """
    Create mercator tile from any images.

    Attributes
    ----------
    address : str
        file url.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    indexes : tuple, int, optional (default: (1, 2, 3))
        Bands indexes for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    nodata: int or float, optional
        Overwrite nodata value for mask creation.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    with rasterio.open(address) as src:
        wgs_bounds = transform_bounds(*[src.crs, 'epsg:4326'] +
                                      list(src.bounds),
                                      densify_pts=21)

        indexes = indexes if indexes is not None else src.indexes

        if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
            raise TileOutsideBounds(
                'Tile {}/{}/{} is outside image bounds'.format(
                    tile_z, tile_x, tile_y))

        mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
        tile_bounds = mercantile.xy_bounds(mercator_tile)
        return utils.tile_read(src,
                               tile_bounds,
                               tilesize,
                               indexes=indexes,
                               nodata=nodata)
示例#7
0
    def tile(
        self,
        x: int,
        y: int,
        z: int,
        tilesize: int = 256,
        assets: Optional[List[str]] = None,
        **kwargs: Any,
    ) -> Tuple[numpy.ndarray, numpy.ndarray]:
        """
        Read Tile from a COG.

        Attributes
        ----------
            x : int
                X tile map index.
            y : int
                y tile map index
            z : int
                Z tile map index
            assets : list or tuple or int, optional
                Band assets.
            tilesize : int, optional
                Output tile size. Default is 256.
            kwargs : Any, optional
                Additional options to forward to rio_tiler.utils._tile_read

        Returns
        -------
            tile : numpy.ndarray
                Tile data.
            mask : numpy.ndarray
                Mask data.

        """
        if isinstance(assets, str):
            assets = [assets]
        elif isinstance(assets, tuple):
            assets = list(assets)

        if not self.tile_exists(x, y, z):
            raise TileOutsideBounds(
                f"Tile {z}/{x}/{y} is outside image bounds")

        assets = assets if assets else list(self.item["assets"].keys())
        assets = [self.item["assets"][asset]["href"] for asset in assets]
        return self._read_multiple(assets,
                                   x,
                                   y,
                                   z,
                                   tilesize=tilesize,
                                   **kwargs)
示例#8
0
def tile(
    src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT],
    x: int,
    y: int,
    z: int,
    tilesize: int = 256,
    **kwargs,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Read mercator tile from an image.

    Attributes
    ----------
        src_dst : rasterio.io.DatasetReader
            rasterio.io.DatasetReader object
        x : int
            Mercator tile X index.
        y : int
            Mercator tile Y index.
        z : int
            Mercator tile ZOOM level.
        tilesize : int, optional
            Output tile size. Default is 256.
        kwargs : Any, optional
            Additional options to forward to part()

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    bounds = transform_bounds(src_dst.crs,
                              constants.WGS84_CRS,
                              *src_dst.bounds,
                              densify_pts=21)
    if not tile_exists(bounds, z, x, y):
        raise TileOutsideBounds(f"Tile {z}/{x}/{y} is outside image bounds")

    tile_bounds = mercantile.xy_bounds(mercantile.Tile(x=x, y=y, z=z))
    return part(
        src_dst,
        tile_bounds,
        tilesize,
        tilesize,
        dst_crs=constants.WEB_MERCATOR_CRS,
        **kwargs,
    )
示例#9
0
    def _s1_tiler(src_path):
        with rasterio.open(src_path) as src_dst:
            with WarpedVRT(
                    src_dst,
                    src_crs=src_dst.gcps[1],
                    src_transform=transform.from_gcps(src_dst.gcps[0]),
                    src_nodata=0,
            ) as vrt_dst:
                if not utils.tile_exists(vrt_dst.bounds, tile_z, tile_x,
                                         tile_y):
                    raise TileOutsideBounds(
                        "Tile {}/{}/{} is outside image bounds".format(
                            tile_z, tile_x, tile_y))

                return utils._tile_read(vrt_dst,
                                        bounds=tile_bounds,
                                        tilesize=tilesize)
示例#10
0
def tile(
    stac: Dict,
    assets: Sequence[str],
    tile_x: int,
    tile_y: int,
    tile_z: int,
    tilesize: int = 256,
    **kwargs: Any,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from any images.

    Attributes
    ----------
        stac : dict
            STAC item.
        assets : list
            Asset names.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        tilesize : int, optional (default: 256)
            Output image size.
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.reader.tile' function.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    if isinstance(assets, str):
        assets = (assets, )

    if not tile_exists(stac["bbox"], tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            f"Tile {tile_z}/{tile_x}/{tile_y} is outside item bounds")

    assets_url = _get_href(stac, assets)
    return reader.multi_tile(assets_url, tile_x, tile_y, tile_z, **kwargs)
示例#11
0
    def tile(
        self,
        tile_x: int,
        tile_y: int,
        tile_z: int,
        tilesize: int = 256,
        indexes: Optional[Sequence] = None,
        expression: Optional[str] = "",
        **kwargs: Any,
    ) -> Tuple[numpy.ndarray, numpy.ndarray]:
        """Read a TMS map tile from a COG."""
        kwargs = {**self._kwargs, **kwargs}

        if isinstance(indexes, int):
            indexes = (indexes, )

        if expression:
            indexes = parse_expression(expression)

        tile = morecantile.Tile(x=tile_x, y=tile_y, z=tile_z)
        if not self._tile_exists(tile):
            raise TileOutsideBounds(
                "Tile {}/{}/{} is outside image bounds".format(
                    tile_z, tile_x, tile_y))

        tile_bounds = self.tms.xy_bounds(*tile)
        tile, mask = reader.part(
            self.dataset,
            tile_bounds,
            tilesize,
            tilesize,
            dst_crs=self.tms.crs,
            indexes=indexes,
            **kwargs,
        )
        if expression:
            blocks = expression.lower().split(",")
            bands = [f"b{bidx}" for bidx in indexes]
            tile = apply_expression(blocks, bands, tile)

        return tile, mask
示例#12
0
    def tile(
        self,
        x: int,
        y: int,
        z: int,
        tilesize: int = 256,
        **kwargs: Any,
    ) -> Tuple[numpy.ndarray, numpy.ndarray]:
        """
        Read Tile from a COG.

        Attributes
        ----------
            x : int
                X tile map index.
            y : int
                y tile map index
            z : int
                Z tile map index
            indexes : list or tuple or int, optional
                Band indexes.
            tilesize : int, optional
                Output tile size. Default is 256.
            kwargs : Any, optional
                Additional options to forward to rio_tiler.utils._tile_read

        Returns
        -------
            tile : numpy.ndarray
                Tile data.
            mask : numpy.ndarray
                Mask data.

        """
        if not self.tile_exists(x, y, z):
            raise TileOutsideBounds(
                f"Tile {z}/{x}/{y} is outside image bounds")

        tile_bounds = mercantile.xy_bounds(mercantile.Tile(x=x, y=y, z=z))
        return _tile_read(self.src_dst, tile_bounds, tilesize, **kwargs)
示例#13
0
def tile(address, tile_x, tile_y, tile_z, tilesize=256, **kwargs):
    """
    Create mercator tile from any images.

    Attributes
    ----------
    address : str
        file url.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    tilesize : int, optional (default: 256)
        Output image size.
    kwargs: dict, optional
        These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    with rasterio.open(address) as src:
        bounds = transform_bounds(src.crs,
                                  "epsg:4326",
                                  *src.bounds,
                                  densify_pts=21)

        if not utils.tile_exists(bounds, tile_z, tile_x, tile_y):
            raise TileOutsideBounds(
                "Tile {}/{}/{} is outside image bounds".format(
                    tile_z, tile_x, tile_y))

        mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
        tile_bounds = mercantile.xy_bounds(mercator_tile)
        return utils.tile_read(src, tile_bounds, tilesize, **kwargs)
示例#14
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         rgb=(4, 3, 2),
         r_bds=(0, 16000),
         g_bds=(0, 16000),
         b_bds=(0, 16000),
         tilesize=256,
         pan=False):
    """Create mercator tile from Landsat-8 data and encodes it in base64.

    Attributes
    ----------

    sceneid : str
        Landsat sceneid. For scenes after May 2017,
        sceneid have to be LANDSAT_PRODUCT_ID.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    rgb : tuple, int, optional (default: (4, 3, 2))
        Bands index for the RGB combination.
    r_bds : tuple, int, optional (default: (0, 16000))
        First band (red) DN min and max values (DN * 10,000)
        used for the linear rescaling.
    g_bds : tuple, int, optional (default: (0, 16000))
        Second band (green) DN min and max values (DN * 10,000)
        used for the linear rescaling.
    b_bds : tuple, int, optional (default: (0, 16000))
        Third band (blue) DN min and max values (DN * 10,000)
        used for the linear rescaling.
    tilesize : int, optional (default: 256)
        Output image size.
    pan : boolean, optional (default: False)
        If True, apply pan-sharpening.

    Returns
    -------
    out : numpy ndarray (type: uint8)
    """

    scene_params = utils.landsat_parse_scene_id(sceneid)
    meta_data = utils.landsat_get_mtl(sceneid).get('L1_METADATA_FILE')
    landsat_address = '{}/{}'.format(LANDSAT_BUCKET, scene_params['key'])

    wgs_bounds = toa_utils._get_bounds_from_metadata(
        meta_data['PRODUCT_METADATA'])

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds('Tile {}/{}/{} is outside image bounds'.format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    # define a list of bands Min and Max Values (from input)
    histo_cuts = dict(zip(rgb, [r_bds, g_bds, b_bds]))

    ms_tile_size = int(tilesize / 2) if pan else tilesize

    addresses = ['{}_B{}.TIF'.format(landsat_address, band) for band in rgb]
    _tiler = partial(utils.tile_band_worker,
                     bounds=tile_bounds,
                     tilesize=ms_tile_size)

    with futures.ThreadPoolExecutor(max_workers=3) as executor:
        out = np.stack(list(executor.map(_tiler, addresses)))

        if pan:
            pan_address = '{}_B8.TIF'.format(landsat_address)
            matrix_pan = utils.tile_band_worker(pan_address, tile_bounds,
                                                tilesize)

            w, s, e, n = tile_bounds
            pan_transform = transform.from_bounds(w, s, e, n, tilesize,
                                                  tilesize)
            vis_transform = pan_transform * Affine.scale(2.)
            out = pansharpen(out,
                             vis_transform,
                             matrix_pan,
                             pan_transform,
                             np.int16,
                             'EPSG:3857',
                             'EPSG:3857',
                             0.2,
                             method='Brovey',
                             src_nodata=0)

        sun_elev = meta_data['IMAGE_ATTRIBUTES']['SUN_ELEVATION']

        for bdx, band in enumerate(rgb):
            multi_reflect = meta_data['RADIOMETRIC_RESCALING'].get(
                'REFLECTANCE_MULT_BAND_{}'.format(band))

            add_reflect = meta_data['RADIOMETRIC_RESCALING'].get(
                'REFLECTANCE_ADD_BAND_{}'.format(band))

            out[bdx] = 10000 * reflectance.reflectance(
                out[bdx], multi_reflect, add_reflect, sun_elev, src_nodata=0)

            out[bdx] = np.where(
                out[bdx] > 0,
                utils.linear_rescale(out[bdx],
                                     in_range=histo_cuts.get(band),
                                     out_range=[1, 255]), 0)

    return out.astype(np.uint8)
示例#15
0
def part(
    src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT],
    bounds: Tuple[float, float, float, float],
    height: Optional[int] = None,
    width: Optional[int] = None,
    padding: int = 0,
    dst_crs: Optional[CRS] = None,
    bounds_crs: Optional[CRS] = None,
    minimum_overlap: Optional[float] = None,
    warp_vrt_option: Dict = {},
    max_size: Optional[int] = None,
    **kwargs: Any,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Read part of an image.

    Attributes
    ----------
    src_dst: rasterio.io.DatasetReader
        rasterio.io.DatasetReader object
    bounds: tuple
        Output bounds (left, bottom, right, top) in target crs ("dst_crs").
    height: int, optional
        Output height of the array.
    width: int, optional
        Output width of the array.
    padding: int, optional
        Padding to apply to each edge of the tile when retrieving data
        to assist in reducing resampling artefacts along edges.
    dst_crs: CRS or str, optional
        Target coordinate reference system, default is "epsg:3857".
    bounds_crs: CRS or str, optional
        Overwrite bounds coordinate reference system, default is equal
        to the output CRS (dst_crs).
    minimum_tile_cover: float, optional
        Minimum % overlap for which to raise an error with dataset not
        covering enought of the tile.
    warp_vrt_option: dict, optional
        These will be passed to the rasterio.warp.WarpedVRT class.
    max_size: int, optional
        Limit output size array if not widht and height.
    kwargs: Any, optional
        Additional options to forward to reader._read()

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not dst_crs:
        dst_crs = src_dst.crs

    if max_size and width and height:
        warnings.warn(
            "'max_size' will be ignored with with 'height' and 'width' set.",
            UserWarning,
        )

    if bounds_crs:
        bounds = transform_bounds(bounds_crs, dst_crs, *bounds, densify_pts=21)

    if minimum_overlap:
        src_bounds = transform_bounds(src_dst.crs,
                                      dst_crs,
                                      *src_dst.bounds,
                                      densify_pts=21)
        x_overlap = max(
            0,
            min(src_bounds[2], bounds[2]) - max(src_bounds[0], bounds[0]))
        y_overlap = max(
            0,
            min(src_bounds[3], bounds[3]) - max(src_bounds[1], bounds[1]))
        cover_ratio = (x_overlap * y_overlap) / ((bounds[2] - bounds[0]) *
                                                 (bounds[3] - bounds[1]))

        if cover_ratio < minimum_overlap:
            raise TileOutsideBounds(
                "Dataset covers less than {:.0f}% of tile".format(cover_ratio *
                                                                  100))

    vrt_transform, vrt_width, vrt_height = get_vrt_transform(src_dst,
                                                             bounds,
                                                             height,
                                                             width,
                                                             dst_crs=dst_crs)

    window = windows.Window(col_off=0,
                            row_off=0,
                            width=vrt_width,
                            height=vrt_height)

    if max_size and not (width and height):
        if max(vrt_width, vrt_height) > max_size:
            ratio = vrt_height / vrt_width
            if ratio > 1:
                height = max_size
                width = math.ceil(height / ratio)
            else:
                width = max_size
                height = math.ceil(width * ratio)

    out_height = height or vrt_height
    out_width = width or vrt_width
    if padding > 0 and not is_aligned(src_dst, bounds, out_height, out_width):
        vrt_transform = vrt_transform * Affine.translation(-padding, -padding)
        orig_vrt_height = vrt_height
        orig_vrt_width = vrt_width
        vrt_height = vrt_height + 2 * padding
        vrt_width = vrt_width + 2 * padding
        window = windows.Window(
            col_off=padding,
            row_off=padding,
            width=orig_vrt_width,
            height=orig_vrt_height,
        )

    return _read(
        src_dst,
        out_height,
        out_width,
        window=window,
        vrt_options=dict(
            crs=dst_crs,
            transform=vrt_transform,
            width=vrt_width,
            height=vrt_height,
            **warp_vrt_option,
        ),
        **kwargs,
    )
示例#16
0
def tile(sceneid, tile_x, tile_y, tile_z, bands=None, tilesize=256):
    """
    Create mercator tile from CBERS data.

    Attributes
    ----------
    sceneid : str
        CBERS sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, int, optional (default: None)
        Bands index for the RGB combination. If None uses default
        defined for the instrument
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    scene_params = utils.cbers_parse_scene_id(sceneid)

    if not bands:
        bands = scene_params["rgb"]

    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    cbers_address = "{}/{}".format(CBERS_BUCKET, scene_params["key"])

    with rasterio.open("{}/{}_BAND{}.tif".format(
            cbers_address, sceneid, scene_params["reference_band"])) as src:
        wgs_bounds = transform_bounds(*[src.crs, "epsg:4326"] +
                                      list(src.bounds),
                                      densify_pts=21)

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    addresses = [
        "{}/{}_BAND{}.tif".format(cbers_address, sceneid, band)
        for band in bands
    ]

    _tiler = partial(utils.tile_read,
                     bounds=tile_bounds,
                     tilesize=tilesize,
                     nodata=0)
    with futures.ThreadPoolExecutor(max_workers=3) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
示例#17
0
def tile(
    sceneid: str,
    tile_x: int,
    tile_y: int,
    tile_z: int,
    bands: Union[Sequence[str], str] = ("04", "03", "02"),
    tilesize: int = 256,
    **kwargs: Dict,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
        sceneid : str
            Sentinel-2 sceneid.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple, str, optional (default: ('04', '03', '02'))
            Bands index for the RGB combination.
        tilesize : int, optional (default: 256)
            Output image size.
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    if isinstance(bands, str):
        bands = (bands, )

    scene_params = sentinel2_parser(sceneid)
    for band in bands:
        if band not in scene_params["valid_bands"]:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    sentinel_prefix = "{scheme}://{bucket}/{prefix}".format(**scene_params)

    preview_file = os.path.join(sentinel_prefix, scene_params["preview_file"])
    with rasterio.open(preview_file) as src:
        bounds = transform_bounds(src.crs,
                                  constants.WGS84_CRS,
                                  *src.bounds,
                                  densify_pts=21)
        if not tile_exists(bounds, tile_z, tile_x, tile_y):
            raise TileOutsideBounds(
                "Tile {}/{}/{} is outside image bounds".format(
                    tile_z, tile_x, tile_y))

    if scene_params["processingLevel"] == "L2A":
        bands = [_l2_prefixed_band(b) for b in bands]
    else:
        bands = ["B{}".format(b) for b in bands]

    addresses = [f"{sentinel_prefix}/{band}.jp2" for band in bands]
    return reader.multi_tile(addresses,
                             tile_x,
                             tile_y,
                             tile_z,
                             tilesize=tilesize,
                             nodata=0)
示例#18
0
def tile(
    sceneid: str,
    tile_x: int,
    tile_y: int,
    tile_z: int,
    bands: Union[Sequence[str], str] = ["4", "3", "2"],
    tilesize: int = 256,
    pan: bool = False,
    **kwargs: Any,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from Landsat-8 data.

    Attributes
    ----------
        sceneid : str
            Landsat sceneid. For scenes after May 2017,
            sceneid have to be LANDSAT_PRODUCT_ID.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple, str, optional (default: ("4", "3", "2"))
            Bands index for the RGB combination.
        tilesize : int, optional (default: 256)
            Output image size.
        pan : boolean, optional (default: False)
            If True, apply pan-sharpening.
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if isinstance(bands, str):
        bands = (bands,)

    for band in bands:
        if band not in LANDSAT_BANDS:
            raise InvalidBandName("{} is not a valid Landsat band name".format(band))

    scene_params = landsat_parser(sceneid)

    meta: Dict = _landsat_get_mtl(sceneid)["L1_METADATA_FILE"]

    landsat_prefix = "{scheme}://{bucket}/{prefix}/{scene}".format(**scene_params)

    bounds = toa_utils._get_bounds_from_metadata(meta["PRODUCT_METADATA"])
    if not tile_exists(bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            "Tile {}/{}/{} is outside image bounds".format(tile_z, tile_x, tile_y)
        )

    def worker(band: str):
        asset = f"{landsat_prefix}_B{band}.TIF"

        if band == "QA":
            nodata = 1
            resamp = "nearest"
        else:
            nodata = 0
            resamp = "bilinear"

        with rasterio.open(asset) as src_dst:
            tile, mask = reader.tile(
                src_dst,
                tile_x,
                tile_y,
                tile_z,
                tilesize=tilesize,
                nodata=nodata,
                resampling_method=resamp,
            )

        return tile, mask

    with futures.ThreadPoolExecutor(max_workers=constants.MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(worker, bands)))
        data = numpy.concatenate(data)
        mask = numpy.all(masks, axis=0).astype(numpy.uint8) * 255

        if pan:
            pan_data, mask = worker("8")
            data = pansharpening_brovey(data, pan_data, 0.2, pan_data.dtype)

        if bands[0] != "QA" or len(bands) != 1:
            for bdx, band in enumerate(bands):
                data[bdx] = _convert(data[bdx], band, meta)

        return data, mask
示例#19
0
    def raw(
        self,
        x: int,
        y: int,
        z: int,
        indexes: Optional[Union[Tuple, List, int]] = None,
        tilesize: int = 256,
        **kwargs: Any,
    ) -> bytes:
        """
        Read Tile from a COG and render as a GeoTIFF file.

        Attributes
        ----------
            x : int
                X tile map index.
            y : int
                y tile map index
            z : int
                Z tile map index
            indexes : list or tuple or int, optional
                Band indexes.
            tilesize : int, optional
                Output tile size. Default is 256
            kwargs : Any, optional
                Additional options to forward to rio_tiler.utils._tile_read

        Returns
        -------
            bytes : GeoTIFF binary content

        """
        if not self.tile_exists(x, y, z):
            raise TileOutsideBounds(
                f"Tile {z}/{x}/{y} is outside image bounds")
        tile_bounds = mercantile.xy_bounds(mercantile.Tile(x=x, y=y, z=z))

        if isinstance(indexes, int):
            indexes = (indexes, )

        indexes = indexes if indexes else self.src_dst.indexes

        tile, alpha = _tile_read(self.src_dst,
                                 tile_bounds,
                                 tilesize,
                                 indexes=indexes,
                                 **kwargs)

        count, _, _ = tile.shape
        output_profile = dict(
            driver="GTiff",
            dtype=tile.dtype,
            count=count,
            nodata=self.src_dst.nodata,
            height=tilesize,
            width=tilesize,
        )
        options = geotiff_options(x, y, z, tilesize)
        output_profile.update(options)

        with MemoryFile() as memfile:
            with memfile.open(**output_profile) as dst:
                dst.write(tile, indexes=list(range(1, count + 1)))
                if has_mask_band(self.src_dst):
                    dst.write_mask(alpha.astype("uint8"))

                dst.colorinterp = [
                    self.src_dst.colorinterp[b - 1] for b in indexes
                ]
                if self._colormap:
                    dst.write_colormap(1, self._colormap)

                for i, b in enumerate(indexes):
                    dst.set_band_description(i + 1,
                                             self.src_dst.descriptions[b - 1])
                    dst.update_tags(i + 1, **self.src_dst.tags(b))

                dst.update_tags(**self.src_dst.tags())
                dst._set_all_scales(
                    [self.src_dst.scales[b - 1] for b in indexes])
                dst._set_all_offsets(
                    [self.src_dst.offsets[b - 1] for b in indexes])

            return memfile.read()
示例#20
0
def tile_utm_source(src,
                    ll_x,
                    ll_y,
                    ur_x,
                    ur_y,
                    indexes=None,
                    tilesize=256,
                    nodata=None,
                    alpha=None,
                    dst_crs='epsg:4326'):
    """
    Create a UTM tile from a :py:class:`rasterio.Dataset` in memory.

    Arguments
    ---------
    src : :py:class:`rasterio.Dataset`
        Source imagery dataset to tile.
    ll_x : int or float
        Lower left x position (i.e. Western bound).
    ll_y : int or f
    loat
        Lower left y position (i.e. Southern bound).
    ur_x : int or float
        Upper right x position (i.e. Eastern bound).
    ur_y : int or float
        Upper right y position (i.e. Northern bound).
    indexes : tuple of 3 ints, optional
        Band indexes for the output. By default, extracts all of the
        indexes from `src`.
    tilesize : int, optional
        Output image X and Y pixel extent. Defaults to ``256``.
    nodata : int or float, optional
        Value to use for `nodata` pixels during tiling. By default, uses
        the existing `nodata` value in `src`.
    alpha : int, optional
        Alpha band index for tiling. By default, uses the same band as
        specified by `src`.
    dst_crs : str, optional
        Coordinate reference system for output. Defaults to ``"epsg:4326"``.

    Returns
    -------
    ``(data, mask, window, window_transform)`` tuple.
        data : :py:class:`numpy.ndarray`
            int pixel values. Shape is ``(C, Y, X)`` if retrieving multiple
            channels, ``(Y, X)`` otherwise.
        mask : :py:class:`numpy.ndarray`
            int mask indicating which pixels contain information and which are
            `nodata`. Pixels containing data have value ``255``, `nodata`
            pixels have value ``0``.
        window : :py:class:`rasterio.windows.Window`
            :py:class:`rasterio.windows.Window` object indicating the raster
            location of the dataset subregion being returned in `data`.
        window_transform : :py:class:`affine.Affine`
            Affine transformation for the window.

    """

    wgs_bounds = transform_bounds(*[src.crs, dst_crs] + list(src.bounds),
                                  densify_pts=21)

    indexes = indexes if indexes is not None else src.indexes
    tile_bounds = (ll_x, ll_y, ur_x, ur_y)
    if not utils.tile_exists_utm(wgs_bounds, tile_bounds):
        raise TileOutsideBounds(
            'Tile {}/{}/{}/{} is outside image bounds'.format(tile_bounds))

    return utils.tile_read_utm(src,
                               tile_bounds,
                               tilesize,
                               indexes=indexes,
                               nodata=nodata,
                               alpha=alpha,
                               dst_crs=dst_crs)
示例#21
0
def _tile_read(
    src_dst,
    bounds,
    tilesize,
    indexes=None,
    nodata=None,
    resampling_method="bilinear",
    tile_edge_padding=2,
    dst_crs=CRS({"init": "EPSG:3857"}),
    bounds_crs=None,
    minimum_tile_cover=None,
    warp_vrt_option={},
):
    """
    Read data and mask.

    Attributes
    ----------
    src_dst : rasterio.io.DatasetReader
        rasterio.io.DatasetReader object
    bounds : list
        Output bounds (left, bottom, right, top) in target crs ("dst_crs").
    tilesize : int
        Output image size
    indexes : list of ints or a single int, optional, (defaults: None)
        If `indexes` is a list, the result is a 3D array, but is
        a 2D array if it is a band index number.
    nodata: int or float, optional (defaults: None)
    resampling_method : str, optional (default: "bilinear")
        Resampling algorithm.
    tile_edge_padding : int, optional (default: 2)
        Padding to apply to each edge of the tile when retrieving data
        to assist in reducing resampling artefacts along edges.
    dst_crs: CRS or str, optional
        Target coordinate reference system (default "epsg:3857").
    bounds_crs: CRS or str, optional
        Overwrite bounds coordinate reference system (default None, equal to dst_crs).
    minimum_tile_cover: float, optional (default: None)
        Minimum % overlap for which to raise an error with dataset not
        covering enought of the tile.
    warp_vrt_option: dict, optional (default: {})
        These will be passed to the rasterio.warp.WarpedVRT class.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if isinstance(indexes, int):
        indexes = [indexes]
    elif isinstance(indexes, tuple):
        indexes = list(indexes)

    if not bounds_crs:
        bounds_crs = dst_crs

    bounds = transform_bounds(bounds_crs, dst_crs, *bounds, densify_pts=21)

    vrt_params = dict(add_alpha=True,
                      crs=dst_crs,
                      resampling=Resampling[resampling_method])

    vrt_transform, vrt_width, vrt_height = get_vrt_transform(src_dst,
                                                             bounds,
                                                             dst_crs=dst_crs)

    out_window = windows.Window(col_off=0,
                                row_off=0,
                                width=vrt_width,
                                height=vrt_height)

    src_bounds = transform_bounds(src_dst.crs,
                                  dst_crs,
                                  *src_dst.bounds,
                                  densify_pts=21)
    x_overlap = max(
        0,
        min(src_bounds[2], bounds[2]) - max(src_bounds[0], bounds[0]))
    y_overlap = max(
        0,
        min(src_bounds[3], bounds[3]) - max(src_bounds[1], bounds[1]))
    cover_ratio = (x_overlap * y_overlap) / ((bounds[2] - bounds[0]) *
                                             (bounds[3] - bounds[1]))
    if minimum_tile_cover and cover_ratio < minimum_tile_cover:
        raise TileOutsideBounds(
            "Dataset covers less than {:.0f}% of tile".format(cover_ratio *
                                                              100))

    if tile_edge_padding > 0:
        vrt_transform = vrt_transform * Affine.translation(
            -tile_edge_padding, -tile_edge_padding)
        orig_vrt_height = vrt_height
        orig_vrt_width = vrt_width
        vrt_height = vrt_height + 2 * tile_edge_padding
        vrt_width = vrt_width + 2 * tile_edge_padding
        out_window = windows.Window(
            col_off=tile_edge_padding,
            row_off=tile_edge_padding,
            width=orig_vrt_width,
            height=orig_vrt_height,
        )

    vrt_params.update(
        dict(transform=vrt_transform, width=vrt_width, height=vrt_height))

    indexes = indexes if indexes is not None else src_dst.indexes
    out_shape = (len(indexes), tilesize, tilesize)

    nodata = nodata if nodata is not None else src_dst.nodata
    if nodata is not None:
        vrt_params.update(
            dict(nodata=nodata, add_alpha=False, src_nodata=nodata))

    if has_alpha_band(src_dst):
        vrt_params.update(dict(add_alpha=False))

    vrt_params.update(warp_vrt_option)
    with WarpedVRT(src_dst, **vrt_params) as vrt:
        data = vrt.read(
            out_shape=out_shape,
            indexes=indexes,
            window=out_window,
            resampling=Resampling[resampling_method],
        )
        mask = vrt.dataset_mask(out_shape=(tilesize, tilesize),
                                window=out_window)

        return data, mask
示例#22
0
def tile(
    sceneid: str,
    tile_x: int,
    tile_y: int,
    tile_z: int,
    bands: Union[Sequence[str], str] = None,
    tilesize: int = 256,
    **kwargs: Dict,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Create mercator tile from CBERS data.

    Attributes
    ----------
        sceneid : str
            CBERS sceneid.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple or list or str, optional
            Bands index for the RGB combination. If None uses default
            defined for the instrument
        tilesize : int, optional
            Output image size. Default is 256
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.reader.tile' function.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    if isinstance(bands, str):
        bands = (bands, )

    scene_params = cbers_parser(sceneid)

    if not bands:
        bands = scene_params["rgb"]

    for band in bands:
        if band not in scene_params["bands"]:
            raise InvalidBandName(
                "{} is not a valid band name for {} CBERS instrument".format(
                    band, scene_params["instrument"]))

    cbers_prefix = "{scheme}://{bucket}/{prefix}/{scene}".format(
        **scene_params)
    with rasterio.open("{}_BAND{}.tif".format(
            cbers_prefix, scene_params["reference_band"])) as src_dst:
        bounds = transform_bounds(src_dst.crs,
                                  constants.WGS84_CRS,
                                  *src_dst.bounds,
                                  densify_pts=21)

    if not tile_exists(bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    addresses = [f"{cbers_prefix}_BAND{band}.tif" for band in bands]
    return reader.multi_tile(addresses,
                             tile_x,
                             tile_y,
                             tile_z,
                             tilesize=tilesize,
                             nodata=0)
示例#23
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         bands=("4", "3", "2"),
         tilesize=256,
         pan=False,
         **kwargs):
    """
    Create mercator tile from Landsat-8 data.

    Attributes
    ----------
    sceneid : str
        Landsat sceneid. For scenes after May 2017,
        sceneid have to be LANDSAT_PRODUCT_ID.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ("4", "3", "2"))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    pan : boolean, optional (default: False)
        If True, apply pan-sharpening.
    kwargs: dict, optional
        These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in LANDSAT_BANDS:
            raise InvalidBandName(
                "{} is not a valid Landsat band name".format(band))

    scene_params = _landsat_parse_scene_id(sceneid)
    meta_data = _landsat_get_mtl(sceneid).get("L1_METADATA_FILE")
    landsat_address = "{}/{}".format(LANDSAT_BUCKET, scene_params["key"])

    wgs_bounds = toa_utils._get_bounds_from_metadata(
        meta_data["PRODUCT_METADATA"])

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    def _tiler(band):
        address = "{}_B{}.TIF".format(landsat_address, band)
        if band == "QA":
            nodata = 1
        else:
            nodata = 0

        return utils.tile_read(address,
                               bounds=tile_bounds,
                               tilesize=tilesize,
                               nodata=nodata,
                               **kwargs)

    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, bands)))
        data = np.concatenate(data)
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

        if pan:
            pan_address = "{}_B8.TIF".format(landsat_address)
            matrix_pan, mask = utils.tile_read(pan_address,
                                               tile_bounds,
                                               tilesize,
                                               nodata=0)
            data = utils.pansharpening_brovey(data, matrix_pan, 0.2,
                                              matrix_pan.dtype)

        sun_elev = meta_data["IMAGE_ATTRIBUTES"]["SUN_ELEVATION"]

        for bdx, band in enumerate(bands):
            if band in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:  # OLI
                multi_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_MULT_BAND_{}".format(band))

                add_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_ADD_BAND_{}".format(band))

                data[bdx] = 10000 * reflectance.reflectance(
                    data[bdx], multi_reflect, add_reflect, sun_elev)

            elif band in ["10", "11"]:  # TIRS
                multi_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_MULT_BAND_{}".format(band))

                add_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_ADD_BAND_{}".format(band))

                k1 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K1_CONSTANT_BAND_{}".format(band))

                k2 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K2_CONSTANT_BAND_{}".format(band))

                data[bdx] = brightness_temp.brightness_temp(
                    data[bdx], multi_rad, add_rad, k1, k2)

        return data, mask
示例#24
0
def tile(sceneid, tile_x, tile_y, tile_z, rgb=('04', '03', '02'),
         r_bds=(0, 16000), g_bds=(0, 16000), b_bds=(1, 16000), tilesize=256):
    """Create mercator tile from Sentinel-2 data and encodes it in base64.

    Attributes
    ----------

    sceneid : str
        Sentinel-2 sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    rgb : tuple, int, optional (default: ('04', '03', '02'))
        Bands index for the RGB combination.
    r_bds : tuple, int, optional (default: (0, 16000))
        First band (red) DN min and max values (DN * 10,000)
        used for the linear rescaling.
    g_bds : tuple, int, optional (default: (0, 16000))
        Second band (green) DN min and max values (DN * 10,000)
        used for the linear rescaling.
    b_bds : tuple, int, optional (default: (0, 16000))
        Third band (blue) DN min and max values (DN * 10,000)
        used for the linear rescaling.
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    out : numpy ndarray (type: uint8)
    """

    scene_params = utils.sentinel_parse_scene_id(sceneid)
    sentinel_address = '{}/{}'.format(SENTINEL_BUCKET, scene_params['key'])

    sentinel_preview = '{}/preview.jp2'.format(sentinel_address)
    with rasterio.open(sentinel_preview) as src:
        wgs_bounds = transform_bounds(
            *[src.crs, 'epsg:4326'] + list(src.bounds), densify_pts=21)

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds('Tile {}/{}/{} is outside image bounds'.format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    # define a list of bands Min and Max Values (form input)
    histo_cuts = dict(zip(rgb, [r_bds, g_bds, b_bds]))

    addresses = ['{}/B{}.jp2'.format(sentinel_address, band) for band in rgb]
    _tiler = partial(utils.tile_band_worker,
                     bounds=tile_bounds,
                     tilesize=tilesize)

    with futures.ThreadPoolExecutor(max_workers=3) as executor:
        out = np.stack(executor.map(_tiler, addresses))

        for bdx, band in enumerate(rgb):
            # Rescale Intensity to byte (1->255) with 0 being NoData
            out[bdx] = np.where(
                out[bdx] > 0,
                utils.linear_rescale(out[bdx],
                                     in_range=histo_cuts.get(band),
                                     out_range=[1, 255]), 0)

    return out.astype(np.uint8)
示例#25
0
def tile(sceneid, tile_x, tile_y, tile_z, rgb=(4, 3, 2), tilesize=256, pan=False):
    """Create mercator tile from Landsat-8 data.

    Attributes
    ----------

    sceneid : str
        Landsat sceneid. For scenes after May 2017,
        sceneid have to be LANDSAT_PRODUCT_ID.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    rgb : tuple, int, optional (default: (4, 3, 2))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    pan : boolean, optional (default: False)
        If True, apply pan-sharpening.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array
    """

    if not isinstance(rgb, tuple):
        rgb = tuple((rgb, ))

    scene_params = utils.landsat_parse_scene_id(sceneid)
    meta_data = utils.landsat_get_mtl(sceneid).get('L1_METADATA_FILE')
    landsat_address = '{}/{}'.format(LANDSAT_BUCKET, scene_params['key'])

    wgs_bounds = toa_utils._get_bounds_from_metadata(
        meta_data['PRODUCT_METADATA'])

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            'Tile {}/{}/{} is outside image bounds'.format(
                tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    ms_tile_size = int(tilesize / 2) if pan else tilesize
    addresses = ['{}_B{}.TIF'.format(landsat_address, band) for band in rgb]

    _tiler = partial(utils.tile_band_worker, bounds=tile_bounds, tilesize=ms_tile_size, nodata=0)
    with futures.ThreadPoolExecutor(max_workers=3) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        data = np.concatenate(data)
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

        if pan:
            pan_address = '{}_B8.TIF'.format(landsat_address)
            matrix_pan, mask = utils.tile_band_worker(pan_address, tile_bounds, tilesize, nodata=0)

            w, s, e, n = tile_bounds
            pan_transform = transform.from_bounds(w, s, e, n, tilesize, tilesize)
            vis_transform = pan_transform * Affine.scale(2.)
            data = pansharpen(data, vis_transform, matrix_pan, pan_transform,
                              np.int16, 'EPSG:3857', 'EPSG:3857', 0.2,
                              method='Brovey', src_nodata=0)

        sun_elev = meta_data['IMAGE_ATTRIBUTES']['SUN_ELEVATION']

        for bdx, band in enumerate(rgb):
            if int(band) > 9:  # TIRS
                multi_rad = meta_data['RADIOMETRIC_RESCALING'].get(
                    'RADIANCE_MULT_BAND_{}'.format(band))

                add_rad = meta_data['RADIOMETRIC_RESCALING'].get(
                    'RADIANCE_ADD_BAND_{}'.format(band))

                k1 = meta_data['TIRS_THERMAL_CONSTANTS'].get(
                    'K1_CONSTANT_BAND_{}'.format(band))

                k2 = meta_data['TIRS_THERMAL_CONSTANTS'].get(
                    'K2_CONSTANT_BAND_{}'.format(band))

                data[bdx] = brightness_temp.brightness_temp(
                    data[bdx], multi_rad, add_rad, k1, k2)

            else:
                multi_reflect = meta_data['RADIOMETRIC_RESCALING'].get(
                    'REFLECTANCE_MULT_BAND_{}'.format(band))

                add_reflect = meta_data['RADIOMETRIC_RESCALING'].get(
                    'REFLECTANCE_ADD_BAND_{}'.format(band))

                data[bdx] = 10000 * reflectance.reflectance(
                    data[bdx], multi_reflect, add_reflect, sun_elev)

        return data, mask
示例#26
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         bands=("04", "03", "02"),
         tilesize=256,
         **kwargs):
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
        sceneid : str
            Sentinel-2 sceneid.
        tile_x : int
            Mercator tile X index.
        tile_y : int
            Mercator tile Y index.
        tile_z : int
            Mercator tile ZOOM level.
        bands : tuple, str, optional (default: ('04', '03', '02'))
            Bands index for the RGB combination.
        tilesize : int, optional (default: 256)
            Output image size.
        kwargs: dict, optional
            These will be passed to the 'rio_tiler.utils._tile_read' function.

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    scene_params = _sentinel_parse_scene_id(sceneid)

    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in scene_params["valid_bands"]:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    preview_file = os.path.join(
        scene_params["aws_bucket"],
        scene_params["aws_prefix"],
        scene_params["preview_file"],
    )
    with rasterio.open(preview_file) as src:
        bounds = transform_bounds(src.crs,
                                  "epsg:4326",
                                  *src.bounds,
                                  densify_pts=21)

    if not utils.tile_exists(bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    path_prefix = os.path.join(scene_params["aws_bucket"],
                               scene_params["aws_prefix"])
    if scene_params["processingLevel"] == "L2A":
        bands = [_l2_prefixed_band(b) for b in bands]
    else:
        bands = ["B{}".format(b) for b in bands]

    def _read_tile(path):
        with rasterio.open(path) as src_dst:
            return utils.tile_read(src_dst,
                                   bounds=tile_bounds,
                                   tilesize=tilesize,
                                   nodata=0,
                                   **kwargs)

    addresses = ["{}/{}.jp2".format(path_prefix, band) for band in bands]
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_read_tile, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
示例#27
0
def tile(sceneid,
         tile_x,
         tile_y,
         tile_z,
         bands=("4", "3", "2"),
         tilesize=256,
         pan=False):
    """
    Create mercator tile from Landsat-8 data.

    Attributes
    ----------
    sceneid : str
        Landsat sceneid. For scenes after May 2017,
        sceneid have to be LANDSAT_PRODUCT_ID.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ("4", "3", "2"))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    pan : boolean, optional (default: False)
        If True, apply pan-sharpening.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in LANDSAT_BANDS:
            raise InvalidBandName(
                "{} is not a valid Landsat band name".format(band))

    scene_params = _landsat_parse_scene_id(sceneid)
    meta_data = _landsat_get_mtl(sceneid).get("L1_METADATA_FILE")
    landsat_address = "{}/{}".format(LANDSAT_BUCKET, scene_params["key"])

    wgs_bounds = toa_utils._get_bounds_from_metadata(
        meta_data["PRODUCT_METADATA"])

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds("Tile {}/{}/{} is outside image bounds".format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    ms_tile_size = int(tilesize / 2) if pan else tilesize
    addresses = ["{}_B{}.TIF".format(landsat_address, band) for band in bands]

    _tiler = partial(utils.tile_read,
                     bounds=tile_bounds,
                     tilesize=ms_tile_size,
                     nodata=0)
    with futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        data = np.concatenate(data)
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

        if pan:
            pan_address = "{}_B8.TIF".format(landsat_address)
            matrix_pan, mask = utils.tile_read(pan_address,
                                               tile_bounds,
                                               tilesize,
                                               nodata=0)

            w, s, e, n = tile_bounds
            pan_transform = transform.from_bounds(w, s, e, n, tilesize,
                                                  tilesize)
            vis_transform = pan_transform * Affine.scale(2.0)
            data = pansharpen(
                data,
                vis_transform,
                matrix_pan,
                pan_transform,
                np.int16,
                "EPSG:3857",
                "EPSG:3857",
                0.2,
                method="Brovey",
                src_nodata=0,
            )

        sun_elev = meta_data["IMAGE_ATTRIBUTES"]["SUN_ELEVATION"]

        for bdx, band in enumerate(bands):
            if int(band) > 9:  # TIRS
                multi_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_MULT_BAND_{}".format(band))

                add_rad = meta_data["RADIOMETRIC_RESCALING"].get(
                    "RADIANCE_ADD_BAND_{}".format(band))

                k1 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K1_CONSTANT_BAND_{}".format(band))

                k2 = meta_data["TIRS_THERMAL_CONSTANTS"].get(
                    "K2_CONSTANT_BAND_{}".format(band))

                data[bdx] = brightness_temp.brightness_temp(
                    data[bdx], multi_rad, add_rad, k1, k2)

            else:
                multi_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_MULT_BAND_{}".format(band))

                add_reflect = meta_data["RADIOMETRIC_RESCALING"].get(
                    "REFLECTANCE_ADD_BAND_{}".format(band))

                data[bdx] = 10000 * reflectance.reflectance(
                    data[bdx], multi_reflect, add_reflect, sun_elev)

        return data, mask