We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi,
im trying to get the most dominant color of an image (perfect case: getting the 5 dominant colors sorted by most used).
Is there a way to make that in processing? I tried already a code i found but with that im only getting the average color:
color extractColorFromImage(PImage img) {
img.loadPixels();
int r = 0, g = 0, b = 0;
for (int i=0; i<img.pixels.length; i++) {
color c = img.pixels[i];
r += c>>16&0xFF;
g += c>>8&0xFF;
b += c&0xFF;
}
r /= img.pixels.length;
g /= img.pixels.length;
b /= img.pixels.length;
return color(r, g, b);
}
So its not really that what i need.
I already read that i could do it with HSV, k-means and so on.... and any way to do it in processing?
Example: Here i want to get the color red as the dominant color, with the example above im getting a dark orange.
Answers
that is averaging the colours, you can see it in the code. it's adding the red green and blue up and dividing by count.
you need to get the colour for each pixel and keep a count of each separate value, which is more complicated, especially for photographs which can have a lot of colours.
then you can sort the entries by count and keep the top 5
look up ArrayList in the reference. or IntDict (which has an increment() method)
I think you can group colors based on their distance (deltaE).
Color Distance: https://en.wikipedia.org/wiki/Color_difference
For some code see: https://forum.processing.org/two/discussion/14185/palette-colors#latest
Easiest way I've come up w/ was to dump the whole
pixels[]
into an IntDict via increment():Then invoke ValuesReverse() in order to have the highest counter color keys at the top of the IntDict:
And as a final touch, collected the 1st 5 entries into a regular
color[]
array and another IntDict:The only con is that IntDict stores its keys as a String rather than an
int
orcolor
.Therefore it needs many conversions w/ str() or int() down the road. :|
In addition of not being as efficient & economic as an
int
! 3:-OWell, here's the full sketch. Enjoy! Any doubts about it, just ask: :bz
In order to be more efficient & saving than an IntDict, we need to use some sorta Map<Integer, Integer>.
Problem is such structure's got no means to sort() neither its keys nor its values.
Actually it doesn't have any notion of ordered entries! @-)
However, not all is lost. In the form of LinkedHashMap, it can at least keep its order of insertion. #:-S
That is, if we manage to sort() all of its entries in another container which allows ordering, like for example a regular array or some List, we can put() everything back into the LinkedHashMap and be assured that when we traverse it, it's gonna be iterated exactly by the order of the put() insertion. *-:)
In this more complex sketch, I've created a function called sortMapByValues() as a replacement for IntDict's ValuesReverse().
It's based on this link btW: http://StackOverflow.com/questions/34381536/sort-a-hashmap-by-the-integer-value-desc
It also invokes Array.sort() passing the array along w/ an instance of Comparator.
Only when it's sorted by most dominant color, it is dumped via put() into the LinkedHashMap, keeping insertion order. ~O)
Well, it's too daunting to explain it all. Better see it for yourself: (:|
As a bonus, an alternative version using List<Map.Entry<K, V>> in place of Map.Entry<K, V>[].
And consequently, it's relying on Collections.sort() in place of Arrays.sort(). >-)
Both K & V represent an Integer instance.
K is the
color
key and V is the value for how many times it's shown up. :-bdThis time it's based on this following article: http://JavaRevisited.BlogSpot.com.br/2012/12/how-to-sort-hashmap-java-by-key-and-value.html