Как работает алгоритм для раскладки списка песен в iTunes 11?

Новый iTunes 11 имеет очень приятное представление для списка песен альбома, подбор цветов для шрифтов и фона в функции обложки альбома. Кто-нибудь понял, как работает алгоритм?

Third Example

Ответ 1

Example 1

Я аппроксимировал цветовой алгоритм iTunes 11 в Mathematica, учитывая обложку альбома:

Output 1

Как я это сделал

Через пробную версию и ошибку я придумал алгоритм, который работает на ~ 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[]}]

Final Output

Примечания

Алгоритм может применяться очень широко. Я изменил приведенные выше настройки и допустимые значения до такой степени, что они работают, чтобы получить в целом правильные цвета для ~ 80% обложек альбомов, которые я тестировал. Несколько случаев краев возникают, когда DominantColorsNew не находит два цвета для подсветки (например, когда обложка альбома монохромна). Мой алгоритм не решает эти случаи, но было бы тривиально дублировать функциональность iTunes: когда альбом дает менее двух основных моментов, название становится белым или черным в зависимости от лучшего контраста с фоном. Затем песни становятся одним цветом выделения, если они есть, или цвет заголовка немного исчез в фоновом режиме.

Дополнительные примеры

More Examples

Ответ 2

С ответом @Seth-thompson и комментарием @bluedog я создаю небольшой проект Objective-C (Cocoa -Touch) для создания цветовых схем в функции изображения.

Вы можете проверить проект по адресу:

https://github.com/luisespinoza/LEColorPicker

Теперь LEColorPicker делает:

  • Изображение масштабируется до 36x36 px (это уменьшает время вычисления).
  • Он генерирует пиксельный массив из изображения.
  • Преобразует массив пикселей в пространство YUV.
  • Соберите цвета, как это делает код Сета Томпсона.
  • Наборы цветов сортируются по счету.
  • Алгоритм выбирает три наиболее доминирующих цвета.
  • Наиболее доминирующим является имя фона.
  • Второе и третье большинство доминантов тестируются с использованием цветовой контрастности w3c, чтобы проверить, достаточно ли цветов для контраста с фоном.
  • Если один из цветов текста не проходит тест, он присваивается белым или черным, в зависимости от компонента Y.

На данный момент я буду проверять проект ColorTunes (https://github.com/Dannvix/ColorTunes) и проект Wade Cosgrove для новых функций. Также у меня есть несколько новых идей для улучшения результата цветовой схемы.

Screenshot_Mona

Ответ 3

Уэйд Косгроув из Panic написал замечательный пост в блоге, в котором описывается его реализация алгоритма, который приближается к таковому в iTunes. Он включает примерную реализацию в Objective-C.

Ответ 4

Вы также можете проверить ColorTunes, который представляет собой реализацию HTML представления альбома Itunes, в котором используется MMCQ (медианное резкое квантование цвета) алгоритм.

Ответ 6

Я просто написал JS-библиотеку, реализующую примерно тот же алгоритм, который описан в @Seth. Он свободно доступен на github.com/arcanis/colibrijs, а на NPM - colibrijs.

Ответ 7

Я задал тот же вопрос в другом контексте и указал на http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/ для алгоритма обучения (k Средство), которое грубо делает то же самое, используя случайные стартовые точки в изображении. Таким образом, алгоритм находит доминирующие цвета сам по себе.