我想设计一个程序,可以帮助我在5种预定义的颜色中评估哪一种更类似于可变颜色,以及与可变颜色的百分比。问题是我不知道如何手动一步一步地做到这一点。所以想一个程序就更难了。
更多细节:颜色来自不同颜色的管子和凝胶的照片。我有5个不同颜色的管子,每个代表5个等级中的1个。我想拍摄其他样本的照片,然后在电脑上通过比较颜色来评估样本属于哪个级别,我也想知道一个近似的百分比。我想要一个这样做的程序:http://www.colortools.net/color_matcher.html
如果你能告诉我该采取什么步骤,即使它们需要我手动思考和执行。那会很有帮助的。
如果你有两个颜色对象c1和c2,你可以比较c1和c2的每个RGB值。
int diffRed = Math.abs(c1.getRed() - c2.getRed());
int diffGreen = Math.abs(c1.getGreen() - c2.getGreen());
int diffBlue = Math.abs(c1.getBlue() - c2.getBlue());
你可以将这些值除以饱和度的差异(255),你就会得到两者之间的差异。
float pctDiffRed = (float)diffRed / 255;
float pctDiffGreen = (float)diffGreen / 255;
float pctDiffBlue = (float)diffBlue / 255;
之后你就可以找到平均色差的百分比。
(pctDiffRed + pctDiffGreen + pctDiffBlue) / 3 * 100
这就得到了c和c之间的百分比差。
快速回答
我找到这个帖子是因为我需要这个问题的Swift版本。由于还没有人给出答案,我的答案是:
extension UIColor {
var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red, green, blue, alpha)
}
func isSimilar(to colorB: UIColor) -> Bool {
let rgbA = self.rgba
let rgbB = colorB.rgba
let diffRed = abs(CGFloat(rgbA.red) - CGFloat(rgbB.red))
let diffGreen = abs(rgbA.green - rgbB.green)
let diffBlue = abs(rgbA.blue - rgbB.blue)
let pctRed = diffRed
let pctGreen = diffGreen
let pctBlue = diffBlue
let pct = (pctRed + pctGreen + pctBlue) / 3 * 100
return pct < 10 ? true : false
}
}
用法:
let black: UIColor = UIColor.black
let white: UIColor = UIColor.white
let similar: Bool = black.isSimilar(to: white)
我设置小于10%的差异返回相似的颜色,但你可以自定义这自己。
Actually I walked the same path a couple of months ago. There is no perfect answer to the question (that was asked here a couple of times) but there is one, more sophisticated than the sqrt(r-r) etc. answer and more easy to implement directly with RGB without moving to all kinds of alternate color spaces. I found this formula here which is a low cost approximation of the quite complicated real formula (by the CIE which is the W3C of colors, since this is a not finished quest, you can find older and simpler color difference equations there).
Good Luck.
编辑:为了子孙后代,这里是相关的C代码:
typedef struct {
unsigned char r, g, b;
} RGB;
double ColourDistance(RGB e1, RGB e2)
{
long rmean = ( (long)e1.r + (long)e2.r ) / 2;
long r = (long)e1.r - (long)e2.r;
long g = (long)e1.g - (long)e2.g;
long b = (long)e1.b - (long)e2.b;
return sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8));
}
如果你有两个颜色对象c1和c2,你可以比较c1和c2的每个RGB值。
int diffRed = Math.abs(c1.getRed() - c2.getRed());
int diffGreen = Math.abs(c1.getGreen() - c2.getGreen());
int diffBlue = Math.abs(c1.getBlue() - c2.getBlue());
你可以将这些值除以饱和度的差异(255),你就会得到两者之间的差异。
float pctDiffRed = (float)diffRed / 255;
float pctDiffGreen = (float)diffGreen / 255;
float pctDiffBlue = (float)diffBlue / 255;
之后你就可以找到平均色差的百分比。
(pctDiffRed + pctDiffGreen + pctDiffBlue) / 3 * 100
这就得到了c和c之间的百分比差。
请参阅维基百科关于色差的文章以获得正确的线索。
基本上,你想要在多维颜色空间中计算一个距离度量。
但是RGB并不是“感知上一致的”,所以Vadim建议的欧几里得RGB距离度量将与人类感知的颜色之间的距离不匹配。首先,L*a*b*是一个感知上均匀的颜色空间,delta度量是常用的。但有更精致的色彩空间和更精致的delta公式,更接近人类的感知。
你需要学习更多关于颜色空间和光源的知识来进行转换。但如果想要一个比欧几里得RGB度量更好的快速公式,只需这样做:
假设你的RGB值在sRGB颜色空间中
找到sRGB到L*a*b*的转换公式
将sRGB颜色转换为L*a*b*
计算两个L*a*b*值之间的delta
计算成本不高,只是一些非线性公式和一些乘法和加法。