Python - 找到相似的颜色,最好的方法

JHo*_*lta 13 python colors find

我已经创建了一个函数来查找图像中的颜色,并返回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
Run Code Online (Sandbox Code Playgroud)

结果:

从答案中得出,比较两种颜色的常规方法是欧几里德距离或切比雪夫距离.

我决定大多使用(平方)欧几里德距离和多个不同的颜色空间.LAB,deltaE(LCH),XYZ,HSL和RGB.在我的代码中,大多数颜色空间使用平方的欧氏距离来计算差异.

例如,LAB,RGB和XYZ是一个简单的平方euc.距离的诀窍是:

if ((X-X1)^2 + (Y-Y1)^2 + (Z-Z1)^2) <= (Tol^2) then
  ...
Run Code Online (Sandbox Code Playgroud)

LCH和HSL稍微复杂一点,因为它们都有圆柱形色调,但是有些数学解决了这个问题,那么它就是使用平方的eucl.这里也是.

在大多数情况下,我为每个通道添加了"单独的参数"(使用1个全局容差和替代"修饰符" HueTol := Tolerance * hueModLightTol := Tolerance * LightMod).


似乎在XYZ(LAB,LCH)之上构建的色彩空间在我的许多场景中表现最佳.在某些情况下,HSL会产生非常好的效果,而且转换为RGB要便宜得多,RGB也很棒,并且满足了我的大部分需求.

Bru*_*uno 21

以对眼睛有意义的方式计算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));
}
Run Code Online (Sandbox Code Playgroud)

移植到Python应该不会太困难.

编辑:

或者,如本回答所示,您可以使用HLS和HSV.该colorsys模块似乎具有从RGB进行转换的功能.它的文档也链接到这些页面,值得阅读,以了解为什么RGB Euclidian距离不起作用:

编辑2:

根据这个答案,这个库应该是有用的:http://code.google.com/p/python-colormath/


Dev*_*per 5

这是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
Run Code Online (Sandbox Code Playgroud)

用法:

>>> import numpy
>>> rgb1 = numpy.array([1,1,0])
>>> rgb2 = numpy.array([0,0,0])
>>> ColorDistance(rgb1,rgb2)
2.5495097567963922
Run Code Online (Sandbox Code Playgroud)

  • 这根本不起作用,我只是浪费了 30 分钟来调试它 (4认同)
  • `(35,255,24)` 与 `(38,38,120)` 返回 `nan` (2认同)