Example #1
0
def visualise_results(results, tile_size, out_path):
    """Given the predictions, false positves and the labels of our model visualise them on the satellite
    image they belong to."""

    # The tiles of the predictions, false positives and labels are all in "results".
    # We need ways to get extract them individually to pass them to overlay_bitmap.
    get_predictions = lambda (tiles, pos, path): (tiles[0], pos, path)
    get_labels = lambda (tiles, pos, path): (tiles[1], pos, path)
    get_false_positives =  lambda (tiles, pos, path): (tiles[2], pos, path)

    get_path = lambda (tiles,pos , path): path
    sorted_by_path = sorted(results, key=get_path)
    for path, result_tiles in itertools.groupby(sorted_by_path, get_path):
        raster_dataset = rasterio.open(path)
        dataset_shape = (raster_dataset.shape[0], raster_dataset.shape[1])

        result_tiles = list(result_tiles)
        predictions = map(get_predictions, result_tiles)
        labels = map(get_labels, result_tiles)
        false_positives = map(get_false_positives, result_tiles)

        satellite_img_name = get_file_name(path)
        out_file_name = "{}_results.tif".format(satellite_img_name)
        out = os.path.join(out_path, out_file_name)
        # We first write the labels in blue, then predictions in green and then false positives in red.
        # This way the true positives will be green, false positives red, false negatives blue and everything
        # else in the image will be true negatives.
        for tiles, color in [(labels, 'blue'), (predictions, 'green'), (false_positives, 'red')]:
            bitmap = image_from_tiles(tiles, tile_size, dataset_shape)
            raster_dataset = overlay_bitmap(bitmap, raster_dataset, out, color=color)
Example #2
0
def reproject_dataset(geotiff_path):
    """Project a GeoTIFF to the WGS84 coordinate reference system.
    See https://mapbox.github.io/rasterio/topics/reproject.html"""

    # We want to project the GeoTIFF coordinate reference system (crs)
    # to WGS84 (e.g. into the familiar Lat/Lon pairs). WGS84 is analogous
    # to EPSG:4326
    dst_crs = 'EPSG:4326'

    with rasterio.open(geotiff_path) as src:
        transform, width, height = rasterio.warp.calculate_default_transform(
            src.crs, dst_crs, src.width, src.height, *src.bounds)
        kwargs = src.meta.copy()
        kwargs.update({
            'crs': dst_crs,
            'transform': transform,
            'width': width,
            'height': height
        })

        satellite_img_name = get_file_name(geotiff_path)
        out_file_name = "{}_wgs84.tif".format(satellite_img_name)
        out_path = os.path.join(WGS84_DIR, out_file_name)
        with rasterio.open(out_path, 'w', **kwargs) as dst:
            for i in range(1, src.count + 1):
                rasterio.warp.reproject(
                    source=rasterio.band(src, i),
                    destination=rasterio.band(dst, i),
                    src_transform=src.transform,
                    src_crs=src.crs,
                    dst_transform=transform,
                    dst_crs=dst_crs,
                    resampling=rasterio.warp.Resampling.nearest)

        return rasterio.open(out_path), out_path
Example #3
0
def reproject_dataset(geotiff_path):
    """Project a GeoTIFF to the WGS84 coordinate reference system.
    See https://mapbox.github.io/rasterio/topics/reproject.html"""

    # We want to project the GeoTIFF coordinate reference system (crs)
    # to WGS84 (e.g. into the familiar Lat/Lon pairs). WGS84 is analogous
    # to EPSG:4326
    dst_crs = 'EPSG:4326'

    with rasterio.open(geotiff_path) as src:
        transform, width, height = rasterio.warp.calculate_default_transform(
            src.crs, dst_crs, src.width, src.height, *src.bounds)
        kwargs = src.meta.copy()
        kwargs.update({
            'crs': dst_crs,
            'transform': transform,
            'width': width,
            'height': height
        })

        satellite_img_name = get_file_name(geotiff_path)
        out_file_name = "{}_wgs84.tif".format(satellite_img_name)
        out_path = os.path.join(WGS84_DIR, out_file_name)
        with rasterio.open(out_path, 'w', **kwargs) as dst:
            for i in range(1, src.count + 1):
                rasterio.warp.reproject(
                    source=rasterio.band(src, i),
                    destination=rasterio.band(dst, i),
                    src_transform=src.transform,
                    src_crs=src.crs,
                    dst_transform=transform,
                    dst_crs=dst_crs,
                    resampling=rasterio.warp.Resampling.nearest)

        return rasterio.open(out_path), out_path
Example #4
0
def create_patched_features_and_labels(geotiff_path,
                                       geotiff_bitmap_path,
                                       patch_size,
                                       dist,
                                       only_cache=False):
    """ Create the features and labels for a given satellite image and its shapefiles. """

    # Try to load patch from cache.
    satellite_img_name = get_file_name(geotiff_path)
    cache_file_name = "{}_{}.pickle".format(satellite_img_name, patch_size)
    cache_path = os.path.join(PATCHES_DIR, cache_file_name)
    try:
        print('Load patches from {}.'.format(cache_path))
        with open(cache_path, 'rb') as f:
            patches = pickle.load(f)

        return patches["features"], patches["labels"]
    except IOError as e:
        if only_cache:
            raise
        print("Cache not available. Compute patches.")

    # The provided satellite images have a different coordinate reference system as
    # the familiar WGS84 which uses Latitude and Longitude. SO we need to reproject
    # the satellite image to the WGS84 coordinate reference system
    #print('geotiff_path: ',geotiff_path)
    dataset, wgs84_path = reproject_dataset(geotiff_path)
    bands = np.dstack(dataset.read())

    #print('bands,dataset,wgs84_path : ',bands,dataset,wgs84_path)

    # For the given satellite image, create a bitmap which has 1 at every pixel corresponding
    # to building in the satellite image. In order to do this we use building polygons from OSM.
    #The building polygons are stored in forms of shapefiles and are given by "shapefiles_paths".

    building_bitmap = create_bitmap(geotiff_path, geotiff_bitmap_path, dataset)
    #patched_bands = create_patches(bands, patch_size, wgs84_path)
    #patched_bitmap = create_patches(building_bitmap, patch_size, wgs84_path)
    #patched_bitmap = create_patches(building_bitmap, patch_size, geotiff_bitmap_path)

    patched_bands, patched_bitmap = create_patches(bands, building_bitmap,
                                                   patch_size, wgs84_path,
                                                   geotiff_bitmap_path, dist)
    # Due to the projection, the satellite image in the GeoTIFF is not a perfect rectangle and the
    # remaining space on the edges is blacked out. When we overlay the GeoTIFF with the
    # shapefile it also overlays features for the blacked out parts which means that if we don't
    # remove these patches the classifier will be fed with non-empty labels for empty features.

    #patched_bands, patched_bitmap = remove_edge_patches(patched_bands,
    #                                             patched_bitmap, patch_size, dataset.shape)

    save_patches(cache_path, patched_bands, patched_bitmap)

    return patched_bands, patched_bitmap
Example #5
0
def create_bitmap(raster_dataset, shapefile_paths, satellite_path):
    """Create the bitmap for a given satellite image."""

    satellite_img_name = get_file_name(satellite_path)
    cache_file_name = "{}_water.tif".format(satellite_img_name)
    cache_path = os.path.join(WATER_BITMAPS_DIR, cache_file_name)
    try:
        # Try loading the water bitmap from cache.
        print("Load water bitmap from {}".format(cache_path))
        bitmap = load_bitmap(cache_path)
        bitmap[bitmap == 255] = 1
        return bitmap
    except IOError as e:
        print("No cache file found.")

    water_features = np.empty((0, ))

    print("Create bitmap for water features.")
    for shapefile_path in shapefile_paths:
        try:
            print("Load shapefile {}.".format(shapefile_path))
            with fiona.open(shapefile_path) as shapefile:
                # Each feature in the shapefile also contains meta information such as
                # wether the features is a lake or a river. We only care about the geometry
                # of the feature i.e. where it is located and what shape it has.
                geometries = [feature['geometry'] for feature in shapefile]

                water_features = np.concatenate(
                    (water_features, geometries), axis=0)
        except IOError as e:
            print("No shapefile found.")
            sys.exit(1)

    # Now that we have the vector data of all water features in our satellite image
    # we "burn it" into a new raster so that we get a B/W image with water features
    # in white and the rest in black. We choose the value 255 so that there is a stark
    # contrast between water and non-water pixels. This is only for visualisation
    # purposes. For the classifier we use 0s and 1s.
    bitmap_image = rasterio.features.rasterize(
        ((g, 255) for g in water_features),
        out_shape=raster_dataset.shape,
        transform=raster_dataset.transform)

    save_bitmap(cache_path, bitmap_image, raster_dataset)

    bitmap_image[bitmap_image == 255] = 1
    return bitmap_image
Example #6
0
def create_tiled_features_and_labels(geotiff_path,
                                     shapefile_paths,
                                     tile_size,
                                     only_cache=False):
    """Create the features and labels for a given satellite image and its shapefiles."""

    # Try to load tiles from cache.
    satellite_img_name = get_file_name(geotiff_path)
    cache_file_name = "{}_{}.pickle".format(satellite_img_name, tile_size)
    cache_path = os.path.join(TILES_DIR, cache_file_name)
    try:
        print("Load tiles from {}.".format(cache_path))
        with open(cache_path) as f:
            tiles = pickle.load(f)

        return tiles["features"], tiles["labels"]
    except IOError as e:
        if only_cache:
            raise
        print("Cache not available. Compute tiles.")

    # The provided satellite images have a different coordinate reference system as
    # the familiar WGS 84 which uses Latitude and Longitude. So we need to reproject
    # the satellite image to the WGS 84 coordinate reference system.
    dataset, wgs84_path = reproject_dataset(geotiff_path)
    bands = np.dstack(dataset.read())

    # For the given satellite image create a bitmap which has 1 at every pixel which corresponds
    # to water in the satellite image. In order to do this we use water polygons from OpenStreetMap.
    # The water polygons are stored in forms of shapefiles and are given by "shapefile_paths".
    water_bitmap = create_bitmap(dataset, shapefile_paths, geotiff_path)

    # Tile the RGB bands of the satellite image and the bitmap.
    tiled_bands = create_tiles(bands, tile_size, wgs84_path)
    tiled_bitmap = create_tiles(water_bitmap, tile_size, wgs84_path)

    # Due to the projection the satellite image in the GeoTIFF is not a perfect rectangle and the
    # remaining space on the edges is blacked out. When we overlay the GeoTIFF with the
    # shapefile it also overlays features for the blacked out parts which means that if we don't
    # remove these tiles the classifier will be fed with non-empty labels for empty features.
    tiled_bands, tiled_bitmap = remove_edge_tiles(tiled_bands, tiled_bitmap,
                                                  tile_size, dataset.shape)

    save_tiles(cache_path, tiled_bands, tiled_bitmap)

    return tiled_bands, tiled_bitmap
Example #7
0
def visualise_labels(labels, tile_size, out_path):
    """Given the labels of a satellite image as tiles. Overlay the source image with the labels
    to check if labels are roughly correct."""

    # The tiles might come from different satellite images so we have to
    # group them according to their source image.
    get_path = lambda (tiles, pos, path): path
    sorted_by_path = sorted(labels, key=get_path)
    for path, predictions in itertools.groupby(sorted_by_path, get_path):
        raster_dataset = rasterio.open(path)

        bitmap_shape = (raster_dataset.shape[0], raster_dataset.shape[1])
        bitmap = image_from_tiles(predictions, tile_size, bitmap_shape)

        satellite_img_name = get_file_name(path)
        out_file_name = "{}.tif".format(satellite_img_name)
        out = os.path.join(out_path, out_file_name)
        overlay_bitmap(bitmap, raster_dataset, out)
Example #8
0
def visualise_labels(labels, tile_size, out_path):
    """Given the labels of a satellite image as tiles. Overlay the source image with the labels
    to check if labels are roughly correct."""

    # The tiles might come from different satellite images so we have to
    # group them according to their source image.
    get_path = lambda (tiles, pos, path): path
    sorted_by_path = sorted(labels, key=get_path)
    for path, predictions in itertools.groupby(sorted_by_path, get_path):
        raster_dataset = rasterio.open(path)

        bitmap_shape = (raster_dataset.shape[0], raster_dataset.shape[1])
        bitmap = image_from_tiles(predictions, tile_size, bitmap_shape)

        satellite_img_name = get_file_name(path)
        out_file_name = "{}.tif".format(satellite_img_name)
        out = os.path.join(out_path, out_file_name)
        overlay_bitmap(bitmap, raster_dataset, out)
Example #9
0
def create_bitmap(satellite_path, satellite_bitmap_path, raster_dataset):
    """ load the bitmap for a given satellite image. """
    #print('satellite_path: {}, satellite_bitmap_path: {}'.format(satellite_path, satellite_bitmap_path))
    satellite_img_name = get_file_name(satellite_path)
    cache_file_name = "{}_building.tif".format(satellite_img_name)
    cache_path = os.path.join(BUILDING_BITMAPS_DIR, cache_file_name)
    try:
        # Try loading the building bitmap from cache.
        print("Load building bitmap {}".format(cache_path))
        bitmap = load_bitmap(cache_path)
        bitmap[bitmap == 255] = 1
        return bitmap
    except IOError as e:
        print("No cache file found.")

    print('Create bitmaps for building features')
    print("Load shapefile {}.".format(satellite_bitmap_path))
    bitmap_image = rasterio.open(satellite_bitmap_path).read(1)

    save_bitmap(cache_path, bitmap_image, raster_dataset)

    bitmap_image[bitmap_image == 255] = 1
    return bitmap_image
Example #10
0
def visualise_results(results, tile_size, out_path, out_format="GeoTIFF"):
    """Given the predictions, false positves and the labels of our model visualise them on the satellite
    image they belong to."""

    # The tiles of the predictions, false positives and labels are all in "results".
    # We need ways to get extract them individually to pass them to overlay_bitmap.
    get_predictions = lambda (tiles, pos, path): (tiles[0], pos, path)
    get_labels = lambda (tiles, pos, path): (tiles[1], pos, path)
    get_false_positives =  lambda (tiles, pos, path): (tiles[2], pos, path)

    get_path = lambda (tiles,pos , path): path
    sorted_by_path = sorted(results, key=get_path)
    for path, result_tiles in itertools.groupby(sorted_by_path, get_path):
        raster_dataset = rasterio.open(path)
        dataset_shape = (raster_dataset.shape[0], raster_dataset.shape[1])

        result_tiles = list(result_tiles)
        predictions = map(get_predictions, result_tiles)
        labels = map(get_labels, result_tiles)
        false_positives = map(get_false_positives, result_tiles)

        satellite_img_name = get_file_name(path)
        file_extension = "tif" if out_format == "GeoTIFF" else "shp"
        out_file_name = "{}_results.{}".format(satellite_img_name, file_extension)
        out = os.path.join(out_path, out_file_name)

        if out_format == "GeoTIFF":
            # We first write the labels in blue, then predictions in green and then false positives in red.
            # This way the true positives will be green, false positives red, false negatives blue and everything
            # else in the image will be true negatives.
            for tiles, color in [(labels, 'blue'), (predictions, 'green'), (false_positives, 'red')]:
                bitmap = image_from_tiles(tiles, tile_size, dataset_shape)
                raster_dataset = overlay_bitmap(bitmap, raster_dataset, out, color=color)
        elif out_format == "Shapefile":
            bitmap = image_from_tiles(predictions, tile_size, dataset_shape)
            create_shapefile(bitmap, raster_dataset, out)