I made a function to find the color inside the image and return x, y. Now I need to add a new function where I can find a color with a certain degree of tolerance. Should it be easy?
Code for finding color in the image and returning 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
Result:
The usual methods for comparing two colors, taken from the answers, are located at Euclidean distance or Chebyshev distance.
I decided to mainly use the (square) Euclidean distance and several different color spaces. LAB, deltaE (LCH), XYZ, HSL and RGB. In my code, most color spaces use the squared Euclidean distance to calculate the difference.
For example, with LAB, RGB and XYZ a simple euc square. Distance does the trick:
if ((X-X1)^2 + (Y-Y1)^2 + (Z-Z1)^2) <= (Tol^2) then ...
LCH and HSL are a bit more complicated, since both have a cylindrical hue, but some parts of mathematics solve this and then use square eucl. here.
In most cases, I added “separate parameters” for the tolerance for each channel (using 1 global tolerance and alternative “modifiers” HueTol := Tolerance * hueMod or LightTol := Tolerance * LightMod ).
It seems that color spaces built on top of XYZ (LAB, LCH) work best in many of my scenarios. Tho HSL gives very good results in some cases, and it’s much cheaper to convert to RGB, RGB is also great for most of my needs.