我已经创建了一个函数来查找图像中的颜色,然后返回x,y。现在我需要添加一个新功能,在那里我可以找到具有给定容忍度的颜色。应该很容易吗?
在图像中查找颜色的代码,并返回x,y:
def FindColorIn(r,g,b, xmin, xmax, ymin, ymax):
image = ImageGrab.grab()
for x in range(xmin, xmax):
for y in range(ymin,ymax):
px = image.getpixel((x, y))
if px[0] == r and px[1] == g and px[2] == b:
return x, y
def FindColor(r,g,b):
image = ImageGrab.grab()
size = image.size
pos = FindColorIn(r,g,b, 1, size[0], 1, size[1])
return pos
结果:
从答案中得出,比较两种颜色的常规方法是欧几里德距离或切比雪夫距离。
我决定大多使用(平方)欧几里德距离和多个不同的颜色空间。 LAB,deltaE(LCH),XYZ,HSL和RGB。在我的代码中,大多数颜色空间使用平方欧几里德距离来计算差异。
例如,LAB,RGB和XYZ是一个简单的平方euc。距离就是诀窍:
if ((X-X1)^2 + (Y-Y1)^2 + (Z-Z1)^2) <= (Tol^2) then
...
LCH和HSL稍微复杂一点,因为它们都有圆柱形色调,但是有些数学解决了这个问题,那么它就是使用平方eucl。在这里。
在大多数情况下,我为每个频道添加了“单独参数”(使用1个全局容差,以及替代“修饰符”HueTol := Tolerance * hueMod
或LightTol := Tolerance * LightMod
)。
似乎在XYZ(LAB,LCH)之上构建的色彩空间在我的许多场景中表现最佳。在某些情况下,HSL会产生非常好的效果,而且转换为RGB要便宜得多,RGB也很棒,并且满足了我的大部分需求。
答案 0 :(得分:19)
以一种对眼睛有意义的方式计算RGB颜色之间的距离并不像在两个RGB矢量之间获取欧几里德距离那么容易。
这里有一篇有趣的文章:http://www.compuphase.com/cmetric.htm
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));
}
移植到Python应该不会太难。
修改强>
或者,如this answer中所述,您可以使用HLS and HSV。 colorsys
模块似乎具有从RGB进行转换的功能。它的文档也链接到这些页面,值得阅读,以了解为什么RGB欧几里德距离不起作用:
编辑2:
根据this answer,此库应该有用:http://code.google.com/p/python-colormath/
答案 1 :(得分:3)
这是一个优化的 Python
版本,改编自 Bruno 的asnwer:
def ColorDistance(rgb1,rgb2):
'''d = {} distance between two colors(3)'''
rm = 0.5*(rgb1[0]+rgb2[0])
d = sum((2+rm,4,3-rm)*(rgb1-rgb2)**2)**0.5
return d
用法:
>>> import numpy
>>> rgb1 = numpy.array([1,1,0])
>>> rgb2 = numpy.array([0,0,0])
>>> ColorDistance(rgb1,rgb2)
2.5495097567963922
答案 2 :(得分:2)
假设rtol,gtol和btol分别是r,g和b的容差,为什么不这样做:
if abs(px[0]- r) <= rtol and \
abs(px[1]- g) <= gtol and \
abs(px[2]- b) <= btol:
return x, y
答案 3 :(得分:1)
而不是:
if px[0] == r and px[1] == g and px[2] == b:
试试这个:
if max(map(lambda a,b: abs(a-b), px, (r,g,b))) < tolerance:
tolerance
是您愿意在任何颜色渠道中接受的最大差异。
它的作用是从目标值中减去每个通道,取绝对值,然后取最大值。
答案 4 :(得分:1)
这是Bruno和Developer的答案的矢量化Python(numpy)版本(即,近似值here的实现),它接受一对形状为{{1}的numpy数组},其中各个行按(x, 3)
的顺序排列,并且各个颜色值∈[0,1]。
您可以将其减少为两个,而以可读性为代价。我不能完全确定它是否是最优化的版本,但它应该足够好。
[R, G, B]
它是根据上面开发人员的每个元素版本进行评估的,并产生相同的结果(在千分之二的情况下保存浮动精度错误)。
答案 5 :(得分:1)
函数here的更清晰的python实现,该函数采用2条图像路径,使用cv.imread读取它们,并输出一个矩阵,每个矩阵单元具有不同的颜色。您可以更改它以使其轻松匹配2种颜色
import numpy as np
import cv2 as cv
def col_diff(img1, img2):
img_bgr1 = cv.imread(img1) # since opencv reads as B, G, R
img_bgr2 = cv.imread(img2)
r_m = 0.5 * (img_bgr1[:, :, 2] + img_bgr2[:, :, 2])
delta_rgb = np.square(img_bgr1- img_bgr2)
cols_diffs = delta_rgb[:, :, 2] * (2 + r_m / 256) + delta_rgb[:, :, 1] * (4) +
delta_rgb[:, :, 0] * (2 + (255 - r_m) / 256)
cols_diffs = np.sqrt(cols_diffs)
# lets normalized the values to range [0 , 1]
cols_diffs_min = np.min(cols_diffs)
cols_diffs_max = np.max(cols_diffs)
cols_diffs_normalized = (cols_diffs - cols_diffs_min) / (cols_diffs_max - cols_diffs_min)
return np.sqrt(cols_diffs_normalized)
答案 6 :(得分:0)
简单:
def eq_with_tolerance(a, b, t):
return a-t <= b <= a+t
def FindColorIn(r,g,b, xmin, xmax, ymin, ymax, tolerance=0):
image = ImageGrab.grab()
for x in range(xmin, xmax):
for y in range(ymin,ymax):
px = image.getpixel((x, y))
if eq_with_tolerance(r, px[0], tolerance) and eq_with_tolerance(g, px[1], tolerance) and eq_with_tolerance(b, px[2], tolerance):
return x, y
答案 7 :(得分:0)
来自pyautogui source code
def pixelMatchesColor(x, y, expectedRGBColor, tolerance=0):
r, g, b = screenshot().getpixel((x, y))
exR, exG, exB = expectedRGBColor
return (abs(r - exR) <= tolerance) and (abs(g - exG) <= tolerance) and (abs(b - exB) <= tolerance)
你只需要一点修理,你就可以准备好了。
答案 8 :(得分:0)
这是一个简单的函数,不需要任何库:
def color_distance(rgb1, rgb2):
rm = 0.5 * (rgb1[0] + rgb2[0])
rd = ((2 + rm) * (rgb1[0] - rgb2[0])) ** 2
gd = (4 * (rgb1[1] - rgb2[1])) ** 2
bd = ((3 - rm) * (rgb1[2] - rgb2[2])) ** 2
return (rd + gd + bd) ** 0.5
假设rgb1和rgb2是RBG元组