Finding the most common color/value in a matrix
I’m writing a patch right now to detect the most common color in a matrix, and then use that as an input value. I located a thread from five years ago by a poster who wanted to do something similar, but the patch posted in that thread does not seem to work, and the problem appeared unsolved.
An example of how I’d like it to work. If I had a matrix of a variety of RGB color values, I wouldn’t just want to take the average of them and output that as the value, I’d instead want to bin similar values together and then perform a count to see which bin had the highest frequency. If I could output the top 5 colors by frequency, that would be even better.
I’ve been exploring jit.rgb2hsl, jit.histogram, and jit.3m but none of these seem to do what I want. Is it possible, or possible to approximate this function?
You may want to take a look at the shaders I’ve just posted: http://cycling74.com/forums/topic.php?id=40482
I built exactly this type of system by creating a chain from RGB –> XYZ –> CIE-L*ab, reading back to a matrix, performing my binning in Java, then back from CIE-L*ab –> XYZ –> RGB. If you build the binning right you can make a very functional tool with variable tolerance.
awesome contribution with the colorspace shaders Jesse!
i’d love to know more about the technique you would use these to solve the problem described in therethere’s post (finding dominant colors in a matrix)
Happy if they’re useful to someone else.
Once you have the texture converted to CIE-L*ab you can iterate through the image and use one of the color delta formulas on this page to do comparisons:
More info on color difference measurements here:
I experimented with both the Delta E 1994 and Delta E 2000 methods, and found the 1994 algorithm to be closer to my own perception, especially when playing with tolerance levels. All of the listed methods require pre-processing to CIE-L*ab, which was the motivation behind the shaders.
I did the binning in Java, through what I euphemistically call a "lazy attractor" approach – anything that was within an adjustable tolerance of a previously observed color was grouped and then averaged to create a composite L*ab value. The larger the composite group, the higher up the comparison list it traveled, so it had a higher likelihood of ensnaring incoming pixels.
My "bins" were wrappers around an ArrayList, so I could collect the L*ab colors and eventually output a histogram that showed the color (converted back to RGB using the reverse shaders) and its relative weight.
This is unfortunately not a realtime process, and I did have to down-rez my source images to get reasonable performance, but the results were promising. I’m sure someone more clever could come up with a way to speed this up to the point that it could be used realtime – it was something I threw together fairly quickly.
If there’s interest I may be able to clean up the Java code and post, but not sure when I’ll have time to do that. I figured I’d release the shaders and see what you all might come up with.