Making Sense of Satellite Data, an Open Source Workflow: Color Correction with GIMP

Now that you’ve found and downloaded satellite data of an area that interests you—or just the sample datasets I pointed to in the Accessing Data and Pre-processing Multi-band Data for Sentinel-2, or Stitching Data for SkySat—what next? How can you convert raw numbers into a picture that evokes the feeling of looking down at Earth from space?

At a global scale, it’s essential to process satellite data automatically—there’s just not enough time to work on images individually. Instead, the data is processed by algorithms (not unlike the software in a digital camera) to convert from bits to pixels.

I’ve run into two general approaches, each with different tradeoffs: either process each image individually, to extract maximum contrast and “punch”, or process every image exactly the same, for consistency.

When you process scenes individually, the same place can look different from day-to-day. Not because that place (or the atmosphere above it) has actually changed, but because the algorithm does different things based on scene content. For example, here’s SkySat imagery of a seismic survey camp, deep in the Libyan desert.

Auto-adjusted SkySat image on a clear day (June 21, 2017 (left)) and on a day with scattered clouds (May 7, 2017 (right)). Images ©2018 Planet Labs, Inc. CC-by SA 4.0.

On the left is the camp on a clear day—there’s plenty of contrast in the details of the buildings and equipment, but the desert’s surface is somewhat dark and distinctly bluish—unlike any photo of the Sahara I’ve ever seen. On the other hand, on a day with scattered clouds (right) the algorithm is stretching the image based on the bright white tops of the cloud and the dark shadows. Fine details of the camp are lost, but the image as a whole is more realistic—more like what a human eye would see.

The other automatic approach is to process every scene identically, no matter what’s in it. (The data do have to be calibrated and adjusted for sun angle, etc. first.) There are two main advantages of this technique. First, every scene is comparable—a stray cloud or some snow won’t change the color balance or contrats in an image.

Snow comes and goes on Mount St. Helens, but the scene remains the same. Sentinel-2 images from May to October of 2017 via Planet’s timelapse tool.

Second, nearby scenes can be stitched together to create seamless composites—something that’s impossible if every image is scaled differently. Even subtle shifts between images result in noticeable boundaries.

Taken to an extreme, consistent color processing (with additional color matching to account for differences in atmospheric conditions and sensors) allows the creation of global mosaics.

Uniform color correction across multiple scenes allows seamless stitching of data, and works well over large areas. Images ©2018 Planet Labs, Inc. CC-by SA 4.0.

The downside of this technique is that even in the best case you’ll end up with a handful of images that look great, a ton of images that look ‘meh’, and a handful of images that look absolutely dreadful. There’s just too much dynamic range and too much variance on the Earth’s surface for a consistent color curve to work in all cases. For example, unbroken forests are going to look way too dark, and trackless deserts too bright (but at least they won’t be bluish).

With global color adjustments many landscapes lack contrast—forests remain dark and desrts are uniformly bright. Images ©2018 Planet Labs, Inc. CC-by SA 4.0.

Both techniques generally work, until they don’t; which is why fashion magazines, furniture catalogs, and film studios still employ people to manually color-correct imagery — it works.

Color-correction with GIMP

Before getting started, I highly recommend reading either or both of my previous tutorials on color correction—How to Make a True-Color Landsat Image and A Hands-On Guide to Color Correction. They both use Photoshop (decidedly not open source) but I include background on my workflow and even more rationalization for a labor-intensive process that doesn’t scale. Rather than repeating myself, I’ll get into the specifics of using GIMP.

Hopefully you’ve already either worked through Part 2 (Sentinel-2) or Part 3 (SkySat) of these tutorials, and have a pre-stretched image to work on. If not, go ahead an download this SkySat image of Boston…

Pre-processed SkySat image of Boston. ©2018 Planet Labs, Inc. CC-by SA 4.0.

… and load it into GIMP.

The basic workflow (which I learned from Real World Photoshop, sadly a decade old at this point) is to adjust the overall tone of the image, shape the colors of the individual channels, and then iterate, because every step is interdependent.

Step 1: Tonal Adjustment

Tonal adjustment (balance between bright and dark) of the image adapts the linear scaling of a scientific instrument to a human’s nonlinear perception. In short, it changes data into pictures.

Color adjustment helps compensate for the effects of the atmosphere on sunlight as it bounces off the ground and back into space. Both tonal and color adjustment is done in the curves palette, found in the menu bar under Colors→Curves.

Here’s where to find GIMP’s Curves palette.

To adjust the tone you need to modify the Value channel (it should be selected by default), which changes the brightness of the red, green, and blue channels together. Start by clicking on the straight line that goes from lower left to upper right, this creates a new point that allows the curve to be modified. Pull it up and to the left to brighten the image. Next, grab the lower left-hand end of the curve, and move it to the right. This will start making the shadows darker, but keep the highlights bright. It may even make the highlights too bright, so click on the curve again, above your first point, and pull the curve down a bit.

As a result, your curve and image should look something like this:

Step 1: tonal adjustment.

The shape of the curve represents the mapping of brightness values from the input data to the output image. Any time the curve is over the original line, the image becomes brighter, and any time it’s below it the image gets darker. By default, GIMP interpolates points smoothly, which allows for non-linear adjustments. Where the curve is steep brightness values are expanded, and where the curve is shallow brightness values are compressed.

This reflects our eye’s sensitivity to subtle changes in light levels in a dark room (a flickering candle), versus insensitivity to small changes in lightness in bright daylight (where a candle flame wouldn’t provide any perceptible illumination). The nonlinearity allows the image retain detail in both shadows and highlights — something that’s generally impossible with linear contrast stretching.

Step 2: Black Point Color Adjustment

Next, you’ll need to change the relative brightness of the Red, Green, and Blue channels individually, to compensate for the blue tinge imparted by the atmosphere. In practice, I tend to leave the shadows a little bit blue, and make the highlights a little bit yellow—a mapmaker’s trick I learned from National Park Service cartographer Tom Patterson. Removing atmospheric effects entirely makes images look unnatural.

Start with the shadows—change the Channel to Blue, and click and drag the lower-left end of the line towards the right. The curves palette includes a histogram that provides a good guide to how far you should go—a good starting point is close, but not quite all the way, to the point where the histogram starts to rise. Then repeat on to the Green channel, followed by the Red channel. In general you’ll move blue more than green more than red (which you may not need to move at all, depending on how much you adjusted Value.) This makes physical sense, because ambient light—which illuminates shadows—is blue, so regions in shadow will be relatively bluer than the rest of the image. Your result should look something like this:

Step 2: black point adjustment.

Step 3: White Point Color Adjustment

The final step is to modify the highlights to appear more natural. Human eyes inherently adjust surrounding colors based on surfaces we think are white (remember The Dress?), so it’s important that white areas are white. White point adjustments are similar to black point adjustments, but instead of moving the bottom of the curve to the right, move the top of the curve to the right. This will make the bright region of each channel brighter.

In the previous post I recommended auto-scaling the image, so the very brightest areas of the image will already be white—255, 255, 255 in red, green, and blue, respectively. So I only have to make a minimal adjustment. (You’ll likely have to make bigger changes on reflectance data, or data that hasnt’t been auto-scaled.) I’ve bumped the Red channel a bit, but left Green and Blue at their original values. This gives the highlights a slight yellow tint, just like the light on a sunny summer day.

Step 3: white point adjustment.

I found that it took me a lot of practice to get a feel for color-correction. Now that I’ve walked you through one example, try to color-correct the stretched the Sentinel-2 reflectance data from Part 2:

Pre-processed image of the Alps on July 4, 2017, from Sentinel 2B.

So far I’ve demonstrated how to find & download satellite data, processing two flavors of multi-band data with QGIS, and a color correction workflow in GIMP. Hopefully you can now create your own images from raw data.

But there’s a few more techniques that can help make images really *pop*—I’ll cover saturation enhancement and sharpening in the next installment.

Making Sense of Satellite Data: An Open Source Workflow