# Why does DominantColors keep shuffling the order of the results?

This graphic is produced by running DominantColors (new in Mathematica 9) with different values, using the Lena image as the source:

Each row is a list of the dominant colours in an image, when asking for between 2 and 60. However I'm surprised that the order of the colors keeps changing: why would the order depend on how many you asked for?

Have I done something daft in my code? Or I have failed to grasp something obvious in the online documentation? (Either is likely.)

With[{l = ExampleData[{"TestImage", "Lena"}]},
Graphics[
Table[{colorList = DominantColors[l, d];
{Table[{
colorList[[x]],
Rectangle[{x - 1, 10 - d},{x, 10 - (d + 0.7)}]
},
{x, 1, Length@colorList}]}},
{d, 2, 60}]]
]


It's not just the order, the actual colours themselves can change depending on how many you ask for. Sometimes, these colours might not even be in your image! The reason is because DominantColors does a clustering operation and returns the mean of the n clusters in the LAB space and doesn't necessarily pick the colours that appear common to the eye (although, they coincide more often than not).

To see what I mean, consider the following example:

img = Image[{Blue, Green, Yellow, Orange, Red, Pink, Cyan} /.
RGBColor -> ({{##}} &) // Transpose, ImageSize -> {300, 50}]


Image[{List @@@ DominantColors[img, #]},
ImageSize -> {Automatic, 50}] & /@ Range@7 // Column


Until you get to 5 dominant colours, there's always one colour in the list that's not in the original image.

So to answer your question, just as you might expect a clustering operation on some random data to give you a centroid that's not an actual point in your data, DominantColors might return colours that are not in your image (but are close). This is the reason why you see some shuffling of the orders (the centroid for 2 clusters need not necessarily be the same for 3), although you can see that in general, they are roughly in the same normalized position.

• Just great, thanks for this exemplary answer. I suppose the lack of this level of information in the online docs led me to jump to the wrong conclusions about what the function was doing... Dec 20, 2012 at 22:52

You could always sort them manually

dc[n_] := List @@@ DominantColors[img, n]
Column[Image[{Sort[dc[#]]}, ImageSize -> 10*#] & /@ Range[3, 40]
,Left, 0]


Might want to fiddle some with what to sort by (second argument to Sort)

EDIT:

clist[sort_, name_] := Rasterize@Column[
{name}~Join~
(Image[{Sort[dc[#], sort]}, ImageSize -> 10*#] & /@
Range[3, 40]),
Left,
0]
lst = clist[#1, #2] & @@ # & /@ {
{Min[#1] < Min[#2] &, "Min"},
{Max[#1] < Max[#2] &, "Max"},
{Mean[#1] < Mean[#2] &, "Mean"},
{Norm[#1] < Norm[#2] &, "Two Norm"},
{OrderedQ[{#1, #2}] &, "Default"}
};
ListAnimate[lst]


If there's a way to sort it rainbowish I believe that could be good

• You can sort "rainbowish" if you ColorConvert to "HSB". Dec 20, 2012 at 20:37
• @ssch Flashy! Thanks... Dec 20, 2012 at 22:53