如何为iTunes 11中的歌曲列表着色算法有效?

Lui*_*oza 297 algorithm user-interface itunes

新的iTunes 11可以很好地查看专辑的歌曲列表,选择专辑封面功能的字体和背景颜色.有谁想出算法是如何工作的?

第三个例子

小智 423

例1

鉴于专辑封面为输入,我在Mathematica中近似了iTunes 11颜色算法:

输出1

我是怎么做到的

通过反复试验,我提出了一种算法,该算法适用于我测试过的约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
    ]
Run Code Online (Sandbox Code Playgroud)

接下来,我写了一个函数来计算上面转换的颜色距离:

ColorDistance[rawRGB1_, rawRGB2_] := 
    EuclideanDistance[convertToYUV @ rawRGB1, convertToYUV @ rawRGB2]
Run Code Online (Sandbox Code Playgroud)

主导色彩

我很快发现内置的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
    ]
Run Code Online (Sandbox Code Playgroud)

请注意,这.1是对不同颜色必须分开考虑的容差.另请注意,尽管输入是原始三元组form({{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
    ]
Run Code Online (Sandbox Code Playgroud)

算法的其余部分

首先,我使用双边滤镜重新调整了专辑封面(36px,36px)和缩小的细节

image = Import["http://i.imgur.com/z2t8y.jpg"]
thumb = ImageResize[ image, 36, Resampling -> "Nearest"];
thumb = BilateralFilter[thumb, 1, .2, MaxIterations -> 2];
Run Code Online (Sandbox Code Playgroud)

iTunes通过查找专辑边缘的主色来选择背景色.但是,它会通过裁剪图像忽略窄的专辑封面边框.

thumb = ImageCrop[thumb, 34];
Run Code Online (Sandbox Code Playgroud)

接下来,我沿着图像的最外边缘找到了主色(带有上面的新函数),默认公差为.1.

border = Flatten[
    Join[ImageData[thumb][[1 ;; 34 ;; 33]] , 
        Transpose @ ImageData[thumb][[All, 1 ;; 34 ;; 33]]], 1];
background = DominantColorsNew[border][[1]];
Run Code Online (Sandbox Code Playgroud)

最后,我在图像中作为一个整体返回了2种主色,告诉函数也过滤掉了背景色.

highlights = DominantColorsNew[Flatten[ImageData[thumb], 1], .1, 2, .2, 
    List @@ background, .5];
title = highlights[[1]];
songs = highlights[[2]];
Run Code Online (Sandbox Code Playgroud)

上述公差值如下:.1是"单独"颜色之间的最小差异; .2是多种主色之间的最小差异(较低的值可能会返回黑色和深灰色,而较高的值可确保主色的多样性); .5是主色和背景之间的最小差异(较高的值会产生较高对比度的色彩组合)

瞧!

Graphics[{background, Disk[]}]
Graphics[{title, Disk[]}]
Graphics[{songs, Disk[]}]
Run Code Online (Sandbox Code Playgroud)

最终产出

笔记

该算法可以非常普遍地应用.我将上述设置和容差值调整到它们工作的程度,以便为我测试的约80%的专辑封面生成大致正确的颜色.当DominantColorsNew没有找到两种颜色返回高光时(即当专辑封面是单色时),会出现一些边缘情况.我的算法没有解决这些问题,但复制iTunes的功能是微不足道的:当专辑产生少于两个高光时,标题会变成白色或黑色,具体取决于与背景的最佳对比度.然后歌曲成为一个高亮颜色,如果有一个,或标题颜色逐渐淡入背景.

更多例子

更多例子

  • 非常棒的解决方案.现在需要一个从Mathematica到Objective-C的端口,这是一场艰苦的斗争. (6认同)
  • 这就是我喜欢称之为"查克诺里斯答案" (6认同)
  • 好的@Seth Thompson,看起来非常有前途.我要自己尝试一下,这需要几天时间,请耐心等待. (3认同)
  • +1 这个非常详细的答案! (2认同)

Lui*_*oza 44

在@ Seth-thompson的回答和@bluedog的评论中,我构建了一个Objective-C(Cocoa-Touch)项目来生成一个图像功能的配色方案.

您可以在以下位置查看项目:

https://github.com/luisespinoza/LEColorPicker

目前,LEColorPicker正在做:

  1. 图像缩放到36x36像素(这会减少计算时间).
  2. 它从图像生成像素阵列.
  3. 将像素阵列转换为YUV空间.
  4. 像Seth Thompson的代码那样收集颜色.
  5. 颜色的集合按计数排序.
  6. 该算法选择三种最主要的颜色.
  7. 最主要的是背景.
  8. 使用w3c颜色对比公式测试第二和第三大优势,以检查颜色是否与背景形成鲜明对比.
  9. 如果其中一种文本颜色未通过测试,则根据Y分量将其分配为白色或黑色.

那就是现在,我将检查ColorTunes项目(https://github.com/Dannvix/ColorTunes)和Wade Cosgrove项目的新功能.我也有一些改进配色方案结果的新想法.

Screenshot_Mona

  • +1 - 非常酷的东西,也是算法开发和应用程序开发本身非常有趣的一个很好的例子 (2认同)

Mik*_*ers 16

Panic的Wade Cosgrove撰写了一篇很好的博客文章,描述了他的算法的实现,该算法与iTunes中的算法相似.它包括Objective-C中的示例实现.


Mat*_*ias 15

您还可以查看ColorTunes,它是使用MMCQ(中值剪切颜色量化)算法的Itunes专辑视图的HTML实现.


phi*_*lix 5

在@ Seth的回答中,我实现了算法,使用PHP和Imagick在图片的两个横向边界中获得主色.

https://gist.github.com/philix/5688064#file-simpleimage-php-L81

它被用来填补http://festea.com.br中封面照片的背景


Maë*_*son 5

我刚刚编写了一个JS库,它实现了与@Seth描述的算法大致相同的算法.它可以在github.com/arcanis/colibrijs和NPM 上免费获得colibrijs.