Новий iTunes 11 має дуже гарний вигляд для списку пісень альбому, підбираючи кольори для шрифтів та фону у функції обкладинки альбомів. Хтось зрозумів, як працює алгоритм?
Новий iTunes 11 має дуже гарний вигляд для списку пісень альбому, підбираючи кольори для шрифтів та фону у функції обкладинки альбомів. Хтось зрозумів, як працює алгоритм?
Відповіді:
Я наблизив алгоритм кольорів iTunes 11 у Mathematica, враховуючи обкладинку альбому як вхідний:
Через спроби та помилки я придумав алгоритм, який працює на ~ 80% альбомів, з якими я тестував його.
Основна частина алгоритму стосується пошуку домінуючого кольору зображення. Необхідною умовою пошуку домінуючих кольорів є обчислення кількісно різниць різниці між двома кольорами. Один із способів обчислити різницю між двома кольорами - це обчислити їх евклідову відстань у кольоровому просторі RGB. Однак сприйняття кольором людини не дуже добре відповідає відстані в кольоровому просторі RGB.
Тому я написав функцію для перетворення кольорів RGB (у формі {1,1,1}
) в YUV , кольоровий простір, який набагато краще для наближення кольорового сприйняття:
(EDIT: @cormullion і @Drake вказали, що вбудовані кольори простору CIELAB та CIELUV в Mathematica будуть настільки ж підходящими ... схоже, я тут трохи переробив колесо)
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
]
Далі я написав функцію обчислення кольорової відстані за допомогою перерахованого вище перетворення:
ColorDistance[rawRGB1_, rawRGB2_] :=
EuclideanDistance[convertToYUV @ rawRGB1, convertToYUV @ rawRGB2]
Я швидко виявив, що вбудована функція Mathematica DominantColors
не дає достатньо тонкого контролю, щоб наблизити алгоритм, який використовує iTunes. Натомість я написав власну функцію ...
Простий метод обчислення домінуючого кольору в групі пікселів - зібрати всі пікселі у відра подібних кольорів і потім знайти найбільше відро.
DominantColorSimple[pixelArray_] :=
Module[{buckets},
buckets = Gather[pixelArray, ColorDistance[#1,#2] < .1 &];
buckets = Sort[buckets, Length[#1] > Length[#2] &];
RGBColor @@ Mean @ First @ buckets
]
Зауважте, що .1
це допуск до того, як різні кольори повинні вважатися окремими. Також зауважте, що хоча вхід є масивом пікселів у необробленій формі триплета ( {{1,1,1},{0,0,0}}
), я повертаю RGBColor
елемент Mathematica, щоб краще наблизити вбудованийDominantColors
функції.
Моя фактична функція DominantColorsNew
додає можливість повернення до n
домінуючих кольорів після фільтрації заданого іншого кольору. Він також виставляє допуски для кожного порівняння кольорів:
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
]
Спочатку я змінив розмір обкладинки альбому ( 36px
, 36px
) та зменшив деталі двостороннім фільтром
image = Import["http://i.imgur.com/z2t8y.jpg"]
thumb = ImageResize[ image, 36, Resampling -> "Nearest"];
thumb = BilateralFilter[thumb, 1, .2, MaxIterations -> 2];
iTunes підбирає колір тла, знаходячи домінуючий колір по краях альбому. Однак він ігнорує вузькі рамки обкладинки альбомів, обрізаючи зображення.
thumb = ImageCrop[thumb, 34];
Далі я знайшов домінуючий колір (з новою функцією вище) уздовж самого зовнішнього краю зображення з допуском за замовчуванням .1
.
border = Flatten[
Join[ImageData[thumb][[1 ;; 34 ;; 33]] ,
Transpose @ ImageData[thumb][[All, 1 ;; 34 ;; 33]]], 1];
background = DominantColorsNew[border][[1]];
Нарешті, я повернув 2 домінуючих кольори на зображенні в цілому, кажучи про функцію фільтрації кольору фону також.
highlights = DominantColorsNew[Flatten[ImageData[thumb], 1], .1, 2, .2,
List @@ background, .5];
title = highlights[[1]];
songs = highlights[[2]];
Вище наведені значення допусків: .1
мінімальна різниця між "окремими" кольорами; .2
- мінімальна різниця між численними домінуючими кольорами (нижче значення може повертати чорний і темно-сірий, тоді як більш високе значення забезпечує більшу різноманітність домінуючих кольорів); .5
- мінімальна різниця між домінуючими кольорами та фоном (Більш високе значення дасть поєднання кольорів з більш контрастним кольором)
Вуаля!
Graphics[{background, Disk[]}]
Graphics[{title, Disk[]}]
Graphics[{songs, Disk[]}]
Алгоритм можна застосовувати дуже загально. Я змінив наведені вище параметри та значення допуску до того, що вони працюють для створення загально правильних кольорів для ~ 80% тестів, які я протестував. Декілька крайових випадків трапляються, колиDominantColorsNew
не знайдеться два кольори, щоб повернутись до яскравих моментів (наприклад, коли обкладинка альбому однотонна). Мій алгоритм не стосується цих випадків, але було б тривіально дублювати функціональність iTunes: коли альбом дає менше двох яскравих тонів, заголовок стає білим або чорним, залежно від найкращого контрасту з фоном. Тоді пісні стають одним кольором виділення, якщо такий є, або колір заголовка трохи відпадає на задньому плані.
Відповідаючи на @ Seth-thompson та на коментар @bluedog, я будую невеликий проект Objective-C (Cocoa-Touch) для створення кольорових схем у функції зображення.
Ви можете перевірити проект за адресою:
https://github.com/luisespinoza/LEColorPicker
Наразі LEColorPicker робить:
Це зараз, я перевіряю проект ColorTunes ( https://github.com/Dannvix/ColorTunes ) та проект Wade Cosgrove на нові функції. Також у мене є кілька нових ідей для покращення результату кольорової гами.
Вейд Косгров з Panic написав приємну публікацію в блозі, де описав його реалізацію алгоритму, який наближає до цього в iTunes. Він включає в себе вибірку реалізації в Objective-C.
Ви також можете перевірити ColorTunes, що є реалізацією HTML перегляду альбому Itunes, який використовує алгоритм MMCQ (середнє квантування кольорів вирізаного кольору).
З відповіддю @ Сет я реалізував алгоритм для отримання домінуючого кольору у двох бічних кордонах зображення за допомогою PHP та Imagick.
https://gist.github.com/philix/5688064#file-simpleimage-php-L81
Він використовується для заповнення фону обкладинки на http://festea.com.br
Я щойно написав бібліотеку JS, що реалізує приблизно той самий алгоритм, який описаний @Seth . Він доступний у вільному доступі на github.com/arcanis/colibrijs та на NPM як colibrijs
.
Я задав те саме питання в іншому контексті, і він був вказаний на http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ для алгоритм навчання (k означає), що грубо робить те саме, використовуючи випадкові вихідні точки на зображенні. Таким чином, алгоритм знаходить домінуючі кольори сам по собі.