Skip to content

Keep achromatic HSL gradients finite - #132

Open
sylvesterkaczmarek wants to merge 2 commits into
google-deepmind:masterfrom
sylvesterkaczmarek:fix/achromatic-hsl-gradients
Open

sylvesterkaczmarek wants to merge 2 commits into
google-deepmind:masterfrom
sylvesterkaczmarek:fix/achromatic-hsl-gradients

Conversation

@sylvesterkaczmarek

@sylvesterkaczmarek sylvesterkaczmarek commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Problem

rgb_to_hsl masks achromatic hue/saturation outputs after dividing by the zero colour range. The forward value for a grey pixel is correct, but reverse differentiation produces NaNs, including in the lightness component. Low-precision black/white pixels also need a safe denominator for the inactive saturation branch.

Change

Replace inactive denominators before division, preserving the existing achromatic output branches and chromatic formula. This follows the JAX guidance on masked undefined operations.

Validation

  • Earlier full colour-conversion run: 171 passed, 40 skipped (JAX 0.7.0, TensorFlow 2.20.0).
  • Current rebased head: 9 HSL regressions and 20 adjacent conversion tests passed; 5 skipped (JAX 0.12.0, TensorFlow 2.21.0). Tests now live in dm_pix/_src/color_conversion_test.py. Unchanged production code fails eight cases and passes the chromatic finite-difference control.
  • Coverage includes black/grey/white, float16/bfloat16/float32, eager/JIT execution, forward/reverse differentiation along the greyscale path, mixed images, and chromatic gradients compared with independent colorsys finite differences.
  • Python syntax and git diff --check pass on the current head.

Hue is mathematically undefined on the achromatic axis. The tests preserve the existing constant hue/saturation branches and verify the lightness derivative along the greyscale path; they do not assert a unique full colour-space derivative there.

Python 3.12.14 on macOS arm64 CPU. GPU/TPU and the complete image-processing suite were not run. Channel-axis handling in #125 is separate and unchanged. No epsilon, colour convention, dependency, or public API changes.

Reproduced against ffb65074b39b67e1a686d1348f2d461c7ff3ab45.

Comment thread dm_pix/_src/hsl_gradients_test.py Outdated
import numpy as np


class HslGradientsTest(parameterized.TestCase):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move these tests under color_conversion_test.py. We already have a color transformation test, so you can put them there, thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the tests into color_conversion_test.py. All 9 new cases and 20 adjacent tests pass on current master.

Comment thread dm_pix/_src/hsl_gradients_test.py Outdated
np.testing.assert_array_equal(grey(x), np.array([0.0, 0.0, level]))
np.testing.assert_allclose(reverse(x), [0.0, 0.0, 1.0], atol=1e-3)
np.testing.assert_allclose(forward(x), [0.0, 0.0, 1.0], atol=1e-3)
jacobian = jax.jacrev(color_conversion.rgb_to_hsl)(jnp.repeat(x[None], 3))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-prepare this outside the loop, so we can clearly see an arrange, act, and assert pattern in each test. Check this also for other tests too, thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RGB Jacobian and its JIT wrapper are now prepared once before the greyscale-level loop.

Signed-off-by: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com>
@sylvesterkaczmarek
sylvesterkaczmarek force-pushed the fix/achromatic-hsl-gradients branch from 378e83c to 52a5c62 Compare October 19, 2026 15:50

@claudiofantacci claudiofantacci left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@claudiofantacci claudiofantacci added the bug Something isn't working label Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants