If color1 withing 'fuzz' of color2

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
User avatar
GreenKoopa
Posts: 457
Joined: 2010-11-04T17:24:08-07:00
Authentication code: 8675308

Re: If color1 withing 'fuzz' of color2

Post by GreenKoopa »

fmw42 wrote: I have my doubts about the use of a cone for rgb even with transparency.

My thoughts are that one just computes normalized euclidean distances.
What is the fuzzy distance between a black and a white pixel with:
* no transparency
* half transparency
* full transparency
The euclidean distance between is constant for these three, right? But as transparency increases, the colors matter less (until full transparency where they matter none). This makes transparency different from the other channels. Put another way: At an extreme value of blue, the value of red still matters. At an extreme value of alpha, the value of red can stop being relevant. This is the triangle shape transparency causes.

Of course the 'distance' between colors all depends on your definition set to meet you need. This is why I asked for examples in a 1-dimensional space; to help me understand the definition and need you two are discussing.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: If color1 withing 'fuzz' of color2

Post by fmw42 »

I don't really know how IM actually computes it. It appears that it multiplies the alpha value times the color value and then computes the normalized euclidean distance. That is what I read from the code. But don't read code very well. That way when the alpha value is opaque (ie. 1), you get the same result as with no alpha. And when alpha is transparent (ie. 0) you get no difference (zero for the euclidean distance). That is my current hypothesis.

So using euclidean distances (applicable to rgb and probably cmyk because the color coordinate systems are orthogonal --- unlike HSL and HSB), I get:

For both transparent (alpha=0):
echo $(convert -size 1x1 xc:"rgba(0,0,128,0)" xc:"rgba(0,0,255,0)" -channel rgba -alpha on -format \
"%[fx:(100)*sqrt(((u.r*u.a-v.r*v.a)^2+(u.g*u.a-v.g*v.a)^2+(u.b*u.a-v.b*v.a)^2)/3)]%%" info:) |\
cut -d" " -f1
0%

and

For both with alpha=0.5
echo $(convert -size 1x1 xc:"rgba(0,0,128,0.5)" xc:"rgba(0,0,255,0.5)" -channel rgba -alpha on -format \
"%[fx:(100)*sqrt(((u.r*u.a-v.r*v.a)^2+(u.g*u.a-v.g*v.a)^2+(u.b*u.a-v.b*v.a)^2)/3)]%%" info:) |\
cut -d" " -f1
14.3772%

and

For both opaque (alpha=1)


echo $(convert -size 1x1 xc:"rgba(0,0,128,1)" xc:"rgba(0,0,255,1)" -channel rgba -alpha on -format \
"%[fx:(100)*sqrt(((u.r*u.a-v.r*v.a)^2+(u.g*u.a-v.g*v.a)^2+(u.b*u.a-v.b*v.a)^2)/3)]%%" info:) |\
cut -d" " -f1
28.7543%

So to confirm the alpha=0.5 case:


convert xc:"rgba(0,0,128,0.5)" -channel rgba -alpha on -fuzz 14% -fill "rgba(0,0,255,0.5)" -opaque "rgba(0,0,255,0.5)" txt:
# ImageMagick pixel enumeration: 1,1,65535,rgba
0,0: ( 0, 0,32896,32768) #0000000080808000 rgba(0%,0%,50.1961%,0.5)

convert xc:"rgba(0,0,128,0.5)" -channel rgba -alpha on -fuzz 15% -fill "rgba(0,0,255,0.5)" -opaque "rgba(0,0,255,0.5)" txt:
# ImageMagick pixel enumeration: 1,1,65535,rgba
0,0: ( 0, 0,65535,32768) #00000000FFFF8000 rgba(0%,0%,100%,0.5)

Which seems to confirm that the the fuzz value is between 14% and 15% as my method above.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

fmw42 wrote:
multiply each rgb component by the alpha value before computing euclidean distance

(u.r*u.a-v.r*v.a)^2 etc

I don't think it is a cone (that is for HSL and HSB)!
The above is basically what FUZZ does now. Each color is multiplied by the alpha channel, and then a euclidean (spherical or Pythagorean distance) is calculated.

This ensures that as colors become more transparent the colors become closer together.

This is close to what we want. That is any fully-transparent color to mapping to zero distance.

The strange thing is, it isn't really a cone. Take these three RGBA colors...
None or #0000 (fully-transparent-black)
#FFF0 (fully-transparent-white)
black
white

As it stands using the current fuzz-color-compare function, None and #FFF0 are zero distance
as all distances are reduced to zero by the formula.

The problem with the current 'fuzz factor' is that the distance between none and black
is ZERO. It probably should be the same distance as none and white (in a 4 dimensional space)

convert xc:none xc:black -format "%[fx:(100)*sqrt(((u.r*u.a-v.r*v.a)^2+(u.g*u.a-v.g*v.a)^2+(u.b*u.a-v.b*v.a)^2)/3)]%%" info:
0%
0%

convert xc:none xc:white -format "%[fx:(100)*sqrt(((u.r*u.a-v.r*v.a)^2+(u.g*u.a-v.g*v.a)^2+(u.b*u.a-v.b*v.a)^2)/3)]%%" info:
100%
100%

This is the current problem with the current fuzz factor.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

fmw42 wrote:I have my doubts about the use of a cone for rgb even with transparency.
Well thinking about it, it isn't a a 4-D cone with a sphere at the top. It should be a 4-D cone with a RGB cube at the top. The problem is that that is not what Fuzz Factor uses (via the IsColorSimilar() function)

This function as you determined just multiplied all colors by the alpha value. but going that just shrinks all transparent colors toward a 'black' color. As such 'None' = 'Black' !

What we need is for the shrinkage to be such that all opaque colors are (as near as posible) equi-distant from 'None' (and all transparent colors are equivelent).

The question is how should color distance be calculated when alpha is included!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

GreenKoopa wrote:What is the fuzzy distance between a black and a white pixel with:
* no transparency
0%
* half transparency
50%
* full transparency
100%
Where 100% is by definition the distance from black to white!
The euclidean distance between is constant for these three, right?
Nope it isn't. if two colors are fully-transparent they should be the same color!

(ASIDE. at this time 'compare' does it this way)

The problem is not the distance between two colors of the same transparency, but two colors with different transparency level.

At this time transparent to Black is 0%
while transparent to white is 100%
And that is obviously not right!
Black is definitely not transparent, and should have about the same distance to transparency as white.

BUT we still need to make it so that two transparent colors should be the same (zero distance).

Hmmm what about something like...

Code: Select all

       sqrt(  ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.g-v.g)^2 ) * u.a * v.a /3
                         + (u.a-v.a)^2
                      )
In summery...
If colors are opaque you get a RGB cube distance (u.a and v.a are both 1.0)
but as colors become transparent that 'cube distance' becomes less important.
If one of the colors is transparent the 'cube distance' become irrelenent,
and only the transparency distance is what counts.

This seems to be a 'cube' on a hyper(4D)-cone.

Hmmm..
convert xc:black xc:white -format "%[fx:100*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.g-v.g)^2)*u.a*v.a/3 + (u.a-v.a)^2)]%%" info: | head -1
100%
convert xc:none xc:black -format "%[fx:100*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.g-v.g)^2)*u.a*v.a/3 + (u.a-v.a)^2)]%%" info: | head -1
100%
convert xc:none xc:white -format "%[fx:100*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.g-v.g)^2)*u.a*v.a/3 + (u.a-v.a)^2)]%%" info: | head -1
100%

fully transparent black and white
convert xc:black xc:white -format "%[fx:100*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.g-v.g)^2)*u.a*v.a/3 + (u.a-v.a)^2)]%%" info: | head -1
convert xc:#0000 xc:#FFF0 -format "%[fx:100*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.g-v.g)^2)*u.a*v.a/3 + (u.a-v.a)^2)]%%" info: | head -1
0%

and half-transparent black and white
convert xc:#0008 xc:#FFF8 -format "%[fx:100*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.g-v.g)^2)*u.a*v.a/3 + (u.a-v.a)^2)]%%" info: | head -1
53.3333%
A little odd (previously this was 50%) but should be reasonably acceptable
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: If color1 withing 'fuzz' of color2

Post by fmw42 »

This seems to be a 'cube' on a hyper(4D)-cone.
For both transparent (alpha=0):
echo $(convert -size 1x1 xc:"rgba(0,0,128,0)" xc:"rgba(0,0,255,0)" -channel rgba -alpha on -format \
"%[fx:(100)*sqrt(((u.r*u.a-v.r*v.a)^2+(u.g*u.a-v.g*v.a)^2+(u.b*u.a-v.b*v.a)^2)/3)]%%" info:) |\
cut -d" " -f1
0%

There is no cone involved for my formula. It was simply a 4D hypercube and I am computing the Euclidean distance (normalized by the number of dimensions (not spherical distance, but similar to Pythagorean distance in more than 2 dimensions), so that it stays in the range of 0-1. It seemed to be what the isColorSimilar code was computing.

Code: Select all

sqrt(  ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.g-v.g)^2 ) * u.a * v.a /3
                         + (u.a-v.a)^2
                      )
I don't follow the rational for this -- it seems rather ad hoc and does not seem to correspond to isColorSimilar!

It may be close to what you might desire, but as you said above, what I am computing does seem to correspond to the current fuzz calculation. I thought that was the goal of the whole topic.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

fmw42 wrote:There is no cone involved for my formula. It was simply a 4D hypercube and I am computing the Euclidean distance (normalized by the number of dimensions (not spherical distance, but similar to Pythagorean distance in more than 2 dimensions), so that it stays in the range of 0-1. It seemed to be what the isColorSimilar code was computing.
anthony wrote:

Code: Select all

sqrt(  ( (u.r-v.r)^2 + (u.g-v.g)^2 + (u.g-v.g)^2 ) * u.a * v.a /3
                         + (u.a-v.a)^2
                      )
I don't follow the rational for this -- it seems rather ad hoc and does not seem to correspond to isColorSimilar!

It may be close to what you might desire, but as you said above, what I am computing does seem to correspond to the current fuzz calculation. I thought that was the goal of the whole topic.
Yes but it seems the current fuzz calculation is not correct!

Try your distance formula between Black and None. It comes out '0'.
That is because it is a 4-D Hypercube with a transparency and black as equivalent.

My formula treats all opaque colors the same when compared against any fully-transparent color.
That is the distance from none to Black is the same as None to White. or even None to Grey.


Going back to the original problem new solution
compare -fuzz 20% -metric AE xc:Navy xc:Blue null:
1
compare -fuzz 30% -metric AE xc:Navy xc:Blue null:
0
Remember 1 means the colors did not match (number of error pixels)
this should they Navy and Blue are between 20 and 30% different.

I have requested that "compare" be given a "Fuzz" metric to actually return the average fuzz factor distance, which is different to RMSE distance.

I tried this before but must have done something wrong as I came to the conclusion AE results was not fuzz thresholded.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: If color1 withing 'fuzz' of color2

Post by fmw42 »

My formula treats all opaque colors the same when compared against any fully-transparent color.
That is the distance from none to Black is the same as None to White. or even None to Grey.
Perhaps I still misunderstand. But if that is all you want, then go back to


echo $(convert -size 1x1 xc:"rgb(0,0,0,0)" xc:"rgb(0,0,0,1)" -format \
"%[fx:(100)*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.b-v.b)^2)/3)]%%" info:) |\
cut -d" " -f1
0%

which just ignores the alpha channel
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

fmw42 wrote:Perhaps I still misunderstand. But if that is all you want, then go back to ... which just ignores the alpha channel
Sorry, if I gave a false impression, we sort of wandered around a bit.

originally i was trying to find a way to determine is two colors were close to each other, according to a user specification. It was to be regardless of if the two colors was transparnet, semi-transparent or otherwise.

It was basically getting a script to apply something "is this color close to this given color and fuzz" but without limits. The colors may be transparent or the not.

However it does appear the 'fuzz' determination is not actually working quite right, with regards to transparency, though it is working better than the simple 'compare colors multiplied by transparency', which would have the colors Black and None as equivalent.

I shall have to try and pull out the fuzz factor formula. and see how it differs from the above.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: If color1 withing 'fuzz' of color2

Post by fmw42 »

I am still not sure what results you really would like to have when alpha is involved and both are not opaque. But what is wrong with just considering the alpha channel as one more color dimension, so that for rgba, one would simply have:

%[fx:(100)*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.b-v.b)^2+(u.a-v.a)^2)/4)]%%"

and when no alpha or alpha=1 for both

%[fx:(100)*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.b-v.b)^2)/3)]%%"

Can you explain what you think you need by way of examples for cases where both rgb values are different (say for black and white or some other simple change of one of the rgb components) for alpha cases of:

1) both alpha=0
2) both alpha=5
3) one alpha=0, and one alpha=1
4) non-zero and non-unity alpha for both

Also consider the effects of changing the fuzz computation regarding backward compatibility. It is such a commonly used thing that many scripts will change.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

fmw42 wrote:I am still not sure what results you really would like to have when alpha is involved and both are not opaque. But what is wrong with just considering the alpha channel as one more color dimension, so that for rgba, one would simply have:

%[fx:(100)*sqrt(((u.r-v.r)^2+(u.g-v.g)^2+(u.b-v.b)^2+(u.a-v.a)^2)/4)]%%"
The problem with that is two different fully transparent colors will NOT be classed as being the same. They are both transparent so they should be considered to have zero distance.
Also the scale is wrong as 100% should be the distance from black to white.

With the alternative method (multiply colors by alpha)...
%[fx:(100)*sqrt(((u.r*u.a-v.r*v.a)^2+(u.g*u.a-v.g*v.a)^2+(u.b*u.a-v.b*v.a)^2)/3)]%%"
This thinks Black and transparent are the same thing! That is Black == None
Can you explain what you think you need by way of examples for cases where both rgb values are different (say for black and white or some other simple change of one of the rgb components) for alpha cases of:
1) both alpha=0
Colors should have zero distance -- all transparent colors are the same

2) both alpha=5
Assuming you me 0.5 colors have some distance but are closer than their fully opaque counterparts.

3) one alpha=0, and one alpha=1
Any opaque color should be different to any transparent color.
Better still all opaque colors should be the same distance from any transparent color

4) non-zero and non-unity alpha for both
The closer the alpha values the closer the color, but it should only reach zero if either
they both become fully transparent, or they are both the same color.
More transparent colors should be closer together than less transparent colors.

5) both alpha=1
color distance should reflect the color space (EG: RGB or CMY color cubes, or HSL cones etc)

Also consider the effects of changing the fuzz computation regarding backward compatibility. It is such a commonly used thing that many scripts will change.
opaque color handling is correct, it must remain correct. But transparency handling is not
quite correct!

Hmmm
Download the colorwheel....

Code: Select all

     wget http://www.imagemagick.org/Usage/images/colorwheel.png
Now run this whcih compares the opaque colors with a color 'none' (fully transparent black)

Code: Select all

     convert colorwheel.png -alpha set -channel RGBA \
                 -fuzz 80% -fill none -opaque none show:
The result shows that darker (near black) colors are 'closer' than 80% of fully transparent black
(none). If you repeat with 50% you will see that all opaque colors are further than 50%
try it again with fully-transparent white!

Code: Select all

        convert colorwheel.png -alpha set -channel RGBA \
                 -fuzz 80% -fill '#FFF0' -opaque '#FFF0' show:
Again opaque black colors are closer to fully-transparent white than white is!

Note that black and none are not zero distance (somewhere between 50 and 80%,
And we do know that 'fuzz' does consider all fully-transparent colors to be the same.

In other words the current fuzz model does handle ALL points. But it does not make all opaque colors the same distance from none. It is ALMOST right, but not quite right, but only with respect to alpha handling.

The question is then, should we correct that last 'inconsistancy'.
That is transparent and black is closer than transparent and white?

I have noted this problem in
http://www.imagemagick.org/Usage/bugs/fuzz_distance/
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: If color1 withing 'fuzz' of color2

Post by fmw42 »

The question is then, should we correct that last 'inconsistancy'.
That is transparent and black is closer than transparent and white?
Seems to me that transparent black should be closer to black than transparent black is to white.

rgba(0,0,0,0) should be closer to rgb(0,0,0)=rgba(0,0,0,1) than rgba(0,0,0,0) is to rgb(1,1,1) or rgba(1,1,1,1)

Perhaps I misunderstand to you mean that transparent black should be the same distance from black as transparent white it to white?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

As 'fuzz' stands ALL transparent colors are about 58% distant from black
and about 112% distant from white!

That does not seem very good at all. To my thinking either....

* All opaque colors should be equi-distant from full-transparency

or

* transparent-black to black should be the same distance as transparent white to white

neither is true, and my preference would be for the first to be true.


My formula will make any transparent to any opaque (regardless of color) 100% distant
and any transparent to any other transparent 0%.

It only chnages transparency distances. Distances to colors of about the same transparency should remain about the same

EG: half-transparent black to half-transparent white is currently 50%
in my formula that distance would be 58% whcih is pretty similar, and should not effect things to much.

Mostly it just equalises transparent to opaque distances.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: If color1 withing 'fuzz' of color2

Post by anthony »

I am looking at IsColorSimilar() and I can't see how it is getting the results I am seeing!

From what I can see it should result in the none to black color distance as being zero!
And yet plainly that is not the results I am seeing!

on the other hand IsMagickColorSimilar() seems to work on a formula I predicted.

I'll have to look at what functions use the two different sub-routines.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply