jupyter-widgets / ipyleaflet

A Jupyter - Leaflet.js bridge
https://ipyleaflet.readthedocs.io
MIT License
1.49k stars 365 forks source link

Fail to load raster layer: ImageOverlay #1145

Open hillsonghimire opened 10 months ago

hillsonghimire commented 10 months ago

I tried the following code to visualize a single band raster image form landsat 8, but the image cannot render over the map. The broken thumbnail appears over the map layer.

I am using google colab as notebook server.

image

import rasterio
from pyproj import Proj, transform

from ipyleaflet import Map, ImageOverlay

# Open the raster file using rasterio
path = '/content/LC08_L1TP_126049_20200301_20200313_01_T1_B1.TIF'
src = rasterio.open(path)

with rasterio.open(path) as src:
    bounds = src.bounds
    crs = src.crs
utm_crs = crs.to_proj4()
wgs84_crs = Proj(init='epsg:4326')

# Convert UTM bounds to latitude and longitude
left, bottom = transform(utm_crs, wgs84_crs, bounds.left, bounds.bottom)
right, top = transform(utm_crs, wgs84_crs, bounds.right, bounds.top)

# print(left, right, )
# print(bottom, top,)

m = Map(center=(((bottom+top)/2, (left+right)/2)), zoom=3)

# # Create an ImageOverlay and add it to the map
overlay = ImageOverlay(url='/content/LC08_L1TP_126049_20200301_20200313_01_T1_B1.TIF', bounds=((bottom, left), (top, right)))
m.add_layer(overlay)

# # Display the map
m
tsutterley commented 10 months ago

Hi @hillsonghimire,

As far as I know, most browsers cannot display tiff images directly. Without making changes to ipyleaflet to include bindings to e.g. GeoRaster, you could:

1) convert the raster to png following @giswqs's example here

import io
import base64
import PIL.Image
# convert geotiff image to in-memory png
f = PIL.Image.open('/content/LC08_L1TP_126049_20200301_20200313_01_T1_B1.TIF')
png = io.BytesIO()
f.save(png, format='png')
png.seek(0)
# encode to base64 and get url
data = base64.b64encode(png.read()).decode('ascii')
url = "data:image/png;base64," + data
# visualize with ImageOverlay
overlay = ImageOverlay(url=url, bounds=((bottom, left), (top, right)))

2) use the tile layer functionality as outlined by @banesullivan here

I think adding bindings for GeoRaster might be a good long-term fix, but this should work in the mean time. Hope this helps.

giswqs commented 10 months ago

It is recommended to add a raster dataset as a tile layer with localtileserver rather than using ImageOverlay. See this example: https://leafmap.org/notebooks/32_local_tile

tsutterley commented 10 months ago

agreed.

giswqs commented 10 months ago

More examples: https://geoai.gishub.org/examples/dataviz/raster_viz