Hello,
I was having some trouble using pixelsearch, it was taking too long (3070) ms per search where I needed to do 10s of comparisons this was starting to add up.
I began rewriting the same script using pixelcolorget, however, I found I would expect, for example, white (FFFFFF) and would get FFFFFE or FFFCFF or similar due to some variation in 3d rendering or something and my if statement would not match.
Pixelsearch has a very useful Variation option that solves this problem but I could not find any similar functionality to compare colors outside of that function.
This is what I wrote to solve the problem. Thanks to several other threads here where I borrowed ideas from.
Please let me know if this is helpful, if anyone has any suggestions, or is aware of something that already exists that does this better, as I could not find it.
Execute the function like so and get_variance will break the color into its R,G,B components, take the absolute value of the difference and add them together. In this case the variance is 3.
hexWhite := 0xFFFFFF
foundcolor : = 0xFEFEFE
get_variance(hexWhite, foundcolor)
Again, let me know if anyone has any suggestions.
Script to determine how close colors are together
Script to determine how close colors are together
 Attachments

 get_variance.ahk
 (920 Bytes) Downloaded 163 times

 gv_example.ahk
 (1.9 KiB) Downloaded 128 times
Re: Script to determine how close colors are together
I don't think ImageSearch checks the sum of the difference of each shade.
If two colors are percieved as similar I think they are close in each color shade. Eg. 150 150 150 is percived as close to 160 160 160 but less to 150 150 180, but the "variance" is the same.
(Left: 150 150 150, Middle: 160 160 160, Right: 150 150 180)
If two colors are percieved as similar I think they are close in each color shade. Eg. 150 150 150 is percived as close to 160 160 160 but less to 150 150 180, but the "variance" is the same.
(Left: 150 150 150, Middle: 160 160 160, Right: 150 150 180)
Re: Script to determine how close colors are together
great point Helgef. I looked over the AHK source code and I believe I found in script2.cpp what pixelsearch is doing in terms of variance/variation and it appears to be, indeed, calculating the variation for r, g, b each individually.
The simplest solution to make variance in my function more similar to variation in pixelsearch would be to determine which is the highest of Absrdiff , Absgdiff , Absbdiff and report that as the variance. However that would not distinguish between 150,150, 170 and 170,170,170. Which are also as different as 1 and 2 are from 3 in the example colors you posted. That said, based on your feedback I am a bit concerned by how close 1 and 2 are in your example while still having a variance of 30! Though so far get_variance.ahk is working great for my use case, I think will for now change it as described but think of a way to implement some kind of weight.
Thanks for the feedback.
Code: Select all
script2.cpp: //BYTE red_low1 = (aVariation > search_red1) ? 0 : search_red1  aVariation;
script2.cpp: //BYTE green_low1 = (aVariation > search_green1) ? 0 : search_green1  aVariation;
script2.cpp: //BYTE blue_low1 = (aVariation > search_blue1) ? 0 : search_blue1  aVariation;
script2.cpp: //BYTE red_high1 = (aVariation > 0xFF  search_red1) ? 0xFF : search_red1 + aVariation;
script2.cpp: //BYTE green_high1 = (aVariation > 0xFF  search_green1) ? 0xFF : search_green1 + aVariation;
script2.cpp: //BYTE blue_high1 = (aVariation > 0xFF  search_blue1) ? 0xFF : search_blue1 + aVariation;
script.h: ResultType PixelSearch(int aLeft, int aTop, int aRight, int aBottom, COLORREF aColorBGR, int aVariation
Thanks for the feedback.
Re: Script to determine how close colors are together
What is the best measure is of course dependent on the application, there could be other concerns than the percieved difference. You could have an option in your function, like,
Also, it's inefficient to do string operations on the hex representation of the color.
A good exercise could be to see if you can improve it, using
Code: Select all
get_var(colA,colB, option="Sum")
{
.
.
.
if (option="maximum")
return max(rDiff,gDiff,bDiff) ; Nonexistent function.
else
return rDiff+gDiff+gDiff
}
A good exercise could be to see if you can improve it, using
Code: Select all
r:=(col&0xFF0000) >> 16
g:=(col&0x00FF00) >> 8
b:=col&0x0000FF
; Where col is some color, eg, 0xabcdef
Spoiler
 Almost_there
 Posts: 404
 Joined: 30 Sep 2014, 10:32
Re: Script to determine how close colors are together
Hi. I would have seen the color values as a 3 dimensional vector. When there are two vectors, you could easilly calculate the difference between them:
[edit]
diff := Sqrt( Abs( (color1_r**2 + color1_g**2 + color1_b**2)  (color2_r**2 + color2_g**2 + color2_b**2) ) )
This is a wrong formula  it just gives the absolute difference between length of two vectors, not the distance between.
However it will be useful if the purpose is to compare brightness of two colors regardless to color value.
The appropriate formula is:
[/edit]
Without further adjustments it will give a maximum distance of approx 442 ( 255 x sqrt(3) ) between white to black.
The nice thing about this method is that the distance as numbers also will be true compared to most humans subjective perception of the color difference  in the means of low numbers are similar colors and high numbers are different colors
[edit]
This is a wrong formula  it just gives the absolute difference between length of two vectors, not the distance between.
However it will be useful if the purpose is to compare brightness of two colors regardless to color value.
The appropriate formula is:
Code: Select all
diff := Sqrt( (color1_r  color2_r)**2 + (color1_g  color2_g)**2 + (color1_b  color2_b)**2 )
Without further adjustments it will give a maximum distance of approx 442 ( 255 x sqrt(3) ) between white to black.
The nice thing about this method is that the distance as numbers also will be true compared to most humans subjective perception of the color difference  in the means of low numbers are similar colors and high numbers are different colors
Last edited by Almost_there on 23 Jul 2016, 12:31, edited 2 times in total.
Re: Script to determine how close colors are together
>> sqrt(abs((150^2+150^2+150^2)(150^2+150^2+180^2)))
ans =
99.4987
>> sqrt(abs((150^2+150^2+150^2)(160^2+160^2+160^2)))
ans =
96.4365
I'm not convinced mate, the colors are are vastly different to my eyes, but they score almost the same, compared to 150 150 150, on your scale.
Edit: I actually have two eyes
ans =
99.4987
>> sqrt(abs((150^2+150^2+150^2)(160^2+160^2+160^2)))
ans =
96.4365
I'm not convinced mate, the colors are are vastly different to my eyes, but they score almost the same, compared to 150 150 150, on your scale.
Edit: I actually have two eyes
 Almost_there
 Posts: 404
 Joined: 30 Sep 2014, 10:32
Re: Script to determine how close colors are together
Helgef
You can try again, I've corrected an math error.
You can try again, I've corrected an math error.
Re: Script to determine how close colors are together
Better for sure, but as mentioned, it depends on what you want to compare. And it's not hard to find an example where this measure doesn't say that much, with respect to percieved difference,
from left to right: A=[0 220 220], B= [50 250 250], C=[0 0 0], D=[66 0 0]
Imo, A and B are more similar to each other, than C and D are, but norm2(AB)~=norm2(CD)~=66. Where norm2() is Almost_there's function. So the question here is, what does a score of 66 give you? The difference between turqoise and slightly darker turqoise, but also the difference between black and dark red wine.
The problem is that the norm2 is not invertible, so we lose information.
On a side note, the norm2 need to convert numbers to doubles, which should be a concern if comparing a lot of pixels, like in ImageSearch.
from left to right: A=[0 220 220], B= [50 250 250], C=[0 0 0], D=[66 0 0]
Imo, A and B are more similar to each other, than C and D are, but norm2(AB)~=norm2(CD)~=66. Where norm2() is Almost_there's function. So the question here is, what does a score of 66 give you? The difference between turqoise and slightly darker turqoise, but also the difference between black and dark red wine.
The problem is that the norm2 is not invertible, so we lose information.
On a side note, the norm2 need to convert numbers to doubles, which should be a concern if comparing a lot of pixels, like in ImageSearch.
 Almost_there
 Posts: 404
 Joined: 30 Sep 2014, 10:32
Re: Script to determine how close colors are together
Yes I see that the conversion may cause the script to run less efficiently.
I assume that the Sqrt() is one cause of this  I would like to see if there is a really effective way to solve this  is there a faster way to perform square root, that only deals with integers?
On the other hand  A faster way woult be:
That would be a number between 0 (same color) and 255x3=765 (black to white).
I assume that the Sqrt() is one cause of this  I would like to see if there is a really effective way to solve this  is there a faster way to perform square root, that only deals with integers?
On the other hand  A faster way woult be:
Code: Select all
diff := Abs(color1_r  color2_r) + Abs(color1_g  color2_g) + Abs(color1_b  color2_b)
Re: Script to determine how close colors are together
That code is exactly what was originally proposed by the author and it's the same as in the "Spoiler" in my previous post.Almost_there wrote:Yes I see that the conversion may cause the script to run less efficiently.
I assume that the Sqrt() is one cause of this  I would like to see if there is a really effective way to solve this  is there a faster way to perform square root, that only deals with integers?
On the other hand  A faster way woult be:That would be a number between 0 (same color) and 255x3=765 (black to white).Code: Select all
diff := Abs(color1_r  color2_r) + Abs(color1_g  color2_g) + Abs(color1_b  color2_b)
Yes, the square root is the cause, it goes ℤ+ > ℝ+.
Re: Script to determine how close colors are together
Here is an example of this same thing using bitshift.
Original by VxE, I condensed it into a single line.
Original by VxE, I condensed it into a single line.
Code: Select all
Distance(c1, c2)
{ ; function by [VxE], return value range = [0, 441.67295593006372]
return Sqrt((((c1>>16)(c2>>16))**2) + (((c1>>8&255)  (c2>>8&255))**2) + (((c1&255)(c1&255))**2))
}
Return to “Scripts and Functions”
Who is online
Users browsing this forum: No registered users and 29 guests