Finding the most common color/value in a matrix

    Jun 06 2012 | 8:37 pm
    Hi -
    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?

    • Jun 12 2012 | 8:45 pm
      You may want to take a look at the shaders I've just posted:
      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.
      Good luck!
    • Jun 12 2012 | 11:32 pm
      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)
    • Jun 13 2012 | 1:24 am
      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.
    • Jun 23 2015 | 6:20 pm
      I finally got around to releasing the Java code I use for this. Released version is tested on Max 7/OSX only.
      The release has variable tolerance for color groupings, and adjustable downsampling to reduce processing time. This is still not a realtime process, but is fairly fast on my recent MacBook Pro.
      Would love to get feedback on this, and suggestions for future directions.
    • Sep 05 2015 | 3:07 am
      Hey Jesse,
      This is brilliant. I just came across it, thanks for saving me a load of work, most of which I 'm probably not qualified to do. It ties in to a project I'm starting, and I'll be in touch once I start working with it. At first glance, let me just say you've done a great job.
    • Sep 05 2015 | 6:36 pm
      Glad it's useful to you - keep in touch about the project, I'd be interested to see how you use this.