Il nuovo iTunes 11 ha una vista molto bella per l'elenco dei brani di un album, scegliendo i colori per i caratteri e lo sfondo in funzione della copertina dell'album. Qualcuno ha capito come funziona l'algoritmo?
Il nuovo iTunes 11 ha una vista molto bella per l'elenco dei brani di un album, scegliendo i colori per i caratteri e lo sfondo in funzione della copertina dell'album. Qualcuno ha capito come funziona l'algoritmo?
Risposte:
Ho approssimato l'algoritmo di colore di iTunes 11 in Mathematica dato l'input copertina:
Attraverso tentativi ed errori, ho ideato un algoritmo che funziona su circa l'80% degli album con cui l'ho provato.
La maggior parte dell'algoritmo si occupa di trovare il colore dominante di un'immagine. Un prerequisito per trovare i colori dominanti, tuttavia, è calcolare una differenza quantificabile tra due colori. Un modo per calcolare la differenza tra due colori è calcolare la loro distanza euclidea nello spazio colore RGB. Tuttavia, la percezione del colore umano non coincide molto bene con la distanza nello spazio colore RGB.
Pertanto, ho scritto una funzione per convertire i colori RGB (nella forma {1,1,1}
) in YUV , uno spazio cromatico che è molto meglio nell'approssimazione della percezione del colore:
(EDIT: @cormullion e @Drake hanno sottolineato che gli spazi colore CIELAB e CIELUV integrati di Mathematica sarebbero altrettanto adatti ... sembra che abbia reinventato un po 'la ruota qui)
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
]
Successivamente, ho scritto una funzione per calcolare la distanza del colore con la conversione sopra:
ColorDistance[rawRGB1_, rawRGB2_] :=
EuclideanDistance[convertToYUV @ rawRGB1, convertToYUV @ rawRGB2]
Ho scoperto rapidamente che la funzione Mathematica integrata DominantColors
non consente un controllo sufficientemente accurato per approssimare l'algoritmo utilizzato da iTunes. Ho scritto la mia funzione invece ...
Un metodo semplice per calcolare il colore dominante in un gruppo di pixel è quello di raccogliere tutti i pixel in secchi di colori simili e quindi trovare il bucket più grande.
DominantColorSimple[pixelArray_] :=
Module[{buckets},
buckets = Gather[pixelArray, ColorDistance[#1,#2] < .1 &];
buckets = Sort[buckets, Length[#1] > Length[#2] &];
RGBColor @@ Mean @ First @ buckets
]
Nota che .1
è la tolleranza per come i diversi colori devono essere considerati separati. Si noti inoltre che sebbene l'input sia una matrice di pixel in formato tripletto grezzo ( {{1,1,1},{0,0,0}}
), restituisco un RGBColor
elemento Mathematica per approssimare meglio la DominantColors
funzione integrata.
La mia funzione effettiva DominantColorsNew
aggiunge la possibilità di tornare ai n
colori dominanti dopo aver filtrato un altro colore. Espone anche tolleranze per ogni confronto di colori:
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
]
Innanzitutto ho ridimensionato la copertina dell'album ( 36px
, 36px
) e ridotto i dettagli con un filtro bilaterale
image = Import["http://i.imgur.com/z2t8y.jpg"]
thumb = ImageResize[ image, 36, Resampling -> "Nearest"];
thumb = BilateralFilter[thumb, 1, .2, MaxIterations -> 2];
iTunes sceglie il colore di sfondo trovando il colore dominante lungo i bordi dell'album. Tuttavia, ignora i bordi stretti della copertina dell'album ritagliando l'immagine.
thumb = ImageCrop[thumb, 34];
Successivamente, ho trovato il colore dominante (con la nuova funzione sopra) lungo il bordo più esterno dell'immagine con una tolleranza predefinita di .1
.
border = Flatten[
Join[ImageData[thumb][[1 ;; 34 ;; 33]] ,
Transpose @ ImageData[thumb][[All, 1 ;; 34 ;; 33]]], 1];
background = DominantColorsNew[border][[1]];
Infine, ho restituito 2 colori dominanti nell'immagine nel suo insieme, dicendo alla funzione di filtrare anche il colore di sfondo.
highlights = DominantColorsNew[Flatten[ImageData[thumb], 1], .1, 2, .2,
List @@ background, .5];
title = highlights[[1]];
songs = highlights[[2]];
I valori di tolleranza sopra riportati sono i seguenti: .1
è la differenza minima tra colori "separati"; .2
è la differenza minima tra numerosi colori dominanti (un valore più basso potrebbe restituire nero e grigio scuro, mentre un valore più elevato garantisce una maggiore diversità nei colori dominanti); .5
è la differenza minima tra i colori dominanti e lo sfondo (Un valore più elevato produrrà combinazioni di colori a contrasto più elevato)
Ecco!
Graphics[{background, Disk[]}]
Graphics[{title, Disk[]}]
Graphics[{songs, Disk[]}]
L'algoritmo può essere applicato in modo molto generale. Ho modificato le impostazioni di cui sopra e i valori di tolleranza al punto in cui lavorano per produrre colori generalmente corretti per circa l'80% delle copertine degli album che ho testato. Alcuni casi limite si verificano quandoDominantColorsNew
non si trovano due colori da restituire per i momenti salienti (ovvero quando la copertina dell'album è monocromatica). Il mio algoritmo non affronta questi casi, ma sarebbe banale duplicare la funzionalità di iTunes: quando l'album produce meno di due momenti salienti, il titolo diventa bianco o nero a seconda del miglior contrasto con lo sfondo. Quindi le canzoni diventano il colore di evidenziazione unico se ce n'è uno, o il colore del titolo si sbiadisce un po 'sullo sfondo.
Con la risposta di @ Seth-thompson e il commento di @bluedog, ho creato un piccolo progetto Objective-C (Cocoa-Touch) per generare combinazioni di colori in funzione di un'immagine.
Puoi controllare il progetto su:
https://github.com/luisespinoza/LEColorPicker
Per ora, LEColorPicker sta facendo:
Questo è per ora, controllerò il progetto ColorTunes ( https://github.com/Dannvix/ColorTunes ) e il progetto Wade Cosgrove per nuove funzionalità. Inoltre ho alcune nuove idee per migliorare il risultato della combinazione di colori.
Wade Cosgrove di Panic ha scritto un post sul blog che descrive la sua implementazione di un algoritmo che si avvicina a quello di iTunes. Include un'implementazione di esempio in Objective-C.
Puoi anche provare ColorTunes che è un'implementazione HTML della vista dell'album Itunes che utilizza l'algoritmo MMCQ (median cut color quantization).
Con la risposta di @ Seth ho implementato l'algoritmo per ottenere il colore dominante nei due bordi laterali di un'immagine usando PHP e Imagick.
https://gist.github.com/philix/5688064#file-simpleimage-php-L81
Viene utilizzato per riempire lo sfondo delle foto di copertina in http://festea.com.br
Ho appena scritto una libreria JS implementando all'incirca lo stesso algoritmo di quello descritto da @Seth . È disponibile gratuitamente su github.com/arcanis/colibrijs e su NPM come colibrijs
.
Ho posto la stessa domanda in un contesto diverso e mi è stato indicato http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ per un algoritmo di apprendimento (k Mezzi) che fa rozzamente la stessa cosa usando punti di partenza casuali nell'immagine. In questo modo, l'algoritmo trova i colori dominanti da solo.