Das neue iTunes 11 bietet eine sehr schöne Ansicht für die Songliste eines Albums und wählt die Farben für die Schriftarten und den Hintergrund in Abhängigkeit vom Albumcover aus. Hat jemand herausgefunden, wie der Algorithmus funktioniert?
Das neue iTunes 11 bietet eine sehr schöne Ansicht für die Songliste eines Albums und wählt die Farben für die Schriftarten und den Hintergrund in Abhängigkeit vom Albumcover aus. Hat jemand herausgefunden, wie der Algorithmus funktioniert?
Antworten:
Ich habe den iTunes 11-Farbalgorithmus in Mathematica anhand des Albumcovers als Eingabe angenähert:
Durch Versuch und Irrtum habe ich einen Algorithmus gefunden, der auf ~ 80% der Alben funktioniert, mit denen ich ihn getestet habe.
Der Großteil des Algorithmus befasst sich mit dem Finden der dominanten Farbe eines Bildes. Voraussetzung für das Auffinden dominanter Farben ist jedoch die Berechnung eines quantifizierbaren Unterschieds zwischen zwei Farben. Eine Möglichkeit, die Differenz zwischen zwei Farben zu berechnen, besteht darin, ihren euklidischen Abstand im RGB-Farbraum zu berechnen. Die menschliche Farbwahrnehmung passt jedoch nicht sehr gut zur Entfernung im RGB-Farbraum.
Daher habe ich eine Funktion zum Konvertieren von RGB-Farben (in der Form {1,1,1}
) in YUV geschrieben , einen Farbraum, der die Farbwahrnehmung viel besser approximieren kann:
(EDIT: @cormullion und @Drake wiesen darauf hin, dass die eingebauten CIELAB- und CIELUV-Farbräume von Mathematica genauso geeignet wären ... es sieht so aus, als hätte ich das Rad hier etwas neu erfunden)
convertToYUV[rawRGB_] :=
Module[{yuv},
yuv = {{0.299, 0.587, 0.114}, {-0.14713, -0.28886, 0.436},
{0.615, -0.51499, -0.10001}};
yuv . rawRGB
]
Als nächstes schrieb ich eine Funktion zur Berechnung des Farbabstands mit der obigen Konvertierung:
ColorDistance[rawRGB1_, rawRGB2_] :=
EuclideanDistance[convertToYUV @ rawRGB1, convertToYUV @ rawRGB2]
Ich stellte schnell fest, dass die integrierte Mathematica-Funktion DominantColors
nicht genügend fein abgestimmte Steuerelemente zulässt, um den von iTunes verwendeten Algorithmus zu approximieren. Ich habe stattdessen meine eigene Funktion geschrieben ...
Eine einfache Methode zur Berechnung der dominanten Farbe in einer Gruppe von Pixeln besteht darin, alle Pixel in Eimern ähnlicher Farben zu sammeln und dann den größten Eimer zu finden.
DominantColorSimple[pixelArray_] :=
Module[{buckets},
buckets = Gather[pixelArray, ColorDistance[#1,#2] < .1 &];
buckets = Sort[buckets, Length[#1] > Length[#2] &];
RGBColor @@ Mean @ First @ buckets
]
Beachten Sie, dass dies .1
die Toleranz dafür ist, wie unterschiedliche Farben als getrennt betrachtet werden müssen. Beachten Sie auch, dass die Eingabe zwar ein Array von Pixeln in roher Triplettform ( {{1,1,1},{0,0,0}}
) ist, ich jedoch ein Mathematica- RGBColor
Element zurückgebe, um die integrierte DominantColors
Funktion besser zu approximieren .
Meine eigentliche Funktion DominantColorsNew
fügt die Option hinzu, n
nach dem Herausfiltern einer bestimmten anderen Farbe zu dominanten Farben zurückzukehren. Außerdem werden Toleranzen für jeden Farbvergleich angezeigt:
DominantColorsNew[pixelArray_, threshold_: .1, n_: 1,
numThreshold_: .2, filterColor_: 0, filterThreshold_: .5] :=
Module[
{buckets, color, previous, output},
buckets = Gather[pixelArray, ColorDistance[#1, #2] < threshold &];
If[filterColor =!= 0,
buckets =
Select[buckets,
ColorDistance[ Mean[#1], filterColor] > filterThreshold &]];
buckets = Sort[buckets, Length[#1] > Length[#2] &];
If[Length @ buckets == 0, Return[{}]];
color = Mean @ First @ buckets;
buckets = Drop[buckets, 1];
output = List[RGBColor @@ color];
previous = color;
Do[
If[Length @ buckets == 0, Return[output]];
While[
ColorDistance[(color = Mean @ First @ buckets), previous] <
numThreshold,
If[Length @ buckets != 0, buckets = Drop[buckets, 1],
Return[output]]
];
output = Append[output, RGBColor @@ color];
previous = color,
{i, n - 1}
];
output
]
Zuerst habe ich die Größe des Albumcovers ( 36px
, 36px
) geändert und die Details mit einem bilateralen Filter reduziert
image = Import["http://i.imgur.com/z2t8y.jpg"]
thumb = ImageResize[ image, 36, Resampling -> "Nearest"];
thumb = BilateralFilter[thumb, 1, .2, MaxIterations -> 2];
iTunes wählt die Hintergrundfarbe aus, indem es die dominierende Farbe an den Rändern des Albums findet. Durch Beschneiden des Bildes werden jedoch schmale Albumcover-Ränder ignoriert.
thumb = ImageCrop[thumb, 34];
Als nächstes fand ich die dominante Farbe (mit der neuen Funktion oben) am äußersten Rand des Bildes mit einer Standardtoleranz von .1
.
border = Flatten[
Join[ImageData[thumb][[1 ;; 34 ;; 33]] ,
Transpose @ ImageData[thumb][[All, 1 ;; 34 ;; 33]]], 1];
background = DominantColorsNew[border][[1]];
Zuletzt habe ich 2 dominante Farben im gesamten Bild zurückgegeben und die Funktion angewiesen, auch die Hintergrundfarbe herauszufiltern.
highlights = DominantColorsNew[Flatten[ImageData[thumb], 1], .1, 2, .2,
List @@ background, .5];
title = highlights[[1]];
songs = highlights[[2]];
Die obigen Toleranzwerte sind wie folgt: .1
ist die minimale Differenz zwischen "getrennten" Farben; .2
ist der minimale Unterschied zwischen zahlreichen dominanten Farben (ein niedrigerer Wert kann Schwarz und Dunkelgrau zurückgeben, während ein höherer Wert eine größere Vielfalt der dominanten Farben gewährleistet); .5
ist der minimale Unterschied zwischen dominanten Farben und dem Hintergrund (Ein höherer Wert ergibt kontrastreichere Farbkombinationen)
Voila!
Graphics[{background, Disk[]}]
Graphics[{title, Disk[]}]
Graphics[{songs, Disk[]}]
Der Algorithmus kann sehr allgemein angewendet werden. Ich habe die obigen Einstellungen und Toleranzwerte so weit angepasst, dass sie für ~ 80% der von mir getesteten Albumcover allgemein korrekte Farben erzeugen. Einige Randfälle treten auf, wenn DominantColorsNew
keine zwei Farben für die Highlights gefunden werden (dh wenn das Albumcover monochrom ist). Mein Algorithmus behandelt diese Fälle nicht, aber es wäre trivial, die Funktionalität von iTunes zu duplizieren: Wenn das Album weniger als zwei Glanzlichter liefert, wird der Titel je nach bestem Kontrast zum Hintergrund weiß oder schwarz. Dann werden die Songs zu der einen Hervorhebungsfarbe, wenn es eine gibt, oder die Titelfarbe tritt etwas in den Hintergrund.
Mit der Antwort von @ Seth-thompson und dem Kommentar von @bluedog baue ich ein kleines Objective-C-Projekt (Cocoa-Touch), um Farbschemata in Abhängigkeit von einem Bild zu generieren.
Sie können das Projekt überprüfen unter:
https://github.com/luisespinoza/LEColorPicker
Im Moment macht LEColorPicker:
Im Moment werde ich das ColorTunes-Projekt ( https://github.com/Dannvix/ColorTunes ) und das Wade Cosgrove-Projekt auf neue Funktionen überprüfen . Außerdem habe ich einige neue Ideen zur Verbesserung des Farbschemaergebnisses.
Wade Cosgrove von Panic schrieb einen schönen Blog-Beitrag, in dem er seine Implementierung eines Algorithmus beschrieb, der dem in iTunes nahekommt. Es enthält eine Beispielimplementierung in Objective-C.
Sie können auch ColorTunes auschecken , eine HTML-Implementierung der Itunes- Albumansicht, die den MMCQ-Algorithmus (Median Cut Color Quantization) verwendet.
Mit der Antwort von @ Seth habe ich den Algorithmus implementiert, um mit PHP und Imagick die dominante Farbe in den beiden seitlichen Rändern eines Bildes zu erhalten.
https://gist.github.com/philix/5688064#file-simpleimage-php-L81
Es wird verwendet, um den Hintergrund von Titelfotos in http://festea.com.br zu füllen
Ich habe gerade eine JS-Bibliothek geschrieben, die ungefähr den gleichen Algorithmus implementiert wie den von @Seth beschriebenen . Es ist frei verfügbar unter github.com/arcanis/colibrijs und auf NPM as colibrijs
.
Ich fragte die gleiche Frage in einem anderen Kontext und wurde darauf über http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ für ein Lernalgorithmus (k bedeutet), der mit zufälligen Startpunkten im Bild das Gleiche tut. Auf diese Weise findet der Algorithmus selbst dominante Farben.