예제 #1
0
def get_elevation_tiles(elevation, url, x, y, z, tilesize, nodata, resampling, padding):
    tile = np.full((tilesize * 3, tilesize * 3), nodata, dtype=elevation.dtype)

    try:
        left, _ = main.tile(url, x - 1, y, z, indexes=1, tilesize=tilesize, nodata=nodata,
                            resampling_method=resampling, tile_edge_padding=padding)
        tile[tilesize:tilesize*2,0:tilesize] = left
    except TileOutsideBounds:
        pass

    try:
        right, _ = main.tile(url, x + 1, y, z, indexes=1, tilesize=tilesize, nodata=nodata,
                             resampling_method=resampling, tile_edge_padding=padding)
        tile[tilesize:tilesize*2,tilesize*2:tilesize*3] = right
    except TileOutsideBounds:
        pass

    try:
        bottom, _ = main.tile(url, x, y + 1, z, indexes=1, tilesize=tilesize, nodata=nodata,
                              resampling_method=resampling, tile_edge_padding=padding)
        tile[tilesize*2:tilesize*3,tilesize:tilesize*2] = bottom
    except TileOutsideBounds:
        pass

    try:
        top, _ = main.tile(url, x, y - 1, z, indexes=1, tilesize=tilesize, nodata=nodata,
                           resampling_method=resampling, tile_edge_padding=padding)
        tile[0:tilesize,tilesize:tilesize*2] = top
    except TileOutsideBounds:
        pass

    tile[tilesize:tilesize*2,tilesize:tilesize*2] = elevation

    return tile
예제 #2
0
def test_tile_invalid_bounds():
    """Should raise an error with invalid tile."""
    tile_z = 19
    tile_x = 554
    tile_y = 200458

    with pytest.raises(TileOutsideBounds):
        main.tile(ADDRESS, tile_x, tile_y, tile_z)
예제 #3
0
def tile(tile_z, tile_x, tile_y, tileformat):
    """Handle tile requests."""
    if tileformat == 'jpg':
        tileformat = 'jpeg'

    query_args = APP.current_request.query_params
    query_args = query_args if isinstance(query_args, dict) else {}

    address = query_args['url']

    indexes = query_args.get('indexes')
    if indexes:
        indexes = tuple(int(s) for s in re.findall(r'\d+', indexes))

    tilesize = query_args.get('tile', 512)
    tilesize = int(tilesize) if isinstance(tilesize, str) else tilesize

    nodata = query_args.get('nodata')
    if nodata is not None:
        nodata = int(nodata)

    tile, mask = main.tile(address,
                           tile_x,
                           tile_y,
                           tile_z,
                           indexes=indexes,
                           tilesize=tilesize,
                           nodata=nodata)

    img = array_to_img(tile, mask=mask)
    str_img = b64_encode_img(img, tileformat)
    return ('OK', f'image/{tileformat}', str_img)
예제 #4
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('path', type=str)
    parser.add_argument('out', type=str)
    parser.add_argument('--zoom', type=int, required=True)
    parser.add_argument('--ext', type=str, default='webp')
    args = parser.parse_args()

    os.makedirs(args.out, exist_ok=True)
    os.makedirs(os.path.join(args.out, str(args.zoom)), exist_ok=True)

    meta = tiler.bounds(args.path)
    bounds = meta['bounds']

    tiles = list(mercantile.tiles(*bounds + [[args.zoom]]))

    for x, y, z in tqdm(tiles, desc='Tiling', unit='tile', ascii=True):
        os.makedirs(os.path.join(args.out, str(z), str(x)), exist_ok=True)

        data, _ = tiler.tile(args.path, x, y, z)

        img = reshape_as_image(data)
        img = Image.fromarray(img, mode='RGB')
        img.save(os.path.join(args.out, str(z), str(x),
                              str(y) + '.' + args.ext),
                 optimize=True)
예제 #5
0
def gdal(
    input,
    tile,
    ext="png",
    bidx=(1, 2, 3),
    colormap=None,
    scale=None,
    save=None,
):
    """Handle tile requests."""
    tile_z, tile_x, tile_y = list(map(int, tile.split('-')))
    tile, mask = main.tile(
        input, tile_x, tile_y, tile_z, indexes=bidx, tilesize=512
    )

    if scale:
        nbands = tile.shape[0]
        for bdx in range(nbands):
            tile[bdx] = numpy.where(
                mask,
                utils.linear_rescale(tile[bdx], in_range=scale[bdx], out_range=[0, 255]),
                0,
            )
        tile = tile.astype(numpy.uint8)

    if colormap:
        colormap = numpy.array(list(chunks(utils.get_colormap(name=colormap), 3)))

    buffer = array_to_img_rasterio(tile, mask, img_format=ext, color_map=colormap)
    if save:
        with open(f"{tile_x}-{tile_y}-{tile_z}_gdal.{ext}", "wb") as f:
            f.write(buffer)
예제 #6
0
def pil(
    input,
    tile,
    ext="png",
    bidx=(1, 2, 3),
    colormap=None,
    scale=None,
    save=None,
):
    """Handle tile requests."""
    tile_z, tile_x, tile_y = list(map(int, tile.split('-')))
    tile, mask = main.tile(
        input, tile_x, tile_y, tile_z, indexes=bidx, tilesize=512
    )

    if scale:
        nbands = tile.shape[0]
        for bdx in range(nbands):
            tile[bdx] = numpy.where(
                mask,
                utils.linear_rescale(tile[bdx], in_range=scale[bdx], out_range=[0, 255]),
                0,
            )
        tile = tile.astype(numpy.uint8)

    if colormap:
        colormap = utils.get_colormap(name=colormap)

    img = utils.array_to_img(tile, mask=mask, color_map=colormap)
    img_format = "JPEG2000" if ext == "jp2" else ext
    buffer = img_to_buffer(img, img_format)
    if save:
        with open(f"{tile_x}-{tile_y}-{tile_z}_pil.{ext}", "wb") as f:
            f.write(buffer)
예제 #7
0
def tiler(
    z: int,
    x: int,
    y: int,
    tilesize: int = 128,
    feature_type: str = "polygon"
) -> Tuple:
    """Handle tile requests."""
    if isinstance(tilesize, str):
        tilesize = int(tilesize)

    address = f"https://elevation-tiles-prod.s3.amazonaws.com/geotiff/{z}/{x}/{y}.tif"
    tile, mask = main.tile(address, x, y, z, tilesize=tilesize)

    token = os.environ["MAPBOX_ACCESS_TOKEN"]
    address = f"https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.jpg?access_token={token}"
    imgdata = urlopen(address).read()
    with MemoryFile(imgdata) as memfile:
        with memfile.open() as dataset:
            rgb_tile = dataset.read(out_shape=(3, tilesize, tilesize))

    tile = numpy.concatenate([tile, rgb_tile], axis=0)
    return (
        "OK",
        "application/x-protobuf",
        mvtEncoder(
            tile,
            mask,
            ["elevation", "R", "G", "B"],
            "satellite-3d",
            feature_type=feature_type,
        ),
    )
예제 #8
0
def save_tile_image(tif_url, xyz, tile_size, folder='', prefix=''):
    x, y, z = xyz
    tile_image, mask_image = rt_main.tile(tif_url, x, y, z, tilesize=tile_size)
    tile_image_filename = ('%s/%s_%s_%s_%s.png' % (folder, prefix, x, y, z))
    imsave(tile_image_filename,
           np.moveaxis(tile_image, 0, 2),
           check_contrast=False)
    return (tile_image_filename)
예제 #9
0
def test_tile_valid_default():
    """Should return a 3 bands array and a full valid mask."""
    tile_z = 21
    tile_x = 438217
    tile_y = 801835

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert mask.all()
예제 #10
0
def test_tile_valid_bands():
    """Should return One band array."""
    tile_z = 21
    tile_x = 438217
    tile_y = 801835
    bands = 1

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z, indexes=bands)
    assert data.shape == (1, 256, 256)
예제 #11
0
def test_tile_valid_wrong_nodata():
    """"Should return a full valid mask."""
    tile_z = 21
    tile_x = 438217
    tile_y = 801835

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z, nodata=1000)
    assert data.shape == (3, 256, 256)
    assert mask.all()
예제 #12
0
def tile(tile_z, tile_x, tile_y, tileformat):
    """Handle tile requests."""
    if tileformat == 'jpg':
        tileformat = 'jpeg'

    query_args = APP.current_request.query_params
    query_args = query_args if isinstance(query_args, dict) else {}

    address = query_args['url']

    ## Read Stac File
    with urllib.request.urlopen(address) as url:
        data = json.loads(url.read().decode())

    asset_key = query_args.get('asset_key', 'raster')

    asset_data = data['assets'][asset_key]

    raster_address = asset_data['href']

    indexes = query_args.get('indexes')
    if indexes:
        indexes = tuple(int(s) for s in re.findall(r'\d+', indexes))

    tilesize = query_args.get('tile', 512)
    tilesize = int(tilesize) if isinstance(tilesize, str) else tilesize

    nodata = query_args.get('nodata')
    if nodata is not None:
        nodata = int(nodata)

    tile, mask = main.tile(raster_address,
                           tile_x,
                           tile_y,
                           tile_z,
                           indexes=indexes,
                           tilesize=tilesize,
                           nodata=nodata)

    tile_mask = tile >= asset_data['binary_threshold']

    if tilesize == 512:
        asset_data['pixel_count'] = np.sum(tile_mask[0]) / 2
    else:
        asset_data['pixel_count'] = np.sum(tile_mask[0])

    geom_list = []
    # Extract feature shapes and values from the array.
    for geom, val in features.shapes(tile_mask[0].astype(np.uint8), mask=mask):

        geom_list.append(geom)

    asset_data['object_count'] = len(geom_list)
    asset_data['object_list'] = geom_list

    return ('OK', 'application/json', json.dumps(asset_data))
예제 #13
0
def test_tile_valid_default_boundless():
    """Should return a partial valid mask because of boundless read."""
    # boundless tile
    tile_z = 19
    tile_x = 109554
    tile_y = 200458

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert not mask.all()
예제 #14
0
def test_tile_valid_internal_mask():
    """"Should return partial valid mask."""
    # non-boundless tile covering the masked part
    tile_z = 22
    tile_x = 876431
    tile_y = 1603670

    data, mask = main.tile(ADDRESS_MASK, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert not mask.all()

    # boundless tile covering the masked part
    tile_z = 22
    tile_x = 876431
    tile_y = 1603668
    data, mask = main.tile(ADDRESS_MASK, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert not mask.all()
    assert not mask[0].any()
예제 #15
0
def test_tile_valid_internal_nodata():
    """Should return a 3 bands array and a partial valid mask."""
    # non-boundless tile covering the nodata part
    tile_z = 22
    tile_x = 876431
    tile_y = 1603670

    data, mask = main.tile(ADDRESS_NODATA, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert not mask.all()
예제 #16
0
def test_tile_valid_external_nodata():
    """Should work as expected"""
    tile_z = 22
    tile_x = 876431
    tile_y = 1603669

    data, mask = main.tile(ADDRESS_NODATA, tile_x, tile_y, tile_z, nodata=0)
    assert data.shape == (3, 256, 256)
    assert not mask.all()
    assert (mask[:, 0:3] == 0).all()
예제 #17
0
def tile(
    z: int,
    x: int,
    y: int,
    scale: int = 1,
    ext: str = None,
    url: str = None,
    indexes: Union[str, Tuple[int]] = None,
    expr: str = None,
    nodata: Union[str, int, float] = None,
    rescale: str = None,
    color_formula: str = None,
    color_map: str = None,
) -> Tuple[str, str, BinaryIO]:
    """Handle tile requests."""
    driver = "jpeg" if ext == "jpg" else ext

    if indexes and expr:
        raise TilerError("Cannot pass indexes and expression")

    if not url:
        raise TilerError("Missing 'url' parameter")

    if isinstance(indexes, str):
        indexes = tuple(int(s) for s in re.findall(r"\d+", indexes))

    if nodata is not None:
        nodata = numpy.nan if nodata == "nan" else float(nodata)

    tilesize = scale * 256

    if expr is not None:
        tile, mask = expression(
            url, x, y, z, expr=expr, tilesize=tilesize, nodata=nodata
        )
    else:
        tile, mask = main.tile(
            url, x, y, z, indexes=indexes, tilesize=tilesize, nodata=nodata
        )

    rtile, rmask = _postprocess(
        tile, mask, rescale=rescale, color_formula=color_formula
    )

    if color_map:
        color_map = get_colormap(color_map, format="gdal")

    options = img_profiles.get(driver, {})
    return (
        "OK",
        f"image/{ext}",
        array_to_image(rtile, rmask, img_format=driver, color_map=color_map, **options),
    )
예제 #18
0
def test_tile_valid_resampling():
    """Should return an array and a mask."""
    tile_z = 21
    tile_x = 438217
    tile_y = 801835
    data, mask = main.tile(ADDRESS,
                           tile_x,
                           tile_y,
                           tile_z,
                           resampling_method="nearest")
    assert data.shape == (3, 256, 256)
    assert mask.all()
예제 #19
0
def test_tile_valid_default():
    """
    Should work as expected
    """

    tile_z = 19
    tile_x = 109554
    tile_y = 200458

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert mask.all()
예제 #20
0
def test_tile_valid_internal_alpha():
    """
    Should work as expected
    """

    tile_z = 19
    tile_x = 109554
    tile_y = 200458

    data, mask = main.tile(ADDRESS_ALPHA, tile_x, tile_y, tile_z, rgb=(1, 2, 3))
    assert data.shape == (3, 256, 256)
    assert not mask.all()
예제 #21
0
def test_tile_valid_internal_nodata():
    """
    Should work as expected
    """

    tile_z = 19
    tile_x = 109554
    tile_y = 200458

    data, mask = main.tile(ADDRESS_NODATA, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert not mask.all()
예제 #22
0
def test_tile_valid_bands():
    """
    Should work as expected
    """

    tile_z = 19
    tile_x = 109554
    tile_y = 200458
    bands = (1)

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z, indexes=bands)
    assert data.shape == (1, 256, 256)
예제 #23
0
def test_tile_valid_default_boundless():
    """Should work as expected.

    Mask should not be all valid because it's boundless read.
    """
    tile_z = 19
    tile_x = 109554
    tile_y = 200458

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert not mask.all()
예제 #24
0
def test_tile_valid_default():
    """
    Should work as expected
    """

    tile_z = 21
    tile_x = 438217
    tile_y = 801835

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z)
    assert data.shape == (3, 256, 256)
    assert mask.all()
예제 #25
0
def test_tile_valid_alpha():
    """
    Should work as expected
    """

    tile_z = 19
    tile_x = 109554
    tile_y = 200458

    data, mask = main.tile(ADDRESS, tile_x, tile_y, tile_z, rgb=(1, 2, 3), alpha=3)
    assert data.shape == (3, 256, 256)
    assert mask.shape == (256, 256)
def save_tile_img(tif_url, xyz, tile_size, save_path='', prefix='', display=False):
    x, y, z = xyz
    img_save_path = f'{save_path}/{prefix}{z}_{x}_{y}.png'
    if os.path.exists(img_save_path):
        return
    
    tile, mask = rt_main.tile(tif_url, x, y, z, tilesize=tile_size)

    if display: 
        plt.imshow(np.moveaxis(tile, 0, 2))
        plt.show()

    skimage.io.imsave(img_save_path, np.moveaxis(tile, 0, 2), check_contrast=False) 
def create_super_tile_image(tile_object, address, zoom_level=2, indexes=None, tile_size=256):

    """Generate the Tile List for The Tasking List

    Parameters
    ----------
    tile_object: mercantile tile object
    address: COG location
    zoom_level : int Zoom Level for Tiles
        One or more zoom levels.
    indexes: List of indexes for address.  This is incase it is more than 3-bands
    tile_size: int tile_size for query.  Standard is 256, 256



    Returns
    ------
    super_restile: returns numpy array of size (len(indexes,(2**zoom_level)*tile_size,(2**zoom_level)*tile_size)
    """

    if indexes is None:
        indexes = [1, 2, 3]
    
    tile_object_list, tile_position_list = create_super_tile_list(tile_object, zoom_level=2)
    
    super_restile = np.zeros(
        (len(indexes), (2 ** zoom_level) * tile_size, (2 ** zoom_level) * tile_size),
        dtype=float
    )

    for tile_coords, (tilePlace_x, tilePlace_y) in zip(tile_object_list, tile_position_list):

        tile_place_calc = [
            tilePlace_x*tile_size,
            (tilePlace_x+1)*tile_size,
            tilePlace_y*tile_size,
            (tilePlace_y+1)*tile_size
        ]

        # print
        logging.debug(tile_place_calc)

        tmp_tile, mask = main.tile(address,
                                   tile_coords.x,
                                   tile_coords.y,
                                   tile_coords.z
                                   )

        super_restile[:, tile_place_calc[0]:tile_place_calc[1], tile_place_calc[2]:tile_place_calc[3]] = tmp_tile
        
    return super_restile
예제 #28
0
def test_tile_valid_internal_alpha():
    """Should return a 3 bands array and a partial valid mask."""
    # non-boundless tile covering the alpha masked part
    tile_z = 22
    tile_x = 876432
    tile_y = 1603670

    data, mask = main.tile(ADDRESS_ALPHA,
                           tile_x,
                           tile_y,
                           tile_z,
                           indexes=(1, 2, 3))
    assert data.shape == (3, 256, 256)
    assert not mask.all()
예제 #29
0
def create_tile(src, x, y, z, style, bands=None):
    """Create the tile for x,y,z

    Parameters
    ----------
    src : string
        The connection to the source data.
        Accepted protocols are s3, https and local files.
    x : int
        Mercator tile X index.
    y : int
        Mercator tile Y index.
    z : int
        Mecator tile zoom level.
    style : Style object
        Used to style the tile.
    bands : int or list of type 'int'
        When querying a source with multiple bands, selects the band to use.

    Returns
    -------
    bytes
        The png image as bytes.
    """

    try:
        # returns the tile at the point as well as a mask to for the undefined values
        indexes = bands
        resample = style.get_resampling_method()
        tile, alpha = main.tile(src,
                                x,
                                y,
                                z,
                                indexes=indexes,
                                resampling_method=resample)
        alpha = style.style_tile_mask(tile, alpha)
        png_tile = style.normalise_tile(tile)

    except Exception as exception:
        print('tile generation exception')
        print(exception)
        traceback.print_exc(file=sys.stdout)
        # Return empty tile
        png_tile = np.full(256, 3)

    colour_map = style.get_colour_map_array()

    return array_to_image(png_tile, color_map=colour_map, mask=alpha)
예제 #30
0
def tile(tile_z, tile_x, tile_y, tileformat):
    """Handle tile requests."""
    if tileformat == 'jpg':
        tileformat = 'jpeg'

    query_args = APP.current_request.query_params
    query_args = query_args if isinstance(query_args, dict) else {}

    address = query_args['url']

    ## Read Stac File
    with urllib.request.urlopen(address) as url:
        data = json.loads(url.read().decode())

    asset_key = query_args.get('asset_key', 'raster')

    raster_address = data['assets'][asset_key]['href']

    indexes = query_args.get('indexes')
    if indexes:
        indexes = tuple(int(s) for s in re.findall(r'\d+', indexes))

    tilesize = query_args.get('tile', 512)
    tilesize = int(tilesize) if isinstance(tilesize, str) else tilesize

    nodata = query_args.get('nodata')
    if nodata is not None:
        nodata = int(nodata)

    raster_address = data['assets'][asset_key]['href']

    tile, mask = main.tile(raster_address,
                           tile_x,
                           tile_y,
                           tile_z,
                           indexes=indexes,
                           tilesize=tilesize,
                           nodata=nodata)

    linearStretch = query_args.get('linearStretch')
    if linearStretch is not None:
        if util.strtobool(linearStretch):
            tile = linear_rescale(tile, in_range=(np.min(tile), np.max(tile)))

    img = array_to_img(tile, mask=mask)
    str_img = b64_encode_img(img, tileformat)

    return ('OK', f'image/{tileformat}', str_img)