18
$\begingroup$

I want to find the major color (the color which appears most often) in a picture and do some analysis later.

For example, if I have this picture:

my picture

What I want to do is find out that gray, red, black, and yellow are major colors in the picture. I thought this could be done by getting a histogram with the X-axis as colors (red, blue, yellow, etc.), and the Y-axis as proportions in the image.

And once I get that histogram, I can retrieve the highest color by comparing the Y-values.

I read some examples of ImageHistogram, ImageLevels and some other color-related functions, but I still don't know how to do this.

Any idea is welcome.

$\endgroup$
5
  • $\begingroup$ What is the "major color" here? i = 0; Image@Table[{i++/10000, 0, 0}, {h, 100}, {k, 100}] (and why?) $\endgroup$ May 9, 2013 at 3:27
  • $\begingroup$ I would like to get black and red. Do you mean getting "major color" doesn't make sense? Thanks~ $\endgroup$
    – Po-Jen Lai
    May 9, 2013 at 3:31
  • $\begingroup$ There seems to be a DominantColors function. Perhaps that is what you are going for. $\endgroup$
    – Andy Ross
    May 9, 2013 at 3:32
  • $\begingroup$ @Ricky In that image each pixel has a different color! $\endgroup$ May 9, 2013 at 3:38
  • $\begingroup$ @belisarius Oh I understand what you mean. What I want to do is getting information on the object level, but major color doesn't make sense when we see on pixel level, sorry for the vague description. $\endgroup$
    – Po-Jen Lai
    May 9, 2013 at 3:54

6 Answers 6

18
$\begingroup$

This may be what you are looking for.

img = Import["http://i.imgur.com/Wd9lPRa.jpg"]

enter image description here

Now use DominantColors.

Graphics[{#, Disk[]}] & /@ DominantColors[img, 4]

enter image description here

$\endgroup$
6
  • $\begingroup$ This is exactly what I need. Thanks! $\endgroup$
    – Po-Jen Lai
    May 9, 2013 at 3:54
  • $\begingroup$ Good answer, but interestingly I couldn't reproduce your results on my computer. Even with the parameter 4 I got four quite different colors from you. I wonder if it's platform or version dependent... $\endgroup$
    – cormullion
    May 9, 2013 at 8:29
  • $\begingroup$ Same here, cannot reproduce the colors. Manipulate[Image[{List @@@ DominantColors[img, n]}, ImageSize -> 300], {{n, 2}, 2, 20, 1}] lets you explore the n dominants, ordered based on the size of the clusters they represent says help. So, clusters. $\endgroup$
    – BoLe
    May 9, 2013 at 9:46
  • 1
    $\begingroup$ Should not it be Graphics[{#, Disk[]}] & /@ DominantColors[img, 4]? The answer as it is gives error in Mathematica 9.0.1. Anyways colors are completely different also from what you have got here. $\endgroup$ May 9, 2013 at 11:04
  • 1
    $\begingroup$ @PlatoManiac you are correct. Lets just say I should have checked the version on my kernel. $\endgroup$
    – Andy Ross
    May 9, 2013 at 12:37
16
$\begingroup$

For those without v9, here's another attempt based on FindClusters, but using a different colour space. The idea is to reduce the effect of overall brightness on the "distance" between colours, so that the clustering gives more weight to differences of hue and is less likely to pick out different shades of gray.

newspace[{r_, g_, b_}] := {r - g, b - g, (r + g + b)/10}   
rgbspace[{x_, y_, z_}] := {(2 x - y + 10 z)/3, (-x - y + 10 z)/3, (-x + 2 y + 10 z)/3}

dominants[image_, n_] := Module[{data, cols},
  data = Flatten[ImageData[image], 1];
  data = newspace /@ data;
  cols = Mean /@ FindClusters[data, n];
  RGBColor @@@ rgbspace /@ cols]      

image = Import["Wd9lPRa.jpg"];
Column[{image, GraphicsRow[Graphics[{#, Disk[]}] & /@ dominants[image, 4]]}]

enter image description here

Another example:

image = Import["Water lilies.jpg"] ~ ImageResize ~ 150;
Column[{image, GraphicsRow[Graphics[{#, Disk[]}] & /@ dominants[image, 5]]}]

enter image description here

$\endgroup$
14
$\begingroup$

Another potentially useful command of this kind is the CommonestFilter which looks locally about each pixel and chooses the most common value to display. Setting the neighborhood large causes large regions of constant color. For example

img = Import["http://i.imgur.com/Wd9lPRa.jpg"]
CommonestFilter[img, n]

where img is the image from the OPs question yields

enter image description here enter image description here

for n=6 and n=10. Following BoLe's suggestion of using this to preprocess the image, we can now apply DominantColors (as used by Andy) to achieve a reasonable partitioning.

Row[Graphics[{#, Disk[]}]&/@DominantColors[CommonestFilter[img, 10], 6]]

The output of this is:

enter image description here

$\endgroup$
1
  • $\begingroup$ Doesn't better my clustering answer, yet it seem a very promising precursor for some other approach. $\endgroup$
    – BoLe
    May 9, 2013 at 10:41
12
$\begingroup$

Try use DominantColors on particular selections instead of the whole. After import select regions you want to analyze and copy that (optionally) multiple selections as a list of images. (New in 9?)

img = Import["http://oaadonline.oxfordlearnersdictionaries.com" <>
   "/media/oaad8/fullsize/f/fru/fruit/fruit_fruit.jpg"]

enter image description here

Paste it and apply dominants to the list.

enter image description here

dominants[selec_List, n_] :=
 Image[{List @@@ DominantColors[#, n]}, ImageSize -> 200] & /@ selec
$\endgroup$
10
$\begingroup$

Here's another take. Not that successful though. It might have educational value.

i = Import@"http://i.imgur.com/Wd9lPRa.jpg";

Extract pixel values into a list of length 9k+.

data = Flatten[ImageData[i], 1];
Dimensions@data
{9603, 3}

Show the pixels as 3D points with (x, y, z) for (R, G, B) components.

Table[Graphics3D[todraw,
   Axes -> True,
   AxesLabel -> {"red", "green", "blue"}],
  {todraw, {Point[data],
    MapIndexed[{ColorData[1][First@#2],
       Point[#1]} &, FindClusters[data, 4]]}}] // GraphicsRow

graphics3d

Also shown are points partitioned into 4 clusters of nearest points. Find their centers.

major = Mean /@ FindClusters[data, 4]
{{0.504232, 0.529231, 0.52977}, {0.676402, 0.702754, 
  0.716483}, {0.454949, 0.274621, 0.130194}, {0.0921803, 0.0873291, 
  0.0800836}}

What colors do they represent?

Graphics[MapIndexed[{
    RGBColor @@ #1, Disk[{#2[[1]], 0}, .4]} &, major]]

major colors

$\endgroup$
2
  • $\begingroup$ This approach is pretty cool, gives a good intuition as to where the dominant colors are coming from. I wonder if this is how DominantColors works internally? $\endgroup$
    – Guillochon
    Jun 7, 2013 at 23:09
  • $\begingroup$ @Guillochon Along this lines. Help notes on the function: The returned colors are ordered based on the size of the clusters they represent. The specifics of clustering I don't know, it could be something cleverer than euclidean distance. $\endgroup$
    – BoLe
    Jun 8, 2013 at 15:05
9
$\begingroup$

You might also enjoy playing with ColorQuantize, which reduces the number of colors used in an image. Here's a BarChart of the results of quantization:

colorquantized = 
  SortBy[
    Tally[
      Flatten[ImageData[ColorQuantize[img, 12, Dithering -> False]], 1]],
   Last];

BarChart[colorquantized[[All, 2]], 
  ChartStyle -> RGBColor /@ colorquantized[[All, 1]]]

bar chart of image colors

I don't think that Yellow is going to make it to the top of this type of list, though...

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.