Pta*_*uth 16 sorting graphics colors
我想对一维颜色列表进行排序,以便典型人类彼此感知"相似"的颜色彼此接近.
显然,要获得"完美"是一个困难或可能不可能的问题,因为颜色通常用三维描述,但这并不意味着没有一些分类方法看起来明显比其他方法更自然.
例如,按RGB排序不能很好地工作,因为它将按以下顺序排序,例如:
(1)R = 254 G = 0 B = 0(2)R = 254 G = 255 B = 0(3)R = 255 G = 0 B = 0(4)R = 255 G = 255 B = 0
也就是说,它将交替红色,黄色,红色,黄色这些颜色,其中两个"红色"基本上彼此不可思议地不同,并且两个黄色也彼此不可思议地不同.
但一般来说,HLS排序效果要好得多,我认为HSL甚至更好; 与其中之一,红色将彼此相邻,黄色将彼此相邻.
但是HLS/HSL也存在一些问题; 人们会认为是"黑色"的东西可能会彼此分开很远,人们会认为是"白色"的东西也是如此.
再一次,我明白我几乎不得不承认会有这样的分裂; 我只是想知道是否有人找到了比HLS/HSL更好的方法.我知道"更好"有点武断; 我的意思是"对一个典型的人来说更自然".
例如,我曾经有过一个模糊的想法,但还没有尝试过,或许"L是最重要的,如果它非常高或非常低",但除此之外它是最不重要的.有没人试过这个?它运作良好吗?具体到底你决定"非常低"和"非常高"是什么意思?等等.或者有没有人发现任何可以改善HSL的东西?
我还应该注意到,我知道我可以通过颜色立方体定义空间填充曲线,并按照沿着该曲线行进时遇到的一维顺序对它们进行排序.这将消除感知到的不连续性.但是,这不是我想要的; 我想要比我想完美的小规模分组更好的整体大规模分组.
在此先感谢您的帮助.
如果要在一个维度中对颜色列表进行排序,首先必须根据要对其进行排序的指标进行排序.对我来说最有意义的是感知亮度(相关问题).
我已经遇到了4种算法来按亮度对颜色进行排序并进行比较.这是结果.
我在循环中生成了颜色,其中仅使用了大约每400种颜色.每种颜色由2x2像素表示,颜色从最暗到最轻(从左到右,从上到下)排序.
第1张图片 - 亮度(相对)
0.2126 * R + 0.7152 * G + 0.0722 * B
Run Code Online (Sandbox Code Playgroud)
第二张图片 - http://www.w3.org/TR/AERT#color-contrast
0.299 * R + 0.587 * G + 0.114 * B
Run Code Online (Sandbox Code Playgroud)
第3张图片 - HSP颜色模型
sqrt(0.299 * R^2 + 0.587 * G^2 + 0.114 * B^2)
Run Code Online (Sandbox Code Playgroud)
4td图片 - WCAG 2.0 SC 1.4.3 相对亮度和对比度公式
根据一行中的颜色数量,有时可以在第1张和第2张照片上发现图案.我从未在第3或第4算法的图片上发现任何图案.
如果我不得不选择我会使用算法3,因为它更容易实现,比第4快约33%

您可以采取两种方法。简单的方法是将每种颜色提取为单个值,然后可以对值列表进行排序。复杂的方法取决于您必须排序的所有颜色;也许这将是一个迭代解决方案,反复调整颜色,试图最小化整个序列的“能量”。
我的猜测是,您想要一些简单而快速、看起来“足够漂亮”的东西(而不是试图找出“最佳”美学颜色排序),所以简单的方法对您来说就足够了。
我想说 HSL 是一条出路。就像是
sortValue = L * 5 + S * 2 + H
Run Code Online (Sandbox Code Playgroud)
假设 H、S 和 L 均在 [0, 1] 范围内。
如果不将3种颜色尺寸减少到单次测量,则无法做到这一点.有许多(无限)方法可以减少这些信息,但是在数学上不可能以确保减少的连续体上彼此靠近的两个数据点在它们的所有三种组件颜色中彼此接近的方式来实现这一点.值.因此,任何此类公式都可能最终将不同颜色分组.
正如您在问题中提到的,一种方法是通过您尝试排序的数据点占用的三维颜色空间拟合复杂曲线,然后将每个数据点减少到最近的位置在曲线上,然后到曲线上的那个点的距离.这可行,但在每种情况下,它都是针对特定数据点集定制的解决方案(而不是通常适用的解决方案).它也可能相对昂贵(可能),并且根本不适用于不能以曲线方式分布的数据集.
更简单的替代方案(不能完美地工作)将是选择两种"端点"颜色,优选地在色轮的相对侧.因此,例如,您可以选择红色作为一种端点颜色,选择蓝色作为另一种颜色.然后,您将每个颜色数据点转换为0到1范围内的值,其中高度偏红的颜色将得到接近0的分数,高度偏蓝的颜色将获得接近1的分数.得分为. 5表示颜色中没有红色或蓝色(也称为绿色),或者具有等量的红色和蓝色(又名紫色).这种方法并不完美,但这是你能解决这个问题的最佳方法.
有几种标准技术可以将多个维度减少到具有某种“邻近性”概念的单个维度。
我认为你应该特别检查z-order transform。
您可以通过交织三个颜色分量的位并根据此转换后的值对颜色进行排序来实现此快速版本。
以下 Java 代码应该可以帮助您入门:
public static int zValue(int r, int g, int b) {
return split(r) + (split(g)<<1) + (split(b)<<2);
}
public static int split(int a) {
// split out the lowest 10 bits to lowest 30 bits
a=(a|(a<<12))&00014000377;
a=(a|(a<<8)) &00014170017;
a=(a|(a<<4)) &00303030303;
a=(a|(a<<2)) &01111111111;
return a;
}
Run Code Online (Sandbox Code Playgroud)