Ответ 1
Я аппроксимировал цветовой алгоритм 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: когда альбом дает менее двух основных моментов, название становится белым или черным в зависимости от лучшего контраста с фоном. Затем песни становятся одним цветом выделения, если они есть, или цвет заголовка немного исчез в фоновом режиме.
Дополнительные примеры