Beispiel #1
0
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')
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #4
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)
Beispiel #5
0
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"],
    }
Beispiel #6
0
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"],
    }
Beispiel #7
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)
Beispiel #8
0
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)
Beispiel #9
0
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)
Beispiel #10
0
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')
Beispiel #11
0
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)