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
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)
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)
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)
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)
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)
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, ), )
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)
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()
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)
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()
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))
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()
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()
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()
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()
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), )
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()
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()
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()
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()
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)
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()
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()
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
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()
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)
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)