比较 RGB 颜色,使色差比强度总和更显着
Compare RGB colors so that color difference is more significant then intensity sum
当涉及到在图像分析过程中比较颜色时,您很快就会发现您可以只使用灰度图像。为什么?因为通常你会这样做:
double average = (color.r+color.g+color.b)/3;
基于grascale平均颜色,我做了一个算法,在屏幕上找到一个对象时实际上非常令人满意(我使用了整个桌面,但是,这就足够了):
按平均颜色搜索耗时 67 毫秒,而按精确像素匹配(蓝框)搜索耗时 1.255 秒! (前者在找到第一个匹配后立即终止,而平均颜色算法循环整个图像)。
但我想提高 GUI 的精度。在 GUI 中,红色按钮看起来就像蓝色按钮,可能会错误匹配。这就是我实现颜色敏感积分图像的原因。现在我发现我不知道如何正确比较颜色总和以获得一些 真实 色差。
假设您有 2 个包含 3 个元素的数组。
//Summed colors on the image you're looking for
double sumOnSearchedImage[3];
//Summed colors on currently checked rectangle (in some loop we'll not bother with here)
double sumOnBigImage[3];
数组中的每个数字分别代表红色、蓝色和绿色的总和(不是平均值)。您如何比较这些,以便 rgb(0, 255, 255)
和 rgb(255,255,255)
之间的差异 大于 rgb(170,170,170)
和 rgb(255,255,255)
之间的差异?
使用点积
dc=cos(ang)=dot(col1,col2);
dc=r1*r2+g1*g2+b1*b2
对于标准化的 RGB 颜色(单位向量),这会为您提供 dc=<0,1>
范围内的系数,其中 0
表示颜色之间的角度为 90 度(最大可能差异) 和 1
表示相同的颜色(不是强度)
性能
每个通道使用 8 位...所以范围是 <0,255>
以避免 FPU 使用。您可以通过以下方式避免 sqrt
使用非标准化颜色:
dc=(r1*r2+g1*g2+b1*b2)^2/(|col1|^2*|col2|^2)
|col|^2=r*r+g*g+b*b
[edit1] 附加信息
归一化颜色是单位3D向量
如果像 255*(r,g,b)
那样将其转换为 8 位范围,则每个通道范围为 8 位,因此您可以将每个颜色通道处理为整数或定点小数。对于定点你只需要改变乘法和除法,其余的操作都是一样的:
add=a+b
sub=a-b
mul=(a*b)>>8
div=((a<<8)/b)>>8
当你使用标准化颜色时 |col|=1
所以你不需要 sqrt
也不需要除法。对于定点,只需右移 8 位...对于整数 <0,255>
,|col|=255
也可以通过 ~shift 右移 8 位来完成。对于非标准化颜色,您需要除以 |col|
,这需要 sqrt
和除法,但 dc
系数在 <0,1>
范围内,因此如果您使用 dc^2
,您只需更改系数的线性度对您和 |col|^2
不重要,sqrt
用法已过时,因为 |col|^2=sqrt(r*r+g*g+b*b)^2=(r*r+g*g+b*b)
.
为了更好地加快速度,您应该在执行任务之前将整个图像转换为标准化颜色。如果编码正确,对于普通桌面分辨率
,它应该在 10+ ms
左右
[注释]
还有其他颜色空间更适合您的目的,例如 HSV
在指标space中rgb(0, 255, 255)和rgb(255,255,255)之间的距离已经远远大于rgb(170,170,170)和rgb(255,255,255)之间的距离。
不使用距离本身,而是使用它们的平方来提高速度。
|(0, 255, 255), (255,255,255)|^2 = 255^2 = 9*85^2
|(170,170,170), (255,255,255)|^2 = 3*85^2
顺便说一句,不要惊讶地发现灰度视图通常就足够了。好的设计使设计师能够使事物 a) 清晰可见,b) 至少以某种方式对大约 18% 的人可见,因为很多人在颜色识别方面存在问题。 http://www.colour-blindness.com/general/prevalence/
当涉及到在图像分析过程中比较颜色时,您很快就会发现您可以只使用灰度图像。为什么?因为通常你会这样做:
double average = (color.r+color.g+color.b)/3;
基于grascale平均颜色,我做了一个算法,在屏幕上找到一个对象时实际上非常令人满意(我使用了整个桌面,但是,这就足够了):
按平均颜色搜索耗时 67 毫秒,而按精确像素匹配(蓝框)搜索耗时 1.255 秒! (前者在找到第一个匹配后立即终止,而平均颜色算法循环整个图像)。
但我想提高 GUI 的精度。在 GUI 中,红色按钮看起来就像蓝色按钮,可能会错误匹配。这就是我实现颜色敏感积分图像的原因。现在我发现我不知道如何正确比较颜色总和以获得一些 真实 色差。
假设您有 2 个包含 3 个元素的数组。
//Summed colors on the image you're looking for
double sumOnSearchedImage[3];
//Summed colors on currently checked rectangle (in some loop we'll not bother with here)
double sumOnBigImage[3];
数组中的每个数字分别代表红色、蓝色和绿色的总和(不是平均值)。您如何比较这些,以便 rgb(0, 255, 255)
和 rgb(255,255,255)
之间的差异 大于 rgb(170,170,170)
和 rgb(255,255,255)
之间的差异?
使用点积
dc=cos(ang)=dot(col1,col2);
dc=r1*r2+g1*g2+b1*b2
对于标准化的 RGB 颜色(单位向量),这会为您提供 dc=<0,1>
范围内的系数,其中 0
表示颜色之间的角度为 90 度(最大可能差异) 和 1
表示相同的颜色(不是强度)
性能
每个通道使用 8 位...所以范围是 <0,255>
以避免 FPU 使用。您可以通过以下方式避免 sqrt
使用非标准化颜色:
dc=(r1*r2+g1*g2+b1*b2)^2/(|col1|^2*|col2|^2)
|col|^2=r*r+g*g+b*b
[edit1] 附加信息
归一化颜色是单位3D向量
如果像 255*(r,g,b)
那样将其转换为 8 位范围,则每个通道范围为 8 位,因此您可以将每个颜色通道处理为整数或定点小数。对于定点你只需要改变乘法和除法,其余的操作都是一样的:
add=a+b
sub=a-b
mul=(a*b)>>8
div=((a<<8)/b)>>8
当你使用标准化颜色时 |col|=1
所以你不需要 sqrt
也不需要除法。对于定点,只需右移 8 位...对于整数 <0,255>
,|col|=255
也可以通过 ~shift 右移 8 位来完成。对于非标准化颜色,您需要除以 |col|
,这需要 sqrt
和除法,但 dc
系数在 <0,1>
范围内,因此如果您使用 dc^2
,您只需更改系数的线性度对您和 |col|^2
不重要,sqrt
用法已过时,因为 |col|^2=sqrt(r*r+g*g+b*b)^2=(r*r+g*g+b*b)
.
为了更好地加快速度,您应该在执行任务之前将整个图像转换为标准化颜色。如果编码正确,对于普通桌面分辨率
,它应该在10+ ms
左右
[注释]
还有其他颜色空间更适合您的目的,例如 HSV
在指标space中rgb(0, 255, 255)和rgb(255,255,255)之间的距离已经远远大于rgb(170,170,170)和rgb(255,255,255)之间的距离。
不使用距离本身,而是使用它们的平方来提高速度。
|(0, 255, 255), (255,255,255)|^2 = 255^2 = 9*85^2
|(170,170,170), (255,255,255)|^2 = 3*85^2
顺便说一句,不要惊讶地发现灰度视图通常就足够了。好的设计使设计师能够使事物 a) 清晰可见,b) 至少以某种方式对大约 18% 的人可见,因为很多人在颜色识别方面存在问题。 http://www.colour-blindness.com/general/prevalence/