Come funziona l'algoritmo per colorare l'elenco dei brani in iTunes 11? [chiuso]


297

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?

Terzo esempio


9
La formula del contrasto cromatico w3c potrebbe far parte della risposta. I miei test empircal mostrano che questa formula viene utilizzata da MS Word per decidere il carattere del colore automatico. Cerca "La luminosità del colore è determinata dalla seguente formula" [w3c formula contrasto contrasto] [1] [1]: w3.org/TR/AERT#color-contrast
bluedog

@luluog, penso che tu abbia ragione. Ho provato molte copertine dei miei album e sempre il font ha abbastanza contrasto con lo sfondo per guardarlo chiaramente.
LuisEspinoza,

1
Un'altra cosa da notare è che sembra differire tra Mac OS e Windows: twitter.com/grimfrog/status/275187988374380546
Tom Irving il

2
Potrei immaginare che forse non solo la quantità dei colori, ma anche i loro valori di saturazione fanno parte del calcolo: i miei esperimenti mi hanno portato alle conclusioni, che i colori di evidenziazione vengono spesso scelti come colore di sfondo sebbene si verifichino in alcune aree del Immagine. Ecco perché credo che guardare l'istogramma dell'immagine di copertina e i suoi picchi potrebbe essere utile e, sulla base di alcuni parametri finemente sintonizzati, viene scelto il colore.
Raffael,

Risposte:


423

Esempio 1

Ho approssimato l'algoritmo di colore di iTunes 11 in Mathematica dato l'input copertina:

Uscita 1

Come l'ho fatto

Attraverso tentativi ed errori, ho ideato un algoritmo che funziona su circa l'80% degli album con cui l'ho provato.

Differenze di colore

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]

Colori dominanti

Ho scoperto rapidamente che la funzione Mathematica integrata DominantColorsnon 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 RGBColorelemento Mathematica per approssimare meglio la DominantColorsfunzione integrata.

La mia funzione effettiva DominantColorsNewaggiunge la possibilità di tornare ai ncolori 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
    ]

Il resto dell'algoritmo

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[]}]

Uscita finale

Appunti

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.

Altri esempi

Altri esempi


3
OK @Seth Thompson, sembra molto promettente. Ci proverò da solo, mi ci vorranno un paio di giorni, per favore sii paziente.
LuisEspinoza,

6
Soluzione davvero fantastica. Ora serve una porta da Mathematica a Objective-C, che è una dura lotta.
Loretoparisi,

1
+1 per questa risposta molto dettagliata!
Marius Schulz,

1
@cormullion LUV (e LAB) mirano entrambi all'uniformità percettiva. Tuttavia, non ho trovato riferimenti espliciti all'uso delle distanze euclidee in nessuno spazio dei colori. La mia ipotesi è che se non altro, entrambi sarebbero meglio di RGB.
Seth Thompson,

6
Questo è quello che mi piace chiamare una "Risposta di Chuck Norris"
MCKapur,

44

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:

  1. L'immagine viene ridimensionata a 36x36 px (questo riduce il tempo di calcolo).
  2. Genera una matrice di pixel dall'immagine.
  3. Converte l'array di pixel nello spazio YUV.
  4. Raccogli i colori come fa il codice di Seth Thompson.
  5. I set di colori sono ordinati per conteggio.
  6. L'algoritmo seleziona i tre colori più dominanti.
  7. Il più dominante è assegnato come Sfondo.
  8. Il secondo e il terzo più dominante sono testati usando la formula del contrasto cromatico w3c, per verificare se i colori hanno abbastanza contrasto con lo sfondo.
  9. Se uno dei colori del testo non supera il test, viene assegnato al bianco o al nero, a seconda del componente Y.

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.

Screenshot_Mona


2
+1 - Roba molto interessante, e un ottimo esempio di come lo sviluppo dell'algoritmo e lo sviluppo di applicazioni possano essere entrambi molto interessanti di per sé
Yuval Karmi,

1
+1 per il controllo del contrasto.
brianmearns,

Sì, ma come stai arrotondando i valori di hash per ogni colore? Penso che potrei facilmente rompere questo algoritmo, semplicemente aggiungendo un piccolo logo "Explicit" in bianco e nero in basso a destra, stai davvero aggiungendo un focus per il bianco e nero. Comunque, questo algoritmo funzionerebbe meglio per le immagini basate su clip art, ma se hai l'immagine a 36x36 quei casi falliti saranno resi più rari dall'anti-aliasing
Jack Franzen,

Una sola parola: FANTASTICO!
Teddy,

16

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.


15

Puoi anche provare ColorTunes che è un'implementazione HTML della vista dell'album Itunes che utilizza l'algoritmo MMCQ (median cut color quantization).


si lo controllo già. Purtroppo sembra a malapena documentato.
LuisEspinoza,

Il commento importante in ColorTunes è il riferimento all'algoritmo di quantizzazione con taglio mediano [ leptonica.com/papers/mediancut.pdf] . L'ho appena implementato in Python in circa 2 ore, semplicemente dalla descrizione nel documento, e lo preferisco alla mia implementazione dell'algoritmo di Seth sopra. Mi piacciono i risultati un po 'meglio, ma soprattutto è un po' più veloce (ovviamente, avrei potuto implementare l'algoritmo di Seth in modo errato).
brianmearns,

@ sh1ftst0rm hai la tua implementazione python su github o da qualche parte? applausi
Anentropic

@Anentropic Siamo spiacenti, io no. Faceva parte di un progetto privato a cui stavo lavorando e non l'ho estratto affatto. Se ne avrò la possibilità, proverò a pubblicarlo da qualche parte, ma probabilmente non lo sarà presto.
brianmearns,



Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.