Nowy iTunes 11 ma bardzo ładny widok na listę utworów z albumu, wybierając kolory czcionek i tła w zależności od okładki albumu. Czy ktoś zorientował się, jak działa algorytm?
Nowy iTunes 11 ma bardzo ładny widok na listę utworów z albumu, wybierając kolory czcionek i tła w zależności od okładki albumu. Czy ktoś zorientował się, jak działa algorytm?
Odpowiedzi:
Przybliżyłem algorytm kolorów iTunes 11 w Mathematica, biorąc pod uwagę okładkę albumu jako dane wejściowe:
Dzięki próbom i błędom opracowałem algorytm, który działa na ~ 80% albumów, z którymi go testowałem.
Większość algorytmu dotyczy znalezienia dominującego koloru obrazu. Warunkiem znalezienia dominujących kolorów jest jednak obliczenie mierzalnej różnicy między dwoma kolorami. Jednym ze sposobów obliczenia różnicy między dwoma kolorami jest obliczenie ich odległości euklidesowej w przestrzeni kolorów RGB. Jednak postrzeganie kolorów przez ludzi nie pasuje zbyt dobrze do odległości w przestrzeni kolorów RGB.
Dlatego napisałem funkcję konwersji kolorów RGB (w formularzu {1,1,1}
) na YUV , przestrzeń kolorów, która jest znacznie lepsza w przybliżeniu postrzegania kolorów:
(EDYCJA: @cormullion i @Drake wskazali, że wbudowane przestrzenie kolorów CIELAB i CIELUV Mathematiki byłyby równie odpowiednie ... wygląda na to, że wymyśliłem nieco koło tutaj)
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
]
Następnie napisałem funkcję do obliczania odległości kolorów z powyższą konwersją:
ColorDistance[rawRGB1_, rawRGB2_] :=
EuclideanDistance[convertToYUV @ rawRGB1, convertToYUV @ rawRGB2]
Szybko odkryłem, że wbudowana funkcja Mathematica DominantColors
nie pozwala na wystarczająco precyzyjną kontrolę, aby zbliżyć się do algorytmu używanego przez iTunes. Zamiast tego napisałem własną funkcję ...
Prostą metodą obliczenia dominującego koloru w grupie pikseli jest zebranie wszystkich pikseli w wiadra o podobnych kolorach, a następnie znalezienie największego wiadra.
DominantColorSimple[pixelArray_] :=
Module[{buckets},
buckets = Gather[pixelArray, ColorDistance[#1,#2] < .1 &];
buckets = Sort[buckets, Length[#1] > Length[#2] &];
RGBColor @@ Mean @ First @ buckets
]
Należy pamiętać, że .1
jest to tolerancja dla tego, jak różne kolory muszą być uważane za osobne. Zauważ też, że chociaż wejściem jest tablica pikseli w surowej formie trypletu ( {{1,1,1},{0,0,0}}
), zwracam RGBColor
element Mathematica , aby lepiej przybliżyć wbudowaną DominantColors
funkcję.
Moja faktyczna funkcja DominantColorsNew
dodaje opcję powrotu do n
dominujących kolorów po odfiltrowaniu danego innego koloru. Ujawnia również tolerancje dla każdego porównania kolorów:
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
]
Najpierw zmieniłem rozmiar okładki albumu ( 36px
, 36px
) i zmniejszyłem szczegółowość dzięki dwustronnemu filtrowi
image = Import["http://i.imgur.com/z2t8y.jpg"]
thumb = ImageResize[ image, 36, Resampling -> "Nearest"];
thumb = BilateralFilter[thumb, 1, .2, MaxIterations -> 2];
iTunes wybiera kolor tła, znajdując dominujący kolor wzdłuż krawędzi albumu. Jednak ignoruje wąskie ramki okładek albumów, przycinając obraz.
thumb = ImageCrop[thumb, 34];
Następnie znalazłem dominujący kolor (z nową funkcją powyżej) wzdłuż najbardziej zewnętrznej krawędzi obrazu z domyślną tolerancją wynoszącą .1
.
border = Flatten[
Join[ImageData[thumb][[1 ;; 34 ;; 33]] ,
Transpose @ ImageData[thumb][[All, 1 ;; 34 ;; 33]]], 1];
background = DominantColorsNew[border][[1]];
Na koniec zwróciłem 2 dominujące kolory na obrazie jako całości, mówiąc funkcji odfiltrowania również koloru tła.
highlights = DominantColorsNew[Flatten[ImageData[thumb], 1], .1, 2, .2,
List @@ background, .5];
title = highlights[[1]];
songs = highlights[[2]];
Powyższe wartości tolerancji są następujące: .1
minimalna różnica między „oddzielnymi” kolorami; .2
to minimalna różnica między wieloma dominującymi kolorami (niższa wartość może zwrócić czerń i ciemnoszary, a wyższa wartość zapewnia większą różnorodność dominujących kolorów);.5
to minimalna różnica między dominującymi kolorami a tłem (wyższa wartość da kombinacje kolorów o większym kontraście)
Voila!
Graphics[{background, Disk[]}]
Graphics[{title, Disk[]}]
Graphics[{songs, Disk[]}]
Algorytm można zastosować bardzo ogólnie. Poprawiłem powyższe ustawienia i wartości tolerancji do punktu, w którym działają one w celu uzyskania ogólnie poprawnych kolorów dla ~ 80% testowanych okładek albumów. Kilka przypadków krawędzi występuje, gdyDominantColorsNew
nie można znaleźć dwóch kolorów, które można by zwrócić w celu wyróżnienia (tj. Gdy okładka albumu jest monochromatyczna). Mój algorytm nie zajmuje się tymi przypadkami, ale powielenie funkcjonalności iTunes byłoby trywialne: gdy album zawiera mniej niż dwie podświetlenia, tytuł staje się biały lub czarny, w zależności od najlepszego kontrastu z tłem. Następnie piosenki stają się jednym wyróżnionym kolorem, jeśli taki istnieje, lub kolor tytułu nieco wyblakł w tle.
Z odpowiedzią @ Seth-Thompson i komentarzem @bluedog buduję mały projekt Objective-C (Cocoa-Touch) w celu generowania schematów kolorów w funkcji obrazu.
Możesz sprawdzić projekt na:
https://github.com/luisespinoza/LEColorPicker
Na razie LEColorPicker wykonuje:
Na razie sprawdzę projekt ColorTunes ( https://github.com/Dannvix/ColorTunes ) i projekt Wade Cosgrove pod kątem nowych funkcji. Mam też kilka nowych pomysłów na ulepszenie wyniku schematu kolorów.
Wade Cosgrove z Panic napisał fajny post na blogu opisujący swoją implementację algorytmu zbliżonego do tego z iTunes. Zawiera przykładową implementację w Objective-C.
Możesz także pobrać ColorTunes, która jest implementacją HTML widoku albumu Itunes, która korzysta z algorytmu MMCQ (mediana kwantyzacji koloru cięcia).
Za pomocą odpowiedzi @ Setha zaimplementowałem algorytm, aby uzyskać dominujący kolor w dwóch bocznych granicach obrazu za pomocą PHP i Imagick.
https://gist.github.com/philix/5688064#file-simpleimage-php-L81
Służy do wypełnienia tła zdjęć na okładkę w http://festea.com.br
Właśnie napisałem bibliotekę JS implementującą mniej więcej ten sam algorytm, który opisał @Seth . Jest dostępny za darmo na github.com/arcanis/colibrijs i na NPM as colibrijs
.
I to samo pytanie w innym kontekście i wskazywano na celu http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ dla algorytm uczenia się (k Oznacza), który z grubsza robi to samo, używając losowych punktów początkowych na obrazie. W ten sposób algorytm sam odnajduje dominujące kolory.