Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in deltaEJz? yellows and blues strangly close together #89

Closed
micgro42 opened this issue Apr 16, 2021 · 6 comments · Fixed by #90
Closed

Bug in deltaEJz? yellows and blues strangly close together #89

micgro42 opened this issue Apr 16, 2021 · 6 comments · Fixed by #90

Comments

@micgro42
Copy link
Contributor

I noticed that for the deltaEJz algorithm, the yellows and blues are strangely close together. E.g., goldenrod is apparently closer to blues like cornflowerblue or royalblue than to peru or khaki? That seems ... unintuitive.

The other color functions seem to agree that the yellows should be much closer to each other than to the blues.

For your convenience, I have created this comparison of color distances between yellows and blues and different distance functions. It works really nicely when copied into one of your incredibly useful notebooks:

let goldenrod = new Color("goldenrod");

let cornflowerblue = new Color("cornflowerblue");
let royalblue = new Color("royalblue");
let slateblue = new Color("slateblue");
let peru = new Color("peru");
let khaki = new Color("khaki");
let darkorange = new Color("darkorange");


goldenrod.deltaEJz(cornflowerblue);
goldenrod.deltaEJz(royalblue);
goldenrod.deltaEJz(slateblue);
goldenrod.deltaEJz(peru);
goldenrod.deltaEJz(khaki);
goldenrod.deltaEJz(darkorange);

goldenrod.deltaE76(cornflowerblue);
goldenrod.deltaE76(royalblue);
goldenrod.deltaE76(slateblue);
goldenrod.deltaE76(peru);
goldenrod.deltaE76(khaki);
goldenrod.deltaE76(darkorange);

goldenrod.deltaE2000(cornflowerblue);
goldenrod.deltaE2000(royalblue);
goldenrod.deltaE2000(slateblue);
goldenrod.deltaE2000(peru);
goldenrod.deltaE2000(khaki);
goldenrod.deltaE2000(darkorange);

goldenrod.deltaECMC(cornflowerblue);
goldenrod.deltaECMC(royalblue);
goldenrod.deltaECMC(slateblue);
goldenrod.deltaECMC(peru);
goldenrod.deltaECMC(khaki);
goldenrod.deltaECMC(darkorange);

goldenrod.deltaEITP(cornflowerblue);
goldenrod.deltaEITP(royalblue);
goldenrod.deltaEITP(slateblue);
goldenrod.deltaEITP(peru);
goldenrod.deltaEITP(khaki);
goldenrod.deltaEITP(darkorange);

However, I really don't have a clue about colors at all, let alone color space and not to mention distance functions in those spaces. So it might very well be that this is the way it is supposed to be for that deltaEJz distance function, in which case I'm very sorry for the noise 😔.

@facelessuser
Copy link
Collaborator

I recently implemented Jzazbz in my own project and personally skipped implementing deltaEJz.

I see nothing wrong with color.js's implementation of detlaEJz. What you are seeing, I saw as well, and I imagine anyone who implements it would see the same. I looked over the spec when implementing it, which you can find here. You can compare the algorithm with Colorjs.io's implementation, but it seems to do everything correctly as far as I can tell. The only difference is maybe some NaN handling logic in the delta function, but none of that would affect the comparisons you are performing.

Personally, I think this is just the way the deltaEJz algorithm works. Or more correctly, how it works with the Jzazbz space. Whether it is a useful distancing method, I guess, is up to you to decide 🙂.

@svgeesus
Copy link
Member

svgeesus commented May 3, 2021

Thanks for the report, which is here as a notebook.

Firstly, deltaEJz values are incredibly small (so are deltaEITP, but our implementation adds the recommended 720x scaling; and so are deltaEOK). I suggested here that a scaling of 400 would be appropriate for deltaEJz when comparing to other metrics, but that was not an in-depth examination.

But that doesn't explain the strange and apparently non-perceptual differences that you are seeing. Unfortunately deltaEJz is relatively little tested in the literature.

@danburzo
Copy link

danburzo commented May 3, 2021

There might be a small error in dH, shouldn't that be Math.sin(dh / 2) in the formula? Also, if I remember correctly, this way of factoring in the Hue channel should make deltaEJz equivalent to the Euclidean distance in Jzazbz coordinates, so a comparison might help pinpoint if the problem is in the delta code or something intrinsic to the color space. (I'm writing from my phone so unfortunately I can't look into it)

@facelessuser
Copy link
Collaborator

Oh, wow...I must have made a very similar mistake. I like to implement directly from the spec and then compare against other implementations. I went over the spec multiple times and not only made the same mistake but couldn't see it after comparing and re-comparing the math 🤦🏻.

So I adjusted color.js to use Math.sin(dh / 2) opposed to Math.sin(dh) , and sure enough, it clears up the issue:

> goldenrod.deltaEJz(peru)
0.037482866533877626
> goldenrod.deltaEJz(cornflowerblue)
0.20345942022978947

@facelessuser
Copy link
Collaborator

Nope, I didn't make the same mistake: facelessuser/coloraide@d901c52#diff-8b70d5b88994afe5d248c27f39727317986e8e92c6472a3a7f62ffc32b621c65R305. Maybe, my eyes just got confused with decimal points and thought the values were off. I guess I'll have to go back and test my old implementation again.

Regardless, it looks like fixing the things in color.js gives more sane results.

@facelessuser
Copy link
Collaborator

facelessuser commented May 3, 2021

Yeah, I can confirm similar results. My brain must have filtered out the leading zero and thought peru was bigger 🤦🏻 🤦🏻.

Screen Shot 2021-05-03 at 2 24 33 PM

I'll code up a pull for color.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants