Overlaying Sentinel 2 13 Band Data with Classification TIF Data in Python

Overlaying Earth observation imagery from Sentinel 2 satellites with classified landcover data enables powerful geospatial analysis. We can visualize vegetation health metrics, assess drought impacts on croplands, quantify surface water changes, and much more by leveraging the spectral bands within Sentinel 2 data fused with categories labeling environmental regions.

This guide will demonstrate a step-by-step workflow for loading Sentinel 2 13 band rasters in Python, aligning pixels to a classified TIF file, applying proper color mapping, and then visualizing the integrated output.

Overview

We will cover:

  • Loading Sentinel 2 tiled imagery with Rasterio
  • Reading in classification TIF data
  • Aligning coordinate systems
  • Assigning RGB bands for visualization
  • Applying pixel colors based on TIF codes
  • Plotting the overlaid raster mosaic

Importing Packages

We will utilize 4 key Python libraries:

import rasterio
from rasterio.plot import show
import earthpy.spatial as es
import matplotlib.pyplot as plt
JavaScript
  • Rasterio: reading and manipulating GeoTIFF/raster data
  • Earthpy: satellite and geospatial processing tools
  • Matplotlib: visualization and plotting capabilities

Loading Sentinel 2 Imagery

We will demonstrate with a sample Sentinel 2 L1C tile covering part of Belgium:

s2_path = 's2_tile.tif'
src = rasterio.open(s2_path)
s2 = src.read()
print(f'Sentinel bands: {s2.shape}')
JavaScript

This loads the 13 spectral bands as a NumPy array with dimensions: (13, 10980, 10980)”

Load Classification TIF Data

Next, we open the classification raster for the same region:

ml_path = 'crop_map.tif' 
ml_src = rasterio.open(ml_path)
ml_arr = ml_src.read()
print(f'Classification array shape: {ml_arr.shape}')
JavaScript

Our crop_map is a single-channel TIF with categorical values.

Align GeoTIFF Extents

Now we clip the Sentinel 2 coverage to match our classified TIF layer exactly:

aligned_s2_arr, ml_transform = es.crop_image(s2, ml_src)
JavaScript

This ensures the same spatial extent and band counts when overlaying.

Map RGB Bands

Next, we define which Sentinel bands map to RGB channels for eventual visualization:

red = aligned_s2_arr[3].squeeze() 
green = aligned_s2_arr[2].squeeze()
blue = aligned_s2_arr[1].squeeze()
JavaScript

Band 4 covers red wavelengths, band 3 covers green, and band 2 captures the blue channel.

Define Color Palette

Then we create a Categorical colormap to colorize pixels based on classified TIFF categories:

cmap = plt.colormaps['Pastel2'] 
colors = [ cmap(i) for i in range(cmap.N) ]
JavaScript

Apply Colors

Here we map RGB channels and colorize where classification exists:

vis = ml_arr.copy()
vis[ml_arr==0] = (red[ml_arr==0], green[ml_arr==0],  
                  blue[ml_arr==0]) 

vis[ml_arr==1] = colors[1] 

vis[ml_arr==2] = colors[2]
JavaScript

Areas where no classification label is assigned retain true color from S2. Other regions get colorized based on their coding value to reveal segmentation.

Visualize Output

Finally, plot using Matplotlib:

fig, ax = plt.subplots(figsize=(12, 12))  
ax.imshow(vis) 
ax.set_title('Sentinel 2 overlaid with Crop Map')
ax.set_axis_off() 
plt.show()
JavaScript

We should now see an integrated raster with a true color background from Sentinel 2 images enriched by classified TIF overlays!

Full Script

Here is the entire overlay code workflow:

import rasterio
from rasterio.plot import show
import earthpy.spatial as es
import matplotlib.pyplot as plt

s2_path = 's2_tile.tif’  
src = rasterio.open(s2_path)
s2 = src.read() 

ml_path = 'crop_map.tif’   
ml_src = rasterio.open(ml_path)  
ml_arr = ml_src.read()   

aligned_s2_arr, ml_transform = es.crop_image(s2, ml_src)
   
red = aligned_s2_arr[3].squeeze()  
green = aligned_s2_arr[2].squeeze()
blue = aligned_s2_arr[1].squeeze()   

cmap = plt.colormaps['Pastel2']  
colors = [ cmap(i) for i in range(cmap.N) ]
   
vis = ml_arr.copy()
vis[ml_arr==0] = (red[ml_arr==0], green[ml_arr==0], blue[ml_arr==0])
   
vis[ml_arr==1] = colors[1]  
vis[ml_arr==2] = colors[2]   

fig, ax = plt.subplots(figsize=(12, 12))   
ax.imshow(vis)
ax.set_title('Sentinel 2 overlaid with Crop Map')
ax.set_axis_off()
plt.show()
JavaScript

Automating this Earth observation data fusion process enables the rapid generation of insightful landcover change visualizations!

Key Takeaways

To recap the main steps covered:

  • Open Sentinel 2 tiles and classified TIFs with Rasterio
  • Align geo extents between both datasets
  • Define RGB channel mappings
  • Create a color palette from classification codes
  • Overlay truecolor background with categorical overlays
  • Visualize integrated raster mosaic

This workflow can extend towards video generation by iterating across time series imagery with class raster animations.

We have only touched the surface of deep multivariate geospatial analytics possible from these types of multispectral satellite and vector data integrations within Python’s powerful computational geospatial libraries.

But this initial tutorial should provide a template to get you started overlaying additional datasets for all kinds of insightful Earth analytics!

Leave a Comment