Better Color Palettes with Histogram Equalization in D3.js

Planet OS
Planet OS
Jan 13, 2016 · 3 min read

Planet OS is handling a lot of climate and environmental data from sensors around the world for multiple projects. As a data visualization engineer, I’m always learning new tricks to makes sense of data. Visualizing data on maps can be challenging. Some colleagues smarter than myself asked me if we could have a color palette using histogram equalization. So I went to Wikipedia.

Histogram equalization is a method in image processing of contrast adjustment using the image’s histogram.

So with hints from this example, from this other one, and from this SO answer, I tried to understand it enough to make a version using D3 scales. It turned out to be very simple.

First, to prove that I have it right, I had as a goal to reproduce the example from the Wikipedia page.

Original image from the Wikipedia example

Image contrasted using histogram equalization from Wikipedia

This picture is not the best example, because a simple linear range already makes it better.

d3.scale.linear().domain(d3.extent(values)).range(['#000', '#fff']);

Image with values rescaled linearly

But the goal is to get more contrast using the histogram equalization method. In the way I understand it, we have to compute a histogram of the values, to put them into “buckets”, in a way that better distributes the values to get higher local contrast. My first thought was to use d3.scale.quantile() to compute the histogram and then use the quantiles as an input to a linear scale that will interpolate the colors between them.

Here’s how I compute the quantiles and how I feed it to my linear scale:

var quantiles = d3.scale.quantile().domain(values).range(d3.range(numberOfBuckets)).quantiles(); d3.scale.linear().domain(quantiles).range(grayScale);

It’s too simple, it can’t be right. Let’s try it on the test image to see if it gives the same results as the Wikipedia example.

Image equalized using a D3.js histogram equalization

Pretty close. Let’s try it on some maps then, now using a ColorBrewer palette (Spectral11). This represents the mean period of wind waves at ground or water surface level, taken from the WaveWatchIII dataset.

Wind wave map using a linear color palette

Same map using the same palette but equalized using D3.js histogram equalization

This needs more polishing, but the histogram equalization works pretty well. You can give it a try here with the picture from Wikipedia and here with the above map.

Happy D3 coding!

Chris Viau (@d3visualization)

Originally published at planetos.com on January 13, 2016.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store