True color GeoTIFF

The Sentinel-2 satellite mission has resulted in the collection and dissemination of imagery covering the earth's land surface with a revisit rate of 2 to 5 days. The sensors collect multi-band imagery, where each band is a portion of the electromagnetic spectrum. The Level 2A (L2A) product provides surface reflectance measures in the following bands:

Band Description Central Wavelength (μm) Resolution (m)
B01 Coastal aerosol 0.433 60
B02 Blue 0.460 10
B03 Green 0.560 10
B04 Red 0.665 10
B05 Vegetation red edge 0.705 20
B06 Vegetation red edge 0.740 20
B07 Vegetation red edge 0.783 20
B08 Near-infrared 0.842 10
B09 Water vapor 0.945 60
B10 Short-wave infrared - Cirrus 1.375 60
B11 Short-wave infrared 1.610 20
B12 Short-wave infrared 2.190 20

When viewing multi-band imagery that includes data from outside the visible spectrum, we have to choose how to map each band to one of the three visible channels (red, green, or blue) available for rendering on digital displays. A true color composite is a rendering that displays visible blue (B02 from Sentinel-2) in the blue channel, visible green (B03) in the green channel, and visible red (B04) in the red channel. Any other mapping of satellite image bands to display channels is a false color composite.

There are a collection of Sentinel-2 L2A products hosted as Cloud-Optimized GeoTIFFs on Amazon S3. In this exercise, we'll render one of these on a map.

First, reset your index.html so we're ready to render a full page map:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>OpenLayers</title>
    <style>
      @import "node_modules/ol/ol.css";
    </style>
    <style>
      html, body, #map-container {
        margin: 0;
        height: 100%;
        width: 100%;
        font-family: sans-serif;
      }
    </style>
  </head>
  <body>
    <div id="map-container"></div>
    <script src="./main.js" type="module"></script>
  </body>
</html>

Now we'll import two new components we haven't used before:

  • the ol/source/GeoTIFF source for working with multi-band raster data
  • the ol/layer/WebGLTile layer for manipulating data tiles with shaders on the GPU

Update your main.js to load and render a remotely hosted GeoTIFF file on a map:

import GeoTIFF from 'ol/source/GeoTIFF.js';
import Map from 'ol/Map.js';
import Projection from 'ol/proj/Projection.js';
import TileLayer from 'ol/layer/WebGLTile.js';
import View from 'ol/View.js';
import {getCenter} from 'ol/extent.js';

const projection = new Projection({
  code: 'EPSG:32721',
  units: 'm',
});

// metadata from https://s3.us-west-2.amazonaws.com/sentinel-cogs/sentinel-s2-l2a-cogs/21/H/UB/2021/9/S2B_21HUB_20210915_0_L2A/S2B_21HUB_20210915_0_L2A.json
const sourceExtent = [300000, 6090260, 409760, 6200020];

const source = new GeoTIFF({
  sources: [
    {
      url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/21/H/UB/2021/9/S2B_21HUB_20210915_0_L2A/TCI.tif',
    },
  ],
});

const layer = new TileLayer({
  source: source,
});

new Map({
  target: 'map-container',
  layers: [layer],
  view: new View({
    projection: projection,
    center: getCenter(sourceExtent),
    extent: sourceExtent,
    zoom: 1,
  }),
});

The working example at http://localhost:1234/ shows a map with a GeoTIFF rendered in a WebGL tile layer.

A true color rendering of a Setinel-2 GeoTIFF
A true color rendering of a Setinel-2 GeoTIFF

The trickiest part here is finding the URL for an image that you might be interested in. To do that, you can try searching in the EO (Earth Observation) Browser. If you have the aws command line interface installed, you can also list the s3://sentinel-cogs/ bucket contents to get the paths for images by the Sentinel-2 grid cell identifier and date. For example, to search for images around Buenos Aires from September, 2021:

aws s3 ls s3://sentinel-cogs/sentinel-s2-l2a-cogs/21/H/UB/2021/9/ --no-sign-request

The next hardest part is figuring out what projection and extent are appropriate for the map view. In the next step, we'll make that easier.

results matching ""

    No results matching ""