Пример #1
0
        def worker(path):

            raster = rasterio_open(path)
            w, s, e, n = transform_bounds(raster.crs, "EPSG:4326", *raster.bounds)
            transform, _, _ = calculate_default_transform(raster.crs, "EPSG:3857", raster.width, raster.height, w, s, e, n)
            tiles = [mercantile.Tile(x=x, y=y, z=z) for x, y, z in mercantile.tiles(w, s, e, n, args.zoom)]
            tiled = []

            for tile in tiles:

                try:
                    w, s, e, n = mercantile.xy_bounds(tile)

                    # inspired by rio-tiler, cf: https://github.com/mapbox/rio-tiler/pull/45
                    warp_vrt = WarpedVRT(
                        raster,
                        crs="epsg:3857",
                        resampling=Resampling.bilinear,
                        add_alpha=False,
                        transform=from_bounds(w, s, e, n, args.ts, args.ts),
                        width=math.ceil((e - w) / transform.a),
                        height=math.ceil((s - n) / transform.e),
                    )
                    data = warp_vrt.read(
                        out_shape=(len(raster.indexes), args.ts, args.ts), window=warp_vrt.window(w, s, e, n)
                    )
                    image = np.moveaxis(data, 0, 2)  # C,H,W -> H,W,C
                except:
                    sys.exit("Error: Unable to tile {} from raster {}.".format(str(tile), raster))

                tile_key = (str(tile.x), str(tile.y), str(tile.z))
                if not args.label and len(tiles_map[tile_key]) == 1 and is_border(image):
                    progress.update()
                    continue

                if len(tiles_map[tile_key]) > 1:
                    out = os.path.join(splits_path, str(tiles_map[tile_key].index(path)))
                else:
                    out = args.out

                x, y, z = map(int, tile)

                if not args.label:
                    ret = tile_image_to_file(out, mercantile.Tile(x=x, y=y, z=z), image)
                if args.label:
                    ret = tile_label_to_file(out, mercantile.Tile(x=x, y=y, z=z), palette, image)

                if not ret:
                    sys.exit("Error: Unable to write tile {} from raster {}.".format(str(tile), raster))

                if len(tiles_map[tile_key]) == 1:
                    progress.update()
                    tiled.append(mercantile.Tile(x=x, y=y, z=z))

            return tiled
Пример #2
0
    def _read_window(self, vrt: WarpedVRT, dst_window: Window) -> MaskedArray:
        """Read window of input raster."""
        dst_bounds: Bounds = bounds(dst_window, self.dst[self.default_format].transform)
        window = vrt.window(*dst_bounds)

        src_bounds = transform_bounds(
            self.dst[self.default_format].crs, self.src.crs, *dst_bounds
        )

        LOGGER.debug(
            f"Read {dst_window} for Tile {self.tile_id} - this corresponds to bounds {src_bounds} in source"
        )

        shape = (
            len(self.layer.input_bands),
            int(round(dst_window.height)),
            int(round(dst_window.width)),
        )

        try:

            return vrt.read(
                window=window,
                out_shape=shape,
                masked=True,
            )
        except rasterio.RasterioIOError as e:
            if "Access window out of range" in str(e) and (
                shape[1] == 1 or shape[2] == 1
            ):
                LOGGER.warning(
                    f"Access window out of range while reading {dst_window} for Tile {self.tile_id}. "
                    "This is most likely due to subpixel misalignment. "
                    "Returning empty array instead."
                )
                return np.ma.array(
                    data=np.zeros(shape=shape), mask=np.ones(shape=shape)
                )

            else:
                LOGGER.warning(
                    f"RasterioIO error while reading {dst_window} for Tile {self.tile_id}. "
                    "Will make attempt to retry."
                )
                raise
Пример #3
0
        def worker(path):

            if path in skip:
                return None


            raster = rasterio_open(path)
            w, s, e, n = transform_bounds(raster.crs, "EPSG:4326", *raster.bounds)
            tiles = [mercantile.Tile(x=x, y=y, z=z) for x, y, z in mercantile.tiles(w, s, e, n, args.zoom)]
            tiled = []

            for tile in tiles:

                if cover and tile not in cover:
                    continue

                w, s, e, n = mercantile.xy_bounds(tile)

                warp_vrt = WarpedVRT(
                    raster,
                    crs="epsg:3857",
                    resampling=Resampling.bilinear,
                    add_alpha=False,
                    transform=from_bounds(w, s, e, n, width, height),
                    width=width,
                    height=height,
                )

                data = warp_vrt.read(
                    out_shape=(len(args.bands), width, height), indexes=args.bands, window=warp_vrt.window(w, s, e, n)
                )
                if data.dtype == "uint16":  # GeoTiff could be 16 bits
                    data = np.uint8(data / 256)
                elif data.dtype == "uint32":  # or 32 bits
                    data = np.uint8(data / (256 * 256))

                image = np.moveaxis(data, 0, 2)  # C,H,W -> H,W,C

                tile_key = (str(tile.x), str(tile.y), str(tile.z))
                if (
                    not args.label
                    and len(tiles_map[tile_key]) == 1
                    and is_nodata(image, args.nodata, args.nodata_threshold, args.keep_borders)
                ):
                    progress.update()
                    continue

                if len(tiles_map[tile_key]) > 1:
                    out = os.path.join(splits_path, str(tiles_map[tile_key].index(path)))
                else:
                    out = args.out

                x, y, z = map(int, tile)

                if not args.label:
                    tile_image_to_file(out, mercantile.Tile(x=x, y=y, z=z), image, ext=ext)
                if args.label:
                    tile_label_to_file(out, mercantile.Tile(x=x, y=y, z=z), palette, args.nodata, image)

                if len(tiles_map[tile_key]) == 1:
                    tiled.append(mercantile.Tile(x=x, y=y, z=z))


                progress.update()

            raster.close()
            return tiled
Пример #4
0
        def worker(path):

            raster = rasterio_open(path)
            w, s, e, n = transform_bounds(raster.crs, "EPSG:4326",
                                          *raster.bounds)
            transform, _, _ = calculate_default_transform(
                raster.crs, "EPSG:3857", raster.width, raster.height, w, s, e,
                n)
            tiles = [
                mercantile.Tile(x=x, y=y, z=z)
                for x, y, z in mercantile.tiles(w, s, e, n, args.zoom)
            ]
            tiled = []

            for tile in tiles:

                if cover and tile not in cover:
                    continue

                w, s, e, n = mercantile.xy_bounds(tile)

                warp_vrt = WarpedVRT(
                    raster,
                    crs="epsg:3857",
                    resampling=Resampling.bilinear,
                    add_alpha=False,
                    transform=from_bounds(w, s, e, n, args.ts, args.ts),
                    width=args.ts,
                    height=args.ts,
                )
                data = warp_vrt.read(out_shape=(len(raster.indexes), args.ts,
                                                args.ts),
                                     window=warp_vrt.window(w, s, e, n))
                image = np.moveaxis(data, 0, 2)  # C,H,W -> H,W,C

                tile_key = (str(tile.x), str(tile.y), str(tile.z))
                if not args.label and len(
                        tiles_map[tile_key]) == 1 and is_nodata(
                            image, threshold=args.nodata_threshold):
                    progress.update()
                    continue

                if len(tiles_map[tile_key]) > 1:
                    out = os.path.join(splits_path,
                                       str(tiles_map[tile_key].index(path)))
                else:
                    out = args.out

                x, y, z = map(int, tile)

                if not args.label:
                    ret = tile_image_to_file(out, mercantile.Tile(x=x,
                                                                  y=y,
                                                                  z=z), image)
                if args.label:
                    ret = tile_label_to_file(out, mercantile.Tile(x=x,
                                                                  y=y,
                                                                  z=z),
                                             palette, image)

                assert ret, "Unable to write tile {} from raster {}.".format(
                    str(tile), raster)

                if len(tiles_map[tile_key]) == 1:
                    progress.update()
                    tiled.append(mercantile.Tile(x=x, y=y, z=z))

            return tiled
Пример #5
0
def main(args):

    if args.type == "label":
        try:
            config = load_config(args.config)
        except:
            sys.exit("Error: Unable to load DataSet config file")

        classes = config["classes"]["title"]
        colors = config["classes"]["colors"]
        assert len(classes) == len(colors), "classes and colors coincide"
        assert len(colors) == 2, "only binary models supported right now"

    try:
        raster = rasterio_open(args.raster)
        w, s, e, n = bounds = transform_bounds(raster.crs, "EPSG:4326",
                                               *raster.bounds)
        transform, _, _ = calculate_default_transform(raster.crs, "EPSG:3857",
                                                      raster.width,
                                                      raster.height, *bounds)
    except:
        sys.exit("Error: Unable to load raster or deal with it's projection")

    tiles = [
        mercantile.Tile(x=x, y=y, z=z)
        for x, y, z in mercantile.tiles(w, s, e, n, args.zoom)
    ]
    tiles_nodata = []

    for tile in tqdm(tiles, desc="Tiling", unit="tile", ascii=True):

        w, s, e, n = tile_bounds = mercantile.xy_bounds(tile)

        # Inspired by Rio-Tiler, cf: https://github.com/mapbox/rio-tiler/pull/45
        warp_vrt = WarpedVRT(
            raster,
            crs="EPSG:3857",
            resampling=Resampling.bilinear,
            add_alpha=False,
            transform=from_bounds(*tile_bounds, args.size, args.size),
            width=math.ceil((e - w) / transform.a),
            height=math.ceil((s - n) / transform.e),
        )
        data = warp_vrt.read(out_shape=(len(raster.indexes), args.size,
                                        args.size),
                             window=warp_vrt.window(w, s, e, n))

        # If no_data is set, remove all tiles with at least one whole border filled only with no_data (on all bands)
        if type(args.no_data) is not None and (
                np.all(data[:, 0, :] == args.no_data)
                or np.all(data[:, -1, :] == args.no_data)
                or np.all(data[:, :, 0] == args.no_data)
                or np.all(data[:, :, -1] == args.no_data)):
            tiles_nodata.append(tile)
            continue

        C, W, H = data.shape

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

        if args.type == "label":
            assert C == 1, "Error: Label raster input should be 1 band"

            ext = "png"
            img = Image.fromarray(np.squeeze(data, axis=0), mode="P")
            img.putpalette(make_palette(colors[0], colors[1]))
            img.save("{}.{}".format(path, ext), optimize=True)

        elif args.type == "image":
            assert C == 1 or C == 3, "Error: Image raster input should be either 1 or 3 bands"

            # GeoTiff could be 16 or 32bits
            if data.dtype == "uint16":
                data = np.uint8(data / 256)
            elif data.dtype == "uint32":
                data = np.uint8(data / (256 * 256))

            if C == 1:
                ext = "png"
                Image.fromarray(np.squeeze(data, axis=0),
                                mode="L").save("{}.{}".format(path, ext),
                                               optimize=True)
            elif C == 3:
                ext = "webp"
                Image.fromarray(np.moveaxis(data, 0, 2),
                                mode="RGB").save("{}.{}".format(path, ext),
                                                 optimize=True)

    if args.web_ui:
        template = "leaflet.html" if not args.web_ui_template else args.web_ui_template
        tiles = [tile for tile in tiles if tile not in tiles_nodata]
        web_ui(args.out, args.web_ui, tiles, tiles, ext, template)