Super Sharp 50cm Pléiades Satellite Imagery on MapBox.com

Pléiades is a constellation of two identical high-res satellites 1A and 1B on the same heliosynchronous orbit on opposite sides. This basically means that Astrium, Europe’s leading space technology company, can capture any point on earth in less than 24 hours, always at similar illumination angles. Their imagery can produce a 20 km² ground footprint at nadir with 50cm resolution (2 meter Blue, Green, Red, Near Infrared and 0.5 meter panchromatic). Using open source tools you can publish this data on Mapbox in minutes. This is all part of our larger goal of making MapBox the number one satellite imagery publishing platform.

Any point on Earth, everyday, with 50cm resolution. With this guide you can go from image download to rendered maps in minutes, all with open software.

Astrium has set up an impressive service with Pléiades. Uplink stations can schedule acquisition up to 3 times per day. Satellites can rotate to maximize pointing opportunities with each pass. Downlink stations can collect up to 1 million km² per day, per satellite. The processing pipeline can then create calibrated and orthorectified images in just 30 minutes. With the instructions below, you can process those high-res images in minutes:

Zoom and pan around the map above, or follow a quick tour full screen. You are looking at Napoli (Italy) as it was taken on a sunny morning on February 14th, 2013 at 10:03am local time. The satellite is 700 km above ground and looking down and forward towards the city, as it is descending South on its orbit.

We’re working with a brand new Pléiades product offered by Astrium: Pléiades Optimized Visual Rendering. This product is great for users who want a high-quality product that requires minimal further processing to turn into a beautiful map.

To import the image into TileMill we need to warp it into a Google Mercator projection. Pléiades offers TIF images ready for warping, but also JP2 images which have smaller file sizes but are not as widely supported across open source image processing tools. On this guide we will use a JP2 image, but we will need to split the original image into tiles, as the 3GB JP2 image is close to 8GB as a GeoTIFF. We are currently further optimizing this process, backed by a fully open source stack.

These are the basic steps of our pipeline:

  • Install software dependencies
  • Convert downloaded image from JP2 to GeoTIFF
  • Split and warp into smaller Web Mercator tiles
  • Color correct
  • Map rendering with TileMill and upload to MapBox.com

Software Install

You might need this step if you have never followed any of our processing guides. All the tools we need are quick and free to download and use. Mostly GDAL, ImageMagick and TileMill.

This is what I used on Ubuntu (on Mac you can either brew install or download binaries from their project page):

sudo apt-get install gdal-bin unzip jasper wget qgis s3cmd imagemagick libjasper-runtime eog tilemill

For Pléiades we also need Orfeo Toolbox to convert JP2 to TIF. Check out Orfeo’s Installation Guide for full install instructions. If you’re installing on Linux, you can use:

sudo apt-get install -y libotb otb-bin python-otb

Or, on a Mac, it’s easy to install via homebrew:

brew install orfeo

Convert downloaded image from JP2 to GeoTIFF.

The Pléiades image we are using is already georeferenced and corrected for topography. It also uses the 0.5 panchomatic black&white image to pansharpen the color 2-m resolution image. There are a few utilities that support decoding JP2 files into TIFF images, but Orfeo Toolbox proved to be the best at preserving original geographic information and image quality.

Convert the image from JPEG2000 to GeoTIFF using Orfeo Toolbox’s otbcli_ExtractROI utility.

IMAGE=$(ls *.JP2)
otbcli_ExtractROI \
    -in ${IMAGE} \
    -out ${IMAGE%.JP2}.tif uint8 \
    -ram 4096;

The produced image has four bands. Since we want RGB (the first three), we throw away the fourth band by creating a Virtual Raster.

  IMAGE="IMG_PHR1A_PMS_201302141015025_ORT_644823101-001_R1C1.tif"
  gdal_translate \
    -b 1 \
    -b 2 \
    -b 3 \
    -co PHOTOMETRIC=RGB \
    -of VRT $IMAGE \
    rgb.vrt

Split and warp into smaller Web Mercator tiles.

The Pléiades image dimensions are roughly 47000x41000 pixels. As a JP2 image, the image is just over 3 GB; as a GeoTIFF, however, the image is nearly 8 GB. Knowing the capabilities and limitations of GDAL’s GeoTIFF support, we cut up the larger GeoTIFF into smaller tiles of more manageable sizes.

gdal_retile.py is a convenient utility for dividing an image into smaller images, without having to compute particular spatial extents. With this utility, you use the -ps flag to specify the output dimensions of the tiles, and gdal_retile.py calculates the rest. Since we will still need to do further processing on the tiles, we make Virtual Rasters (VRT) rather than actual image tiles (which also saves time and disk space). However, gdal_retile.py does not support creating VRTs – the VRTs it creates will show up as fully black images if you try to load them in QGIS. This is fine for us, though, since we only want the VRTs to grab the tile bounding box. Thus we use 2> /dev/null flag at the end to suppress error printing.

We want the tiles to be in our ultimate SRS, EPSG:3857, to ensure we retain the seamless image across reprojection and tiling, and gdal_retile.py retiles based on an image’s native SRS, so our first step here is to create a Virtual Raster of the converted image in Web Mercator. A VRT here saves a lot of processing time.

gdalwarp \
    -of VRT \
    -s_srs EPSG:32633 \
    -t_srs EPSG:3857 \
    rgb.vrt \
    3857.vrt

Next we make VRT tiles at 8192x8192px dimensions of the VRT, which we use to create a tileindex shapefile using gdaltindex. The shapefile will be used later to determine the tiles cut out from the original image.

mkdir -p tiles
gdal_retile.py \
    -ps 8192 8192 \
    -targetDir tiles \
    -of VRT \
    -s_srs EPSG:3857 \
    3857.vrt 2> /dev/null;

gdaltindex \
  -t_srs EPSG:4326 \
  tiles.shp \
  tiles/*vrt;

Next we take advantage of gdalwarp, wrapped within a small function specific to the Pléiades tiles. This function does a few things:

  1. Create a tile subset of the original RGB full-size image for each tile contained in the tile index file.
  2. Reproject the tile to Web Mercator: -t_srs EPSG:3857
  3. Once we’ve warped the tiles to Web Mercator, we use gdaladdo to add overviews to make them faster and easier to work with in TileMill.
function warp(){
    x="$1"
    y="$2"
    gdalwarp \
        -q \
        -s_srs EPSG:32633 \
        -t_srs EPSG:3857 \
        -cutline tiles.shp \
        -cwhere "location = \"tiles/3857_${x}_${y}.vrt\"" \
        -crop_to_cutline \
        rgb.vrt \
        tiles/${x}_${y}.tif;
    gdaladdo \
        -q\
        -r cubic \
        tiles/${x}_${y}.vrt \
        2 4 8 16;
}

Since our gdal_retile.py step produced a 6x6 tiling scheme for the original image, we can set up a simple nested for loop script to cycle through the creation and processing of each tile subset. We use the -cutline and -cwhere flag available with gdalwarp to cut out the subset tiles based on our tile index shapefile. This step can be made significantly faster, depending on the amount of computing power, by having multiple tiles process in parallel.

for x in {1..6}; do
  for y in {1..6}; do
    warp $x $y;
  done
done

Lastly, we take advantage of VRTs once again, using gdalbuildvrt to create a mosaic image of our finished tiles. Note that since we will bring this VRT into TileMill to render, it is important to supply absolute paths for the source tiles.

gdalbuildvrt \
   -srcnodata "0 0 0" \
   -vrtnodata "0 0 0" \
   mosaic.vrt \
   $(pwd)/tiles/*.tif;

Finally, we obtain the right format, coordinates and projection.

Next step is to correct those dark flat colors.

Color correct.

We are going to use Image Magik to enhance the colors on the scence. The original image is sensor corrected, but the sensor has a much wider range than the current scence, and a different sensitivity profile than the eye. Thus, we are going to add brightness and contrast to the scence. In particular, after some iterations we decided to:

1- Increase the gamma. 30%: -modulate 100,130 2- Slightly decrease the Green and Blue channels -channel G -gamma 0.95 -channel B -gamma 0.875 3- Apply a contrast correction across the intensity histogram of all channels -channel RGB -sigmoidal-contrast 11x40%

convert -monitor -modulate 100,130 -channel G -gamma 0.95 -channel B -gamma 0.875 -channel RGB -sigmoidal-contrast 11x40%  input.tif -compress lzw output.tif

Once we are set with our color correction function, we can apply it all of the tiles using a color_correct function, which uses Virtual Raster files again to preserve the tile’s original geometry information, which ImageMagick does not retain.

function color_correct(){
    x="$1"
    y="$2"
    listgeo -tfw tiles/${x}_${y}.tif 2> /dev/null;
    cp tiles/${x}_${y}.tfw color/${x}_${y}.tfw;
    convert -modulate 100,130 -channel G -gamma 0.95 -channel B -gamma 0.875 -channel RGB -sigmoidal-contrast 11x40%  tiles/${x}_${y}.tif -compress lzw color/${x}_${y}.tif 2> /dev/null;
    gdal_translate \
        -q \
        -a_srs EPSG:3857 \
        -a_nodata "0 0 0" \
        -of VRT \
        $(pwd)/color/${x}_${y}.tif \
        color/${x}_${y}.vrt;
    gdaladdo \
        -q\
        -r cubic \
        color/${x}_${y}.vrt \
        2 4 8 16;
}

mkdir -p color
for x in {1..6}; do
    for y in {1..6}; do
      color_correct $x $y;
    done
done

Finally, build the VRT of the color-corrected tiles:

gdalbuildvrt \
    color.vrt \
    $(pwd)/color/*.vrt;

Map rendering with TileMill and upload.

Importing into TileMill is now as easy as selecting the file and clicking on export to render and upload to your hosting account in MapBox. If you don´t have an account, you can make a free one here.


We love being able to integrate more imagery sources into our cloud publishing service. Make sure to check our processing tips for other leading imagery sources, like Landsat 8 or RapidEye (Or other planets!). If you have any other Satellite imagery you want to publish, let us know. Either from archives or fresh from space, we are trying to be the easiest fastest way to process, and publish imagery.

Ping us on Twitter with ideas and feedback: Chris(@hrwgc), Charlie(@vruba), or myself(@brunosan).