Новый iTunes 11 имеет очень приятное представление для списка песен альбома, подбор цветов для шрифтов и фона в функции обложки альбома. Кто-нибудь понял, как работает алгоритм?
Новый iTunes 11 имеет очень приятное представление для списка песен альбома, подбор цветов для шрифтов и фона в функции обложки альбома. Кто-нибудь понял, как работает алгоритм?
Я аппроксимировал цветовой алгоритм iTunes 11 в Mathematica, учитывая обложку альбома:
Через пробную версию и ошибку я придумал алгоритм, который работает на ~ 80% альбомов, с которыми я его тестировал.
Основная часть алгоритма имеет дело с поиском доминирующего цвета изображения. Однако предпосылкой для поиска доминирующих цветов является подсчет количественной разницы между двумя цветами. Одним из способов расчета разницы между двумя цветами является вычисление их евклидова расстояния в цветовом пространстве RGB. Однако восприятие цвета человека не очень хорошо сочетается с расстоянием в цветовом пространстве RGB.
Поэтому я написал функцию для преобразования цветов RGB (в форме {1,1,1}
) в YUV, цветовое пространство, которое намного лучше при приближении восприятия цвета:
(EDIT: @cormulion и @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}}
), я возвращаю элемент Mathematica RGBColor
для лучшего приближения к встроенной функции 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
- минимальная разница между доминирующими цветами и фоном (более высокое значение даст более контрастные цветовые комбинации)
Voila!
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 - colibrijs
.
Я задал тот же вопрос в другом контексте и указал на http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ для алгоритма обучения (k Средство), которое грубо делает то же самое, используя случайные стартовые точки в изображении. Таким образом, алгоритм находит доминирующие цвета сам по себе.