2012-01-14 8 views
6

私は画像内で色を見つけてx、yを返す関数を作った。今私は新しい関数を追加する必要があります。ここでは、与えられたtolerenceで色を見つけることができます。簡単でしょうか?Python - 類似の色を見つける、最良の方法

コード画像の色を見つけ、そして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 

結果:2つの色を比較する通常の方法は、ユークリッド距離にある回答から撮影

、チェビシェフ距離。

私は主にユークリッド距離と複数の異なる色空間を使用することに決めました。 LAB、デルタE(LCH)、XYZ、HSL、およびRGB。私のコードでは、ほとんどの色空間は、その差を計算するために二乗ユークリッド距離を使用します。

たとえば、LAB、RGB、およびXYZでは、単純な2乗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)の上に作成された色空間は、私のシナリオの多くで最もよく機能するようです。 Tho HSLは、いくつかのケースで非常に良い結果をもたらし、RGBから変換する方がはるかに安く、RGBも素晴らしいですし、私のニーズの大部分を占めています。単純

+0

画像で色が見つからない場合は、何かを返す必要があります。すなわち、エラーコード。 –

+0

どのように耐性を定義していますか? 'r'、' g'、 'b'の区切りは? –

+0

私はジョンと一緒です:何を試しましたか? [コサイン類似度](https://en.wikipedia.org/wiki/Cosine_similarity)を見て、Pythonの実装を探してみてください。 –

答えて

17

2つのRGBベクトル間のユークリッド距離をとるだけで、目に意味のある方法でRGBカラー間の距離を計算するのは簡単ではありません。

これについて興味深い記事がここにあります:Cでhttp://www.compuphase.com/cmetric.htm

実装例はこれです:

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のポートにあまりにも難しいことではありません。

EDIT:

また、this answerで提案されているように、あなたはHLS and HSVを使用することができます。 colorsysモジュールには、RGBから変換する機能があるようです。その文書はまた、RGBユークリッド距離が実際に動作しない理由を理解するために読む価値があるこれらのページへのリンク:

EDIT 2:

this answerによれば、このライブラリは有用であるはずです:http://code.google.com/p/python-colormath/

+0

最適化された 'Python'バージョンの私の答えを見てください。 – Developer

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 
2

そのRTOL、gtolを仮定し、R、G、Bの公差がない理由を、それぞれbtolある:これに代え

if abs(px[0]- r) <= rtol and \ 
    abs(px[1]- g) <= gtol and \ 
    abs(px[2]- b) <= btol: 
    return x, y 
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は、いずれかのカラーチャネルで受け入れる最大の差です。

これは、ターゲット値から各チャネルを減算し、絶対値をとり、次にそれらの最大値を取ることです。

+0

'import operator'。 –

+0

@SLACKY、最初に 'import operator'を呼び出す必要があります。これはユークリッド距離の式です。 – Bruno

+0

@ブリュノ:私のメトリックはユークリッド距離よりもさらに悪いです!私はその部分に重点を置いていませんでした(しかし、あなたの答えをアップアップしました)。許容誤差が小さい場合は問題ではありませんが、許容誤差が大きい場合はおそらく重要です。 –

2

はここブルーノのasnwerから適応最適化Pythonバージョンです:

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 

使用:あなたは少しだけを必要とする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) 

pyautoguiから

>>> import numpy 
>>> rgb1 = numpy.array([1,1,0]) 
>>> rgb2 = numpy.array([0,0,0]) 
>>> ColorDistance(rgb1,rgb2) 
2.5495097567963922 
+0

私が見たことから、 'x ** 0.5'は' from math import sqrt'よりもはるかに遅く、 'sqrt(x)'を使います。しかし、もしあなたが 'math'をimportして' math.sqrt(x) 'を使うと、ほとんどまたは全く違いは見られません。 – JHolta

+0

'(35,255,24)' vs '(38,38,120)'は 'nan'を返します –

0

修正して、あなたは行く準備が整いました。

関連する問題