This is a summary of a project to find crossovers between the USGS EO-1 satellite and Planet Dove satellite constellation using their respective APIs.
This project required quite a bit of python tooling, I am only going to summarize a few snippets of code in this post. The complete scripts can be found on Github here.
Planet is a private company that designs and operates a fleet of dozens of small ~8lb Dove satellites that mostly produce 3 band RGB color images. I also happen to work there.
The EO-1 Satellite is a single ~1300lb satellite operated by the USGS that was launched in 2000. It contains several cameras but the most interesting is its hyperspectral camera, Hyperion. I’ve written about the usefulness of hyperspectral imaging in the past. Essentially each Hyperion image is 200 separate grayscale images each showing a different wavelength of light from the scene. Most Doves image only four spectral bands, so the 200 band Hyperion image contains much more spectral information.
When two satellites image the same area on earth within a short window that’s known as a crossover. A close crossover between Hyperion/Doves allows us to examine the underlying high resolution spectrum that produced the resulting Dove image. I’ve personally been using these crossovers to assess Dove color reproduction but they can be used for all kinds of Dove calibration.
Hyperion may have higher spectral resolution but Doves have higher spatial resolution (how many pixels per square meter) and temporal resolution (how often an area is imaged). Combining data from two different systems like this gives you the best of both worlds.
Here are some of my favorite examples of sub-hour Hyperion/Dove crossovers that I found.
The thin strip is a single Hyperion image, rendered with a false color technique using non-visual bands. The wider strips are series of individual Dove images rendered in natural color that overlap with the Hyperion.
In the above cases the Dove and Hyperion images are aligned well, but often the satellites are moving in different directions and you get strips that cross paths. Sometimes you even find examples of Hyperion strips intersecting with several different Planet Doves.
To use the USGS api you’ll first need to head over to https://earthexplorer.usgs.gov/ and make an account. The Earth Explorer web app is a pretty nice tool for finding and downloading free satellite data such as Hyperion/Landsat/Sentinel.
Downloading large amount of Hyperion metadata was really easy with the unofficial python API from Mapbox https://mapbox.github.io/usgs/
Now we have the ids and other metadata for 548 Hyperion scenes from Jan 2017.
Like Earth Explorer, Planet has a web tool for browsing and downloading imagery at planet.com/explorer. Free users can browse but don’t have download access.
When you’re done playing with that, head over to https://www.planet.com/account/#/ to get your API key.
The next steps are:
- Generate geojson geometry objects for each Hyperion scene based on the lat/long coordinates in the Hyperion metadata.
- Search the Planet API for any items that intersect with each geometry within a 2 hour window
Here’s my script to do this https://github.com/Chandler/planet-labs-cookbook/blob/master/crossovers_guide/find_crossovers.py
The official Planet docs are also helpful: https://www.planet.com/docs/
With a little unix-fo I can see that of the 548 Hyperion scenes my script found 63 crossovers and some of them are offset by < 20 minutes!
At first I manually fetched a few of the crossover images from Planet Explorer and Earth Explorer and stitched them together by hand in Photoshop to see if they really lined up.
This was exciting but time consuming. The next step is to download the images and automatically combine them into one image with the correct alignment.
In the GIS world there is an Image format called GeoTiff that is commonly used to encode location information about an image so that images of the same area can be automatically stitched.
Both the Planet and USGS apis offer two basic categories of images
- Full resolution 100+MB Geotiffs
- Low resolution jpeg/png thumbnails without any location encoding.
My challenge was figuring how to download the quick thumbnail versions of the images and then convert them back into geotiffs so they could be properly stitched. Otherwise I would be stuck for days downloading gigabytes worth of full resolution imagery to make these previews.
Note that Hyperion data is 30 meters per pixel imagery and Planet data is 5 meters per pixel, a much higher resolution. In order to stitch them the Planet data will have to be rescaled to match the resolution of the Hyperion data.
I used three imaging tools to accomplish this:
- rasterio, a Python wrapper around the infamous gdal
- imagemagick, the classic imaging swiss army knife
- geotifcp, some tool I don’t even remember installing but it seems to work
Luckily, Earth Explorer offers a Hyperion “GIS Ready” bundle that comes with the preview jpg and a World File, an older format that contains location information about the image.
Not so bad.
The only lightweight preview imagery offered by Planet is through the tile service. This is a very convenient service, the full resolution image API is somewhat complicated.
A single tile request looks like this: https://tiles2.planet.com/v1/experimental/tiles/PSScene4Band/20170223_013243_0f1d/thumb?api_key=[redacted]&width=500
Planet offers no World File for tiles but if I can create my own I could use the same process to create GeoTiffs as I did for the Hyperion thumbnail. Here’s the World File schema.
pixel X size
rotation about the Y axis (usually 0.0)
rotation about the X axis (usually 0.0)
negative pixel Y size
X coordinate of upper left pixel center
Y coordinate of upper left pixel center
And here’s the metadata that can be fetched about a Planet Item from the API. The bolded items provide enough enough to build the world file.
With the newly minted World File in hand you can now build the geo tiff of the planet item.
Putting it all together
The last command is a ‘rio’ command, rio is the CLI for the rasterio library.
➜ rio merge hyperion_geo.tif planet_geo.tif merged_result.tif
This stitches our Hyperion and Planet geotiffs together into a single geotiff.
The final rendering script is here: https://github.com/Chandler/planet-labs-cookbook/blob/master/crossovers_guide/render_crossovers.py