def test_array_to_img_invalid_format(): """Should raise an error with invalid format """ arr = np.random.randint(0, 255, size=(1, 512, 512), dtype=np.uint8) img = utils.array_to_img(arr) with pytest.raises(InvalidFormat): utils.b64_encode_img(img, 'gif')
def ratio(scene, tile_z, tile_x, tile_y, tileformat): """Handle processing requests """ if tileformat == 'jpg': tileformat = 'jpeg' query_args = APP.current_request.query_params query_args = query_args if isinstance(query_args, dict) else {} ratio_value = query_args['ratio'] range_value = query_args.get('range', [-1, 1]) tilesize = query_args.get('tile', 256) tilesize = int(tilesize) if isinstance(tilesize, str) else tilesize tile, mask = expression(scene, tile_x, tile_y, tile_z, ratio_value, tilesize=tilesize) if len(tile.shape) == 2: tile = np.expand_dims(tile, axis=0) rtile = np.where( mask, linear_rescale(tile, in_range=range_value, out_range=[0, 255]), 0).astype(np.uint8) img = array_to_img(rtile, color_map=get_colormap(name='cfastie'), mask=mask) str_img = b64_encode_img(img, tileformat) return ('OK', f'image/{tileformat}', str_img)
def tile(scene, 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 {} bands = query_args.get('rgb', '4,3,2') bands = tuple(re.findall(r'\d+', bands)) histoCut = query_args.get('histo', ';'.join(['0,16000'] * len(bands))) histoCut = re.findall(r'\d+,\d+', histoCut) histoCut = list(map(lambda x: list(map(int, x.split(','))), histoCut)) if len(bands) != len(histoCut): raise LandsatTilerError('The number of bands doesn\'t match the number of histogramm values') tilesize = query_args.get('tile', 256) tilesize = int(tilesize) if isinstance(tilesize, str) else tilesize pan = True if query_args.get('pan') else False tile, mask = landsat8.tile(scene, tile_x, tile_y, tile_z, bands, pan=pan, tilesize=tilesize) rtile = np.zeros((len(bands), tilesize, tilesize), dtype=np.uint8) for bdx in range(len(bands)): rtile[bdx] = np.where(mask, linear_rescale(tile[bdx], in_range=histoCut[bdx], out_range=[0, 255]), 0) img = array_to_img(rtile, mask=mask) str_img = b64_encode_img(img, tileformat) return ('OK', f'image/{tileformat}', str_img)
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 area( scene, bbox, expression, expression_range=[-1, 1], bbox_crs="epsg:4326", out_crs="epsg:3857", ): """Area handler.""" max_img_size = 512 bands = tuple(set(re.findall(r"b(?P<bands>[0-9]{1,2})", expression))) scene_params = sentinel_parse_scene_id(scene) sentinel_address = f'{SENTINEL_BUCKET}/{scene_params["key"]}' scene_info = sentinel2_get_info(os.path.basename(SENTINEL_BUCKET), scene_params["key"], request_pays=True) addresses = [f"{sentinel_address}/B{band}.jp2" for band in bands] _worker = partial( get_area, bbox=bbox, max_img_size=max_img_size, bbox_crs=bbox_crs, out_crs=out_crs, ) with futures.ThreadPoolExecutor(max_workers=3) as executor: data = np.concatenate(list(executor.map(_worker, addresses))) if not np.any(data): raise Exception("No valid data in array") mask = np.all(data != 0, axis=0).astype(np.uint8) * 255 ctx = {} for bdx, b in enumerate(bands): ctx["b{}".format(b)] = data[bdx] ratio = np.nan_to_num(ne.evaluate(expression, local_dict=ctx)) ratio = np.where( mask, linear_rescale(ratio, in_range=expression_range, out_range=[0, 255]), 0).astype(np.uint8) img = array_to_img(ratio, mask, get_colormap(name="cfastie")) ndvi = b64_encode_img(img, "jpeg") date = (scene_params["acquisitionYear"] + "-" + scene_params["acquisitionMonth"] + "-" + scene_params["acquisitionDay"]) return { "ndvi": ndvi, "date": date, "sat": scene_info["sat"], "scene": scene, "cloud": scene_info["cloud_coverage"], }
def area( scene, bbox, expression, expression_range=[-1, 1], bbox_crs="epsg:4326", out_crs="epsg:3857", ): """Area handler.""" max_img_size = 512 bands = tuple(set(re.findall(r"b(?P<bands>[0-9]{1,2})", expression))) scene_params = landsat_parse_scene_id(scene) meta_data = landsat_get_mtl(scene).get("L1_METADATA_FILE") landsat_address = f'{LANDSAT_BUCKET}/{scene_params["key"]}' def worker(band): """Worker.""" address = f"{landsat_address}_B{band}.TIF" sun_elev = meta_data["IMAGE_ATTRIBUTES"]["SUN_ELEVATION"] multi_reflect = meta_data["RADIOMETRIC_RESCALING"][ f"REFLECTANCE_MULT_BAND_{band}" ] add_reflect = meta_data["RADIOMETRIC_RESCALING"][f"REFLECTANCE_ADD_BAND_{band}"] band = get_area( address, bbox, max_img_size=max_img_size, bbox_crs=bbox_crs, out_crs=out_crs ) return reflectance(band, multi_reflect, add_reflect, sun_elev, src_nodata=0) with futures.ThreadPoolExecutor(max_workers=3) as executor: data = np.concatenate(list(executor.map(worker, bands))) if not np.any(data): raise Exception("No valid data in array") mask = np.all(data != 0, axis=0).astype(np.uint8) * 255 ctx = {} for bdx, b in enumerate(bands): ctx["b{}".format(b)] = data[bdx] ratio = np.nan_to_num(ne.evaluate(expression, local_dict=ctx)) ratio = np.where( mask, linear_rescale(ratio, in_range=expression_range, out_range=[0, 255]), 0 ).astype(np.uint8) img = array_to_img(ratio, mask, get_colormap(name="cfastie")) ndvi = b64_encode_img(img, "jpeg") return { "ndvi": ndvi, "date": scene_params["date"], "scene": scene, "cloud": meta_data["IMAGE_ATTRIBUTES"]["CLOUD_COVER"], }
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)
def tile(scene, 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 {} bands = query_args.get("rgb", "04,03,02") bands = tuple(re.findall(r"[0-9A]{2}", bands)) histoCut = query_args.get("histo", "-".join(["0,16000"] * len(bands))) histoCut = re.findall(r"\d+,\d+", histoCut) histoCut = list(map(lambda x: list(map(int, x.split(","))), histoCut)) if len(bands) != len(histoCut): raise SentinelTilerError( "The number of bands doesn't match the number of histogramm values" ) tilesize = query_args.get("tile", 256) tilesize = int(tilesize) if isinstance(tilesize, str) else tilesize tile, mask = sentinel2.tile(scene, tile_x, tile_y, tile_z, bands, tilesize=tilesize) rtile = np.zeros((len(bands), tilesize, tilesize), dtype=np.uint8) for bdx in range(len(bands)): rtile[bdx] = np.where( mask, linear_rescale(tile[bdx], in_range=histoCut[bdx], out_range=[0, 255]), 0, ) img = array_to_img(rtile, mask=mask) str_img = b64_encode_img(img, tileformat) return ("OK", f"image/{tileformat}", str_img)
def create( scene, bands=None, expression=None, expression_range=[-1, 1], img_format="jpeg", ovrSize=512, ): """Handler.""" if img_format not in ["png", "jpeg"]: raise UserWarning(f"Invalid {img_format} extension") if not expression and not bands: raise Exception("Expression or Bands must be provided") if bands: nb_bands = len(bands) if nb_bands != 3: raise Exception("RGB combination only") if expression: bands = tuple(set(re.findall(r"b(?P<bands>[0-9]{1,2})", expression))) rgb = expression.split(",") nb_bands = len(rgb) scene_params = landsat_parse_scene_id(scene) meta_data = landsat_get_mtl(scene).get("L1_METADATA_FILE") landsat_address = f'{LANDSAT_BUCKET}/{scene_params["key"]}' _worker = partial(worker, landsat_address=landsat_address, meta=meta_data, ovr_size=ovrSize) with futures.ThreadPoolExecutor(max_workers=3) as executor: data = np.concatenate(list(executor.map(_worker, bands))) mask = np.all(data != 0, axis=0).astype(np.uint8) * 255 if expression: ctx = {} for bdx, b in enumerate(bands): ctx["b{}".format(b)] = data[bdx] data = np.array([ np.nan_to_num(ne.evaluate(bloc.strip(), local_dict=ctx)) for bloc in rgb ]) for band in range(data.shape[0]): imgRange = (expression_range if expression else np.percentile( data[band][mask > 0], (2, 98)).tolist()) data[band] = np.where( mask, linear_rescale(data[band], in_range=imgRange, out_range=[0, 255]), 0, ) data = data.squeeze() colormap = None if len(data.shape) >= 3 else get_colormap(name="cfastie") img = array_to_img(data, mask, colormap) return b64_encode_img(img, img_format)
def test_b64_encode_img_valid_webp(): """Should work as expected """ arr = np.random.randint(0, 255, size=(4, 512, 512), dtype=np.uint8) img = utils.array_to_img(arr) assert utils.b64_encode_img(img, 'webp')
def tile(scene, tile_z, tile_x, tile_y, tileformat): if tileformat == 'jpg': tileformat = 'jpeg' query_args = APP.current_request.query_params query_args = query_args if isinstance(query_args, dict) else {} bands = query_args.get('rgb', '4,3,2') label_id = -1 if bands == '12,12,12': label_id = 0 bands = '4,3,2' elif bands == '13,13,13': label_id = 1 bands = '4,3,2' elif bands == '14,14,14': label_id = 2 bands = '4,3,2' elif bands == '15,15,15': label_id = 3 bands = '4,3,2' bands = tuple(re.findall(r'\d+', bands)) histoCut = query_args.get('histo', ';'.join(['0,16000'] * len(bands))) histoCut = re.findall(r'\d+,\d+', histoCut) histoCut = list(map(lambda x: list(map(int, x.split(','))), histoCut)) if len(bands) != len(histoCut): raise LandsatTilerError( 'The number of bands doesn\'t match the number of histogramm values' ) tilesize = query_args.get('tile', 256) tilesize = int(tilesize) if isinstance(tilesize, str) else tilesize pan = True if query_args.get('pan') else False tile, mask = landsat8.tile(scene, tile_x, tile_y, tile_z, bands, pan=pan, tilesize=tilesize) rtile = np.zeros((len(bands), tilesize, tilesize), dtype=np.uint8) for bdx in range(len(bands)): rtile[bdx] = np.where( mask, linear_rescale(tile[bdx], in_range=histoCut[bdx], out_range=[0, 255]), 0) img = array_to_img(rtile, mask=mask) str_img = b64_encode_img(img, tileformat) if label_id != -1: data = { 'label_id': label_id, 'img': str_img, } r = requests.post(f"http://kursach.ngrok.io/getmask/", json=data) str_img = r.json()['mask'] img = Image.open(io.BytesIO(base64.decodebytes(eval(f"b'{str_img}'")))) img_np = np.asarray(img).T img = array_to_img(img_np, mask=mask) str_img = b64_encode_img(img, tileformat) return ('OK', f'image/{tileformat}', str_img)