在iTunes 11中为歌曲列表着色的algorithm如何工作?
新的iTunes 11有一个相册的歌曲列表很好的观点,select专辑封面function的字体和背景的颜色。 任何人都知道algorithm是如何工作的?
我将Mathematica中的iTunes 11颜色algorithm推荐为专辑封面作为input:
我是怎么做到的
通过试验和错误,我想出了一个algorithm,可以在我testing过的大约80%的专辑上使用。
颜色差异
该algorithm的大部分处理寻找图像的主色。 然而,find主色的先决条件是计算两种颜色之间的量化差异。 计算两种颜色差异的一种方法是计算RGB颜色空间中的欧几里德距离。 然而,在RGB色彩空间中,人类的色彩感知与距离不匹配。
因此,我写了一个函数来将RGB颜色(forms为{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使用的algorithm。 我写了自己的function,而不是…
计算一组像素中的主色的简单方法是将所有像素收集到相似颜色的桶中,然后find最大的桶。
DominantColorSimple[pixelArray_] := Module[{buckets}, buckets = Gather[pixelArray, ColorDistance[#1,#2] < .1 &]; buckets = Sort[buckets, Length[#1] > Length[#2] &]; RGBColor @@ Mean @ First @ buckets ]
注意.1
是不同的颜色必须被认为是分开的容差。 还要注意,虽然input是原始三元组forms( {{1,1,1},{0,0,0}}
)中的一个像素数组,我返回一个Mathematica RGBColor
元素以更好地逼近内置的DominantColors
函数。
我的实际functionDominantColorsNew
添加了滤除某一给定的其他颜色后返回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 ]
algorithm的其余部分
首先我调整了专辑封面( 36px
, 36px
)的大小,并用双边filter减less了细节
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];
接下来,我沿着图像的最外边缘find了主色(使用上面的新函数),默认容差为.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[]}]
笔记
该algorithm可以非常普遍地应用。 我调整了上面的设置和公差值,以使他们能够为我testing的专辑封面的80%制作大致正确的颜色。 当DominantColorsNew
没有find高亮返回的两种颜色(即当相册封面是单色的时候)会出现一些边缘情况。 我的algorithm没有解决这些情况,但是重复iTunes的function是微不足道的:当相册产生less于两个高光时,标题变成白色或黑色,这取决于与背景的最佳对比度。 然后,如果有歌曲的话,歌曲变成一个高亮的颜色,或者标题颜色淡入背景。
更多的例子
随着@ Seth-Thompson的回答和@bluedog的评论,我构build了一个Objective-C(Cocoa-Touch)项目来生成一个图像函数的配色scheme。
您可以在以下位置查看该项目:
https://github.com/luisespinoza/LEColorPicker
现在,LEColorPicker正在做:
- 图像缩放到36×36像素(这减less了计算时间)。
- 它从图像中生成一个像素数组。
- 将像素数组转换为YUV空间。
- 收集颜色塞思·汤普森的代码做到这一点。
- 颜色的集合按照计数sorting。
- 该algorithmselect三个最主要的颜色。
- 最主要的是和背景一样。
- 使用w3c颜色对比公式testing第二和第三大支配者,以检查颜色是否与背景有足够的对比。
- 如果其中一种文字颜色未通过testing,则根据Y分量将其分为白色或黑色。
那就是现在,我将检查ColorTunes项目( https://github.com/Dannvix/ColorTunes )和Wade Cosgrove项目的新function。 我也有一些新的想法来改善颜色scheme的结果。
Panic的Wade Cosgrove写了一篇很好的博客文章,描述了他在iTunes中实现的近似algorithm。 它包含Objective-C中的一个示例实现。
您也可以检出ColorTunes ,它是使用MMCQ(中值切割颜色量化)algorithm的iTunes相册视图的HTML实现。
用@ Seth的答案,我实现了algorithm,使用PHP和Imagick获取图片两个横向边界的主色。
https://gist.github.com/philix/5688064#file-simpleimage-php-L81
这是用来填补在http://festea.com.br封面照片的背景;
我刚刚写了一个JS库,实现了与@Seth描述的大致相同的algorithm。 它可以在github.com/arcanis/colibrijs和NPM上以colibrijs
forms免费获得。
我在不同的上下文中提出了相同的问题,并被指向http://charlesleifer.com/blog/using-python-and-k-means-to-find-the-dominant-colors-in-images/学习algorithm(k Means),它使用图像中的随机起点进行相同的操作。 这样,algorithm本身就可以find主色。