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?
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?
Réponses:
J'ai approximé l'algorithme de couleur iTunes 11 dans Mathematica étant donné la couverture de l'album en entrée:
Par essais et erreurs, j'ai trouvé un algorithme qui fonctionne sur environ 80% des albums avec lesquels je l'ai testé.
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]
J'ai rapidement découvert que la fonction Mathematica intégrée DominantColors
ne 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 .1
c'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 DominantColors
fonction intégrée.
Ma fonction réelle DominantColorsNew
ajoute la possibilité de revenir aux n
couleurs 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
]
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: .1
est la différence minimale entre les couleurs "séparées"; .2
est 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); .5
est 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[]}]
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 DominantColorsNew
ne 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.
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:
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.
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.
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).
Avec la réponse de @ Seth, j'ai implémenté l'algorithme pour obtenir la couleur dominante dans les deux bordures latérales d'une image en utilisant PHP et Imagick.
https://gist.github.com/philix/5688064#file-simpleimage-php-L81
Il est utilisé pour remplir l'arrière-plan des photos de couverture sur http://festea.com.br
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
.
J'ai posé la même question dans un contexte différent et j'ai été pointé vers http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ pour un algorithme d'apprentissage (k Moyens) qui fait grossièrement la même chose en utilisant des points de départ aléatoires dans l'image. De cette façon, l'algorithme trouve lui-même les couleurs dominantes.