How to make a color palette from an image ordered by frequence

My goal is to get an array that’ll show in order the most used colours in an image. The catch is that the colours should be perceptually different.

I have working code that does the first part — get all the colours in order of occurrence — but many of the colours are too similar (darker of lighter parts of other common colours.

I’m thinking that image quantization might be a way to achieve that. First have the image colours reduced, and then grab them, but I’m not sure if that’s the best approach.

Essentially, I want to get a colour palette from an image. I’d prefer if the resulting colours are really in the image (some methods average the colours). A median cut approach might be appropriate.

1 Like

First off you should share the code that you are using to collect the first bit of data. That way we can help develop it. Then it might be a good idea to pick up a pen and some paper and try to brainstorm a little. How could you do this manually? If you had a list of all the colors with all the variations, how would you sort them in order to get a good overview? Could you visualize it? How would you move on from there?

Then, when you have an idea of what you want to do or how you want to do it, you will probably have to break the problem down into smaller tasks.

And if you have any questions or have problems solving the tasks we are here to help you.

To clarify, I’m not a programming beginner (though Java is definitely not my cup of tea). I’m looking for a good general solution I can reuse, not help cooking up a personal inefficient one.

I’ve been reading for hours on methods to achieve this, which is how I came to Image Quantization, LAB, Median cut, K-means, etc. This is a (more than) solved problem and any semi-decent image editing application can achieve this via a GUI. As such, I find it hard to believe no one has a ready-made approach they like and stick to. I’d be more than happy to help improve one of those, but I’m not interested in reinventing the wheel, especially when it comes to mathematical problems. Any solution I can come up with will be inferior to an established mathematical algorithm.

Can you describe what kind of content you are working with? Is it photographic, illustrative, CGI, some mix?

Supposing your system encountered an image that was random color static

…what would be a desirable outcome? Do you have particular palette sizes in mind (3, 5, 10, 20?) and would you want to bias towards more “noticeable” versions of a color, e.g. full saturation?

Doesn’t matter. It should work with any image (i.e. collection of pixels).

Essentially, like I mention in the top post, I could already get this to work by first applying color quantization to an image and then extracting the most common colours (by checking every pixel).

For that particular image, if I apply color reduction (quantization) with imagemagick to 6 colours, I get:

Which, as a palette, translates to #CAC4CB, #363B33, #739893, #A74646, #BB54B7, #44AB46

It should be customisable.

I’m not sure. Probably not.

I remember an OLD Processing implementation of the neuquant algorithm for neural network color quantization. If what you want is “maximally flexible” (any input, any number of bins, etc) more than “performant” you could check out its results and see if you like them. Will probably need to be updated to Processing 3 – that example was 14 years ago.

Another option might be to use an external invocation of imagemagick convert, if it is doing what you like. That is the approach taken by e.g. this Kotlin demo code on color quantization:

You might also be interested in these old (2012?) Processing sketches based on k-means:

1 Like

That’s what I’m currently doing, via exec(). I do find it weird that there’s no ready-made Processing function/library for it, though.

The more common thing I’ve seen is palette generator libraries (no cluster analysis) like ColorHarmony and ColorScheme

The closest I’ve seen in library form is the ColorBlindness library, which isn’t for arbitrary analysis – it is a color translator – but it might have some clustering algorithms under the hood.

It is also possible that you could access kmeans or median cut through a more general purpose image processing library – perhaps check out the apis for opencv or boofcv.

…and here is a java implementation of median cut that I used to use with ImageJ:

1 Like

I’ve done something similar in the past by using k-means to cluster the colors. Some posts that you might find interesting: