赞
踩
想要做一个工具,自动化把贴图中的所有主色调区域区分开,以便逐步为各个主色调区域单独上色。所以需要将贴图中颜色近似的区域区分开,看似非常简单,其实不然。常用的RGB或HSV颜色模型,由三个变量共同控制着颜色,如何合并成一个因子呢?经过查阅资料最终选用了一个效率和准确度相对平衡的算法。
最简单的方式就是转化为颜色空间的距离,即:distance² = (R2 - R1)² + (G2 - G1)² + (B2 - B1)²
但是人类的眼睛对于红、绿、蓝的敏感度也是不同的,这就可能造成数值上distance很小,但肉眼识别颜色感觉色差很大。因此就引入了一个RGB权重的问题,人眼越敏感的颜色权重值越大。麻烦的是在不同的色值下人类对RGB的敏感权重不同,比如R < 128 和 R ≥ 128时的敏感权重就不同:
取两个颜色R的平均值,计为averageR:
averageR = (R1 + R2) / 2
averageR < 128时:distance² = 2 * (R2 - R1)² + 4 * (G2 - G1)² + 3 * (B2 - B1)²
averageR ≥ 128时:distance² = 3 * (R2 - R1)² + 4 * (G2 - G1)² + 2 * (B2 - B1)²
还可以把两种情况的权重平滑过度,变成一个公式:
distance² = (2 + averageR / 255f) * (R2 - R1)² + 4 * (G2 - G1)² + (2 + (255 - averageR) / 255f) * (B2 - B1)²
最后最终的结果distance归一化到0-1
下面是C#实现,需要做后处理可以照搬shader中实现:
- public class ColorExt
- {
- public static float Difference(Color c1, Color c2)
- {
- c1 *= 255; c2 *= 255;
- var averageR = (c1.r + c2.r) * 0.5f;
- return Mathf.Sqrt((2 + averageR / 255f) * Mathf.Pow(c1.r - c2.r, 2) + 4 * Mathf.Pow(c1.g - c2.g, 2) + (2 + (255 - averageR) / 255f) * Mathf.Pow(c1.b - c2.b, 2)) / (3 * 255f);
- }
- }
返回值为色差,取值范围0-1。颜色越近似返回值越小,比如相同颜色返回值为0,白色与黑色返回值为1.
算法参考:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。