Comment fonctionne l'algorithme pour colorer la liste des chansons dans iTunes 11? [fermé]

297

Le nouvel iTunes 11 a une très belle vue pour la liste des chansons d'un album, en choisissant les couleurs pour les polices et l'arrière-plan en fonction de la couverture de l'album. Quelqu'un a compris comment fonctionne l'algorithme?

Troisième exemple

LuisEspinoza
la source
9
La formule de contraste des couleurs w3c pourrait faire partie de la réponse. Mes propres tests empircal montrent que cette formule est utilisée par MS Word pour décider qu'il s'agit d'une police de couleur automatique. Rechercher "La luminosité des couleurs est déterminée par la formule suivante" [formule de contraste des couleurs w3c] [1] [1]: w3.org/TR/AERT#color-contrast
bluedog
@bluedog, je pense que vous avez raison. J'ai essayé beaucoup de pochettes d'albums et la police a toujours assez de contraste avec l'arrière-plan pour la voir clairement.
LuisEspinoza
1
Une autre chose à noter est qu'il semble différer entre Mac OS et Windows: twitter.com/grimfrog/status/275187988374380546
Tom Irving
2
Je pourrais imaginer que peut-être non seulement la quantité des couleurs, mais aussi leurs valeurs de saturation font partie du calcul: Mes expériences m'ont amené aux conclusions, que les couleurs de surbrillance sont souvent choisies comme couleur de fond bien qu'elles se produisent dans quelques zones du image. C'est pourquoi je crois que regarder l'histogramme de l'image de couverture et ses pics pourrait être utile, et en fonction de certains paramètres finement réglés, la couleur est choisie.
Raffael
2
Voir une autre réponse sur panic.com/blog/2012/12/itunes-11-and-colors
Mark Ransom

Réponses:

423

Exemple 1

J'ai approximé l'algorithme de couleur iTunes 11 dans Mathematica étant donné la couverture de l'album en entrée:

Sortie 1

Comment je l'ai fait

Par essais et erreurs, j'ai trouvé un algorithme qui fonctionne sur environ 80% des albums avec lesquels je l'ai testé.

Différences de couleurs

La majeure partie de l'algorithme concerne la recherche de la couleur dominante d'une image. Cependant, une condition préalable à la recherche de couleurs dominantes consiste à calculer une différence quantifiable entre deux couleurs. Une façon de calculer la différence entre deux couleurs est de calculer leur distance euclidienne dans l'espace colorimétrique RVB. Cependant, la perception des couleurs humaines ne correspond pas très bien à la distance dans l'espace colorimétrique RVB.

Par conséquent, j'ai écrit une fonction pour convertir les couleurs RVB (sous la forme {1,1,1}) en YUV , un espace colorimétrique qui est bien meilleur pour approximer la perception des couleurs:

(EDIT: @cormullion et @Drake ont souligné que les espaces colorimétriques CIELAB et CIELUV de Mathematica seraient tout aussi appropriés ... on dirait que j'ai réinventé un peu la roue ici)

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
    ]

Ensuite, j'ai écrit une fonction pour calculer la distance des couleurs avec la conversion ci-dessus:

ColorDistance[rawRGB1_, rawRGB2_] := 
    EuclideanDistance[convertToYUV @ rawRGB1, convertToYUV @ rawRGB2]

Couleurs dominantes

J'ai rapidement découvert que la fonction Mathematica intégrée DominantColorsne permettait pas un contrôle suffisamment fin pour approximer l'algorithme utilisé par iTunes. J'ai plutôt écrit ma propre fonction ...

Une méthode simple pour calculer la couleur dominante dans un groupe de pixels consiste à rassembler tous les pixels dans des seaux de couleurs similaires, puis à trouver le plus grand seau.

DominantColorSimple[pixelArray_] :=
    Module[{buckets},
        buckets = Gather[pixelArray, ColorDistance[#1,#2] < .1 &];
        buckets = Sort[buckets, Length[#1] > Length[#2] &];
        RGBColor @@ Mean @ First @ buckets
    ]

Notez que .1c'est la tolérance pour la façon dont les différentes couleurs doivent être considérées comme distinctes. Notez également que bien que l'entrée soit un tableau de pixels sous forme de triplet brut ( {{1,1,1},{0,0,0}}), je renvoie un RGBColorélément Mathematica pour mieux approximer la DominantColorsfonction intégrée.

Ma fonction réelle DominantColorsNewajoute la possibilité de revenir aux ncouleurs dominantes après avoir filtré une autre couleur donnée. Il expose également les tolérances pour chaque comparaison de couleurs:

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
    ]

Le reste de l'algorithme

J'ai d'abord redimensionné la couverture de l'album ( 36px, 36px) et réduit les détails avec un filtre bilatéral

image = Import["http://i.imgur.com/z2t8y.jpg"]
thumb = ImageResize[ image, 36, Resampling -> "Nearest"];
thumb = BilateralFilter[thumb, 1, .2, MaxIterations -> 2];

iTunes choisit la couleur d'arrière-plan en trouvant la couleur dominante le long des bords de l'album. Cependant, il ignore les bordures étroites de la couverture de l'album en recadrant l'image.

thumb = ImageCrop[thumb, 34];

Ensuite, j'ai trouvé la couleur dominante (avec la nouvelle fonction ci-dessus) le long du bord le plus à l'extérieur de l'image avec une tolérance par défaut de .1.

border = Flatten[
    Join[ImageData[thumb][[1 ;; 34 ;; 33]] , 
        Transpose @ ImageData[thumb][[All, 1 ;; 34 ;; 33]]], 1];
background = DominantColorsNew[border][[1]];

Enfin, j'ai renvoyé 2 couleurs dominantes dans l'image dans son ensemble, indiquant à la fonction de filtrer également la couleur d'arrière-plan.

highlights = DominantColorsNew[Flatten[ImageData[thumb], 1], .1, 2, .2, 
    List @@ background, .5];
title = highlights[[1]];
songs = highlights[[2]];

Les valeurs de tolérance ci-dessus sont les suivantes: .1est la différence minimale entre les couleurs "séparées"; .2est la différence minimale entre de nombreuses couleurs dominantes (une valeur inférieure peut renvoyer le noir et le gris foncé, tandis qu'une valeur plus élevée garantit une plus grande diversité des couleurs dominantes); .5est la différence minimale entre les couleurs dominantes et l'arrière-plan (une valeur plus élevée donnera des combinaisons de couleurs plus contrastées)

Voila!

Graphics[{background, Disk[]}]
Graphics[{title, Disk[]}]
Graphics[{songs, Disk[]}]

Sortie finale

Remarques

L'algorithme peut être appliqué de manière très générale. J'ai modifié les paramètres et les valeurs de tolérance ci-dessus au point où ils fonctionnent pour produire des couleurs généralement correctes pour environ 80% des couvertures d'album que j'ai testées. Quelques cas marginaux se produisent lorsque DominantColorsNewne trouve pas deux couleurs à retourner pour les hautes lumières (c'est-à-dire lorsque la couverture de l'album est monochrome). Mon algorithme ne traite pas ces cas, mais il serait trivial de dupliquer la fonctionnalité d'iTunes: lorsque l'album produit moins de deux hautes lumières, le titre devient blanc ou noir selon le meilleur contraste avec l'arrière-plan. Ensuite, les chansons deviennent la seule couleur de surbrillance s'il y en a une, ou la couleur du titre s'estompe un peu dans l'arrière-plan.

Plus d'exemples

Plus d'exemples

Seth Thompson
la source
3
OK @Seth Thompson, cela semble très prometteur. Je vais l'essayer moi-même, cela me prendra quelques jours, soyez patient.
LuisEspinoza
6
Solution assez impressionnante. Il nous faut maintenant un portage de Mathematica vers Objective-C, ce qui est difficile.
loretoparisi
1
+1 pour cette réponse très détaillée!
Marius Schulz
1
@cormullion LUV (et LAB) visent tous deux l'uniformité perceptuelle. Cependant, je n'ai trouvé aucune référence explicite à l'utilisation des distances euclidiennes dans les deux espaces colorimétriques. Je suppose que si rien d'autre, ils seraient tous deux meilleurs que RVB.
Seth Thompson
6
C'est ce que j'aime appeler une "réponse de Chuck Norris"
MCKapur
44

Avec la réponse de @ Seth-thompson et le commentaire de @bluedog, je construis un petit projet Objective-C (Cocoa-Touch) pour générer des schémas de couleurs en fonction d'une image.

Vous pouvez consulter le projet sur:

https://github.com/luisespinoza/LEColorPicker

Pour l'instant, LEColorPicker fait:

  1. L'image est mise à l'échelle à 36x36 px (cela réduit le temps de calcul).
  2. Il génère un tableau de pixels à partir de l'image.
  3. Convertit le tableau de pixels en espace YUV.
  4. Rassemblez les couleurs comme le fait le code de Seth Thompson.
  5. Les jeux de couleurs sont triés par nombre.
  6. L'algorithme sélectionne les trois couleurs les plus dominantes.
  7. Le plus dominant est assigné comme arrière-plan.
  8. Les deuxième et troisième plus dominants sont testés en utilisant la formule de contraste des couleurs w3c, pour vérifier si les couleurs ont suffisamment contrasté avec le fond.
  9. Si l'une des couleurs du texte ne réussit pas le test, elle est affectée au blanc ou au noir, selon le composant Y.

C'est pour l'instant, je vais vérifier le projet ColorTunes ( https://github.com/Dannvix/ColorTunes ) et le projet Wade Cosgrove pour les nouvelles fonctionnalités. J'ai également de nouvelles idées pour améliorer le résultat du jeu de couleurs.

Screenshot_Mona

LuisEspinoza
la source
2
+1 - Des trucs très sympas, et un excellent exemple de la façon dont le développement d'algorithmes et le développement d'applications peuvent tous deux être très intéressants à part entière
Yuval Karmi
1
+1 pour vérifier le contraste.
brianmearns
Ouais cool mais comment arrondissez-vous les valeurs de hachage pour chaque couleur? Je pense que je pourrais casser cet algorithme facilement, en ajoutant simplement un petit logo "Explicit" en noir et blanc en bas à droite, vous ajoutez vraiment un focus pour le noir et blanc. Quoi qu'il en soit, cet algorithme fonctionnerait mieux pour les images basées sur des images clipart, mais si vous avez l'image à 36x36, ces cas d'échec seront rendus plus rares par l'anti-aliasing
Jack Franzen
Un mot: FANTASTIQUE!
Teddy
16

Wade Cosgrove de Panic a écrit un joli billet de blog décrivant sa mise en œuvre d'un algorithme qui se rapproche de celui d'iTunes. Il comprend un exemple d'implémentation dans Objective-C.

Mike Akers
la source
15

Vous pouvez également extraire ColorTunes qui est une implémentation HTML de la vue de l'album Itunes qui utilise l'algorithme MMCQ (quantification médiane des couleurs coupées).

Matthias
la source
oui je l'ai déjà vérifié. Semble malheureusement à peine documenté.
LuisEspinoza
Le commentaire important dans ColorTunes est la référence à (l'algorithme de quantification de la coupe médiane) [ leptonica.com/papers/mediancut.pdf] . Je viens de l'implémenter en python en environ 2 heures, il suffit de former la description dans l'article, et je le préfère à mon implémentation de l'algorithme de Seth ci-dessus. J'aime un peu mieux les résultats, mais surtout c'est un peu plus rapide (bien sûr, j'aurais pu implémenter l'algorithme de Seth de manière incorrecte).
brianmearns
@ sh1ftst0rm avez-vous votre implémentation python sur github ou quelque part? cheers
Anentropic
@Anentropic Désolé, je ne le fais pas. Cela faisait partie d'un projet privé sur lequel je travaillais, et je ne l'ai pas extrait du tout. Si j'en ai l'occasion, j'essaierai de le poster quelque part, mais ce ne sera probablement pas de sitôt.
brianmearns
5

Je viens d'écrire une bibliothèque JS implémentant à peu près le même algorithme que celui décrit par @Seth . Il est disponible gratuitement sur github.com/arcanis/colibrijs et sur NPM as colibrijs.

Maël Nison
la source