Skip to content

Commit

Permalink
Add "colour.characterisation.optimisation_factory_Oklab_18" definition.
Browse files Browse the repository at this point in the history
  • Loading branch information
KelSolaar committed Apr 26, 2023
1 parent b6a66d0 commit 2c6ce87
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 9 deletions.
2 changes: 2 additions & 0 deletions colour/characterisation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
whitepoint_preserving_matrix,
optimisation_factory_rawtoaces_v1,
optimisation_factory_Jzazbz,
optimisation_factory_Oklab_18,
matrix_idt,
camera_RGB_to_ACES2065_1,
)
Expand Down Expand Up @@ -81,6 +82,7 @@
"whitepoint_preserving_matrix",
"optimisation_factory_rawtoaces_v1",
"optimisation_factory_Jzazbz",
"optimisation_factory_Oklab_18",
"matrix_idt",
"camera_RGB_to_ACES2065_1",
]
Expand Down
102 changes: 101 additions & 1 deletion colour/characterisation/aces_it.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- :func:`colour.characterisation.training_data_sds_to_XYZ`
- :func:`colour.characterisation.optimisation_factory_rawtoaces_v1`
- :func:`colour.characterisation.optimisation_factory_Jzazbz`
- :func:`colour.characterisation.optimisation_factory_Oklab_18`
- :func:`colour.matrix_idt`
- :func:`colour.camera_RGB_to_ACES2065_1`
Expand All @@ -24,6 +25,10 @@
M. (2017). RAW to ACES (Version 1.0) [Computer software].
- :cite:`Forsythe2018` : Borer, T. (2017). Private Discussion with Mansencal,
T. and Shaw, N.
- :cite:`Finlayson2015` : Finlayson, G. D., MacKiewicz, M., & Hurlbert, A.
(2015). Color Correction Using Root-Polynomial Regression. IEEE
Transactions on Image Processing, 24(5), 1460-1470.
doi:10.1109/TIP.2015.2405336
- :cite:`TheAcademyofMotionPictureArtsandSciences2014q` : The Academy of
Motion Picture Arts and Sciences, Science and Technology Council, & Academy
Color Encoding System (ACES) Project Subcommittee. (2014). Technical
Expand Down Expand Up @@ -75,6 +80,7 @@
from colour.characterisation import (
MSDS_ACES_RICD,
RGB_CameraSensitivities,
polynomial_expansion_Finlayson2015,
)
from colour.hints import (
ArrayLike,
Expand All @@ -90,6 +96,7 @@
from colour.models import (
XYZ_to_Jzazbz,
XYZ_to_Lab,
XYZ_to_Oklab,
XYZ_to_xy,
xy_to_XYZ,
)
Expand Down Expand Up @@ -138,6 +145,7 @@
"whitepoint_preserving_matrix",
"optimisation_factory_rawtoaces_v1",
"optimisation_factory_Jzazbz",
"optimisation_factory_Oklab_18",
"matrix_idt",
"camera_RGB_to_ACES2065_1",
]
Expand Down Expand Up @@ -803,7 +811,7 @@ def optimisation_factory_rawtoaces_v1() -> (
data *RGB* tristimulus values and the training data *CIE XYZ* tristimulus
values** in *CIE L\\*a\\*b\\** colourspace.
It also implements whitepoint preservation.
It implements whitepoint preservation as an optimisation constraint.
Returns
-------
Expand Down Expand Up @@ -925,6 +933,86 @@ def finaliser_function(M: NDArrayFloat) -> NDArrayFloat:
)


def optimisation_factory_Oklab_18() -> (
Tuple[NDArrayFloat, Callable, Callable, Callable]
):
"""
Produce the objective function and *CIE XYZ* colourspace to optimisation
colourspace/colour model function based on the *Oklab* colourspace.
The objective function returns the euclidean distance between the training
data *RGB* tristimulus values and the training data *CIE XYZ* tristimulus
values** in the *Oklab* colourspace.
It implements support for *Finlayson et al. (2015)* root-polynomials of
degree 2 and produces 18 terms.
Returns
-------
:class:`tuple`
:math:`x_0` initial values, objective function, *CIE XYZ* colourspace
to *Oklab* colourspace function and finaliser function.
References
----------
:cite:`Finlayson2015`
Examples
--------
>>> optimisation_factory_Oklab_18() # doctest: +SKIP
array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., \
1., 1., 1., 1., 1.]), \
<function optimisation_factory_Oklab_18.<locals>\
.objective_function at 0x...>, \
<function optimisation_factory_Oklab_18.<locals>\
.XYZ_to_optimization_colour_model at 0x...>, \
<function optimisation_factory_Oklab_18.<locals>.\
finaliser_function at 0x...>)
"""

x_0 = ones(18)

def objective_function(
M: ArrayLike, RGB: ArrayLike, Jab: ArrayLike
) -> NDArrayFloat:
"""*Oklab* colourspace based objective function."""

M = np.reshape(M, (3, 6))

XYZ_t = np.transpose(
np.dot(
RGB_COLOURSPACE_ACES2065_1.matrix_RGB_to_XYZ,
np.dot(
M,
np.transpose(
polynomial_expansion_Finlayson2015(RGB, 2, True)
),
),
)
)

Jab_t = XYZ_to_Oklab(XYZ_t)

return as_float(np.sum(euclidean_distance(Jab, Jab_t)))

def XYZ_to_optimization_colour_model(XYZ: ArrayLike) -> NDArrayFloat:
"""*CIE XYZ* colourspace to *Oklab* colourspace function."""

return XYZ_to_Oklab(XYZ)

def finaliser_function(M: NDArrayFloat) -> NDArrayFloat:
"""Finaliser function."""

return np.reshape(M, (3, 6))

return (
x_0,
objective_function,
XYZ_to_optimization_colour_model,
finaliser_function,
)


def matrix_idt(
sensitivities: RGB_CameraSensitivities,
illuminant: SpectralDistribution,
Expand Down Expand Up @@ -1031,6 +1119,18 @@ def matrix_idt(
[ 0.023, -0.225, 1.196]])
>>> RGB_w # doctest: +ELLIPSIS
array([ 2.3414154..., 1. , 1.5163375...])
>>> M, RGB_w = matrix_idt(
... sensitivities,
... illuminant,
... optimisation_factory=optimisation_factory_Oklab_18,
... )
>>> np.around(M, 3)
array([[ 0.659, -0.556, 0.132, 0.69 , 0.332, -0.26 ],
[-0.137, 0.815, -0.045, 0.578, -0.1 , -0.119],
[-0.145, -0.3 , 1.448, 0.426, -0.426, -0.013]])
>>> RGB_w # doctest: +ELLIPSIS
array([ 2.3414154..., 1. , 1.5163375...])
"""

training_data = optional(training_data, read_training_data_rawtoaces_v1())
Expand Down
4 changes: 1 addition & 3 deletions colour/characterisation/correction.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,9 +740,7 @@ def matrix_colour_correction_Finlayson2015(
>>> prng = np.random.RandomState(2)
>>> M_T = prng.random_sample((24, 3))
>>> M_R = M_T + (prng.random_sample((24, 3)) - 0.5) * 0.5
>>> matrix_colour_correction_Finlayson2015(
... M_T, M_R, 2
... ) # doctest: +ELLIPSIS
>>> matrix_colour_correction_Finlayson2015(M_T, M_R) # doctest: +ELLIPSIS
array([[ 1.0526376..., 0.1378078..., -0.2276339...],
[ 0.0739584..., 1.0293994..., -0.1060115...],
[ 0.0572550..., -0.2052633..., 1.1015194...]])
Expand Down
72 changes: 67 additions & 5 deletions colour/characterisation/tests/test_aces_it.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
whitepoint_preserving_matrix,
optimisation_factory_rawtoaces_v1,
optimisation_factory_Jzazbz,
optimisation_factory_Oklab_18,
matrix_idt,
camera_RGB_to_ACES2065_1,
)
Expand Down Expand Up @@ -63,6 +64,7 @@
"TestWhitepointPreservingMatrix",
"TestOptimizationFactoryRawtoacesV1",
"TestOptimizationFactoryJzazbz",
"TestOptimizationFactoryOklab18",
"TestMatrixIdt",
"TestCamera_RGB_to_ACES2065_1",
]
Expand Down Expand Up @@ -941,7 +943,7 @@ def test_optimisation_factory_rawtoaces_v1(self):
optimisation_factory_rawtoaces_v1` definition.
"""

self.assertEqual(len(optimisation_factory_rawtoaces_v1()), 2)
self.assertEqual(len(optimisation_factory_rawtoaces_v1()), 4)


class TestOptimizationFactoryJzazbz(unittest.TestCase):
Expand All @@ -956,7 +958,22 @@ def test_optimisation_factory_Jzazbz(self):
optimisation_factory_Jzazbz` definition.
"""

self.assertEqual(len(optimisation_factory_Jzazbz()), 2)
self.assertEqual(len(optimisation_factory_Jzazbz()), 4)


class TestOptimizationFactoryOklab18(unittest.TestCase):
"""
Define :func:`colour.characterisation.aces_it.\
optimisation_factory_Oklab_18` definition unit tests methods.
"""

def test_optimisation_factory_Oklab_18(self):
"""
Test :func:`colour.characterisation.aces_it.\
optimisation_factory_Oklab_18` definition.
"""

self.assertEqual(len(optimisation_factory_Oklab_18()), 4)


class TestMatrixIdt(unittest.TestCase):
Expand Down Expand Up @@ -1033,6 +1050,50 @@ def test_matrix_idt(self):
rtol=0.0001,
atol=0.0001,
)
M, RGB_w = matrix_idt(
MSDS_CANON_EOS_5DMARK_II,
SDS_ILLUMINANTS["D55"],
optimisation_factory=optimisation_factory_Oklab_18,
)
np.testing.assert_allclose(
M,
np.array(
[
[
0.65857990,
-0.55646898,
0.13178280,
0.68969743,
0.33171300,
-0.25994351,
],
[
-0.13719710,
0.81519400,
-0.04501889,
0.57807948,
-0.09995071,
-0.11895455,
],
[
-0.14543552,
-0.30025758,
1.44781243,
0.42639300,
-0.42594640,
-0.01275006,
],
]
),
rtol=0.0001,
atol=0.0001,
)
np.testing.assert_allclose(
RGB_w,
np.array([2.34141541, 1.00000000, 1.51633759]),
rtol=0.0001,
atol=0.0001,
)

M, RGB_w = matrix_idt(
MSDS_CANON_EOS_5DMARK_II,
Expand All @@ -1043,9 +1104,9 @@ def test_matrix_idt(self):
M,
np.array(
[
[0.88338671, 0.00225383, 0.11435946],
[0.08296792, 1.13432355, -0.21729147],
[0.01504774, -0.15021542, 1.13516768],
[0.86504351, -0.02633990, 0.16129640],
[0.05659298, 1.12296533, -0.17955832],
[0.02370632, -0.20257926, 1.17887294],
]
),
rtol=0.0001,
Expand All @@ -1057,6 +1118,7 @@ def test_matrix_idt(self):
rtol=0.0001,
atol=0.0001,
)
return

training_data = sds_and_msds_to_msds(
SDS_COLOURCHECKERS["BabelColor Average"].values()
Expand Down
32 changes: 32 additions & 0 deletions colour/examples/characterisation/examples_aces_it.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os

import colour
import numpy as np
from colour.hints import cast
from colour.utilities import message_box

Expand Down Expand Up @@ -67,3 +68,34 @@
illuminant,
)
)

message_box(
'Optimising in "Oklab" colourspace using "Finlayson et al. (2015)" '
"root-polynomials colour correction:"
)

M, RGB_w = colour.matrix_idt( # pyright: ignore
cast(colour.characterisation.RGB_CameraSensitivities, sensitivities),
illuminant,
optimisation_factory=colour.characterisation.optimisation_factory_Oklab_18,
)

print((M, RGB_w))

RGB = np.random.random((48, 3))

print(
colour.utilities.vector_dot( # pyright: ignore
colour.models.RGB_COLOURSPACE_ACES2065_1.matrix_RGB_to_XYZ,
np.transpose(
np.dot(
M,
np.transpose(
colour.characterisation.polynomial_expansion_Finlayson2015(
RGB, 2, True
)
),
)
),
)
)
1 change: 1 addition & 0 deletions docs/colour.characterisation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ ACES Input Transform Computation
whitepoint_preserving_matrix
optimisation_factory_rawtoaces_v1
optimisation_factory_Jzazbz
optimisation_factory_Oklab_18

Colour Fitting
--------------
Expand Down

0 comments on commit 2c6ce87

Please sign in to comment.