新的iTunes 11具有专辑歌曲列表的绝佳视图,可以选择专辑封面功能中的字体和背景颜色。有人知道算法是如何工作的吗?
新的iTunes 11具有专辑歌曲列表的绝佳视图,可以选择专辑封面功能中的字体和背景颜色。有人知道算法是如何工作的吗?
Answers:
给定专辑封面作为输入,我估计了Mathematica中的iTunes 11颜色算法:
经过反复试验,我想出了一种算法,该算法可用于大约80%的测试专辑。
该算法的大部分内容是寻找图像的主色。但是,找到主色的前提是计算两种颜色之间的可量化差异。一种计算两种颜色之间差异的方法是计算它们在RGB颜色空间中的欧式距离。但是,人类的色彩感知与RGB色彩空间中的距离并不能很好地匹配。
因此,我编写了一个将RGB颜色(以形式{1,1,1}
)转换为YUV的函数,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使用的算法。我写了我自己的函数...
一种计算一组像素中主色的简单方法是将所有像素收集到相似颜色的存储桶中,然后找到最大的存储桶。
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
是主色和背景之间的最小差异(值越大,对比度越高的颜色组合)
瞧!
Graphics[{background, Disk[]}]
Graphics[{title, Disk[]}]
Graphics[{songs, Disk[]}]
该算法可以非常普遍地应用。我调整了上述设置和公差值,使它们可以为我测试的专辑封面的〜80%产生大致正确的颜色。当DominantColorsNew
找不到两种颜色返回高光时(例如,当专辑封面为单色时),会出现一些边缘情况。我的算法无法解决这些情况,但是复制iTunes的功能将是微不足道的:当专辑产生的突出显示少于两个时,标题将变为白色或黑色,具体取决于与背景的最佳对比度。然后,如果有一种,则歌曲变成一种突出显示的颜色,或者标题颜色逐渐淡入背景。
通过@ Seth-thompson的回答和@bluedog的评论,我构建了一个小的Objective-C(可可触摸)项目,以生成具有图像功能的配色方案。
您可以在以下位置检查项目:
https://github.com/luisespinoza/LEColorPicker
现在,LEColorPicker正在做:
到目前为止,我将检查ColorTunes项目(https://github.com/Dannvix/ColorTunes)和Wade Cosgrove项目是否有新功能。另外,我还有一些新想法可以改善配色方案的结果。
Panic的Wade Cosgrove写了一篇不错的博客文章,描述了他在iTunes中实现近似算法的算法的实现。它包括Objective-C中的示例实现。
您可能还会签出ColorTunes,它是Itunes专辑视图的HTML实现,该视图使用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均值)使用图像中的随机起点粗糙地执行相同的操作。这样,算法就可以自己找到主导色。