Новый iTunes 11 имеет очень хороший вид для списка песен альбома, выбирая цвета для шрифтов и фона в функции обложки альбома. Кто-нибудь разобрался, как работает алгоритм?
Новый iTunes 11 имеет очень хороший вид для списка песен альбома, выбирая цвета для шрифтов и фона в функции обложки альбома. Кто-нибудь разобрался, как работает алгоритм?
Ответы:
Я приблизил цветовой алгоритм iTunes 11 в Mathematica с учетом обложки альбома:
Методом проб и ошибок я придумал алгоритм, который работает на ~ 80% альбомов, с которыми я его тестировал.
Основная часть алгоритма связана с поиском доминирующего цвета изображения. Однако предварительным условием для нахождения доминирующих цветов является расчет количественной разницы между двумя цветами. Один из способов расчета разницы между двумя цветами - это вычисление их евклидова расстояния в цветовом пространстве RGB. Однако восприятие цвета человеком не очень хорошо согласуется с расстоянием в цветовом пространстве RGB.
Поэтому я написал функцию для преобразования цветов RGB (в форме {1,1,1}
) в YUV , цветовое пространство, которое намного лучше приближает восприятие цвета:
(РЕДАКТИРОВАТЬ: @cormullion и @Drake указали, что встроенные в Mathematica цветовые пространства CIELAB и CIELUV были бы такими же подходящими ... похоже, я немного заново изобрел колесо)
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 (квантование среднего цвета среза).
С ответом @ Seth я реализовал алгоритм получения доминирующего цвета на двух боковых границах изображения, используя PHP и Imagick.
https://gist.github.com/philix/5688064#file-simpleimage-php-L81
Он используется для заполнения фона фотографий на обложке http://festea.com.br
Я только что написал библиотеку JS, реализующую примерно тот же алгоритм, который описан @Seth . Он свободно доступен на github.com/arcanis/colibrijs и на NPM as colibrijs
.
Я задал тот же вопрос в другом контексте и был указан на http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ для алгоритм обучения (k означает), что грубо делает то же самое, используя случайные начальные точки на изображении. Таким образом, алгоритм сам находит доминирующие цвета.