Skip to content

Commit

Permalink
Implement support for "Munish Ragoo and Farup (2021)" "Optimised IPT"…
Browse files Browse the repository at this point in the history
… Colourspace.
  • Loading branch information
KelSolaar committed May 26, 2022
1 parent ddc191c commit 24656e6
Show file tree
Hide file tree
Showing 12 changed files with 461 additions and 2 deletions.
13 changes: 13 additions & 0 deletions BIBLIOGRAPHY.bib
Original file line number Diff line number Diff line change
Expand Up @@ -2550,6 +2550,19 @@ @article{Morovic2000
keywords = {Cross-media reproduction,Gamut boundary
calculation,Gamut mapping},
}
@article{MunishRagoo2021,
title = {Optimising a {{Euclidean Colour Space Transform}}
for {{Colour Order}} and {{Perceptual Uniformity}}},
author = {Munish Ragoo, Luvin and Farup, Ivar},
year = 2021,
month = nov,
journal = {Color and Imaging Conference},
volume = 29,
number = 1,
pages = {282--287},
issn = {2166-9635},
doi = {10.2352/issn.2169-2629.2021.29.282},
}
@misc{MunsellColorScienceb,
title = {Macbeth {{Colorchecker}}},
author = {{Munsell Color Science}},
Expand Down
8 changes: 8 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,14 @@ IPT Colourspace
>>> colour.XYZ_to_IPT([0.20654008, 0.12197225, 0.05136952])
array([ 0.38426191, 0.38487306, 0.18886838])
Munish Ragoo and Farup (2021) Optimised IPT Colourspace
*******************************************************
.. code-block:: python
>>> colour.XYZ_to_IPT([0.20654008, 0.12197225, 0.05136952])
array([ 0.42248243, 0.2910514 , 0.20410663])
DIN99 Colourspace and DIN99b, DIN99c, DIN99d Refined Formulas
*************************************************************
Expand Down
4 changes: 4 additions & 0 deletions colour/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@
IgPgTg_to_XYZ,
IPT_hue_angle,
IPT_to_XYZ,
IPT_Munish2021_to_XYZ,
JMh_CAM16_to_CAM16LCD,
JMh_CAM16_to_CAM16SCD,
JMh_CAM16_to_CAM16UCS,
Expand Down Expand Up @@ -313,6 +314,7 @@
XYZ_to_ICtCp,
XYZ_to_IgPgTg,
XYZ_to_IPT,
XYZ_to_IPT_Munish2021,
XYZ_to_Jzazbz,
XYZ_to_K_ab_HunterLab1966,
XYZ_to_Lab,
Expand Down Expand Up @@ -665,6 +667,7 @@ def __getattr__(self, attribute) -> Any:
"IgPgTg_to_XYZ",
"IPT_hue_angle",
"IPT_to_XYZ",
"IPT_Munish2021_to_XYZ",
"JMh_CAM16_to_CAM16LCD",
"JMh_CAM16_to_CAM16SCD",
"JMh_CAM16_to_CAM16UCS",
Expand Down Expand Up @@ -725,6 +728,7 @@ def __getattr__(self, attribute) -> Any:
"XYZ_to_ICtCp",
"XYZ_to_IgPgTg",
"XYZ_to_IPT",
"XYZ_to_IPT_Munish2021",
"XYZ_to_Jzazbz",
"XYZ_to_K_ab_HunterLab1966",
"XYZ_to_Lab",
Expand Down
20 changes: 18 additions & 2 deletions colour/examples/models/examples_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@
)
print(colour.ICaCb_to_XYZ(ICaCb))

XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
message_box(
f'Converting to "IgPgTg" colourspace from given "CIE XYZ" tristimulus '
f"values:\n\n\t{XYZ}"
Expand All @@ -325,7 +324,6 @@

print("\n")

XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
message_box(
f'Converting to "IPT" colourspace from given "CIE XYZ" tristimulus '
f"values:\n\n\t{XYZ}"
Expand All @@ -343,6 +341,24 @@

print("\n")

message_box(
f'Converting to "Munish Ragoo and Farup (2021)" "Optimised IPT" '
f'colourspace from given "CIE XYZ" tristimulus values:\n\n\t{XYZ}'
)
print(colour.XYZ_to_IPT_Munish2021(XYZ))

print("\n")

IPT = np.array([0.42248243, 4.05710276, 0.20410663])
message_box(
f'Converting to "CIE XYZ" tristimulus values from given'
f'"Munish Ragoo and Farup (2021)" "Optimised IPT" colourspace '
f"values:\n\n\t{IPT}"
)
print(colour.IPT_Munish2021_to_XYZ(IPT))

print("\n")

message_box(
f'Converting to "hdr-CIELab" colourspace from given "CIE XYZ" tristimulus '
f"values:\n\n\t{XYZ}"
Expand Down
4 changes: 4 additions & 0 deletions colour/graph/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
IHLS_to_RGB,
IgPgTg_to_XYZ,
IPT_to_XYZ,
IPT_Munish2021_to_XYZ,
JMh_CAM16_to_CAM16LCD,
JMh_CAM16_to_CAM16SCD,
JMh_CAM16_to_CAM16UCS,
Expand Down Expand Up @@ -122,6 +123,7 @@
XYZ_to_ICtCp,
XYZ_to_IgPgTg,
XYZ_to_IPT,
XYZ_to_IPT_Munish2021,
XYZ_to_Jzazbz,
XYZ_to_Lab,
XYZ_to_Luv,
Expand Down Expand Up @@ -663,6 +665,8 @@ def RGB_luminance_to_RGB(Y: FloatingOrArrayLike) -> NDArray:
("IgPgTg", "CIE XYZ", IgPgTg_to_XYZ),
("CIE XYZ", "IPT", XYZ_to_IPT),
("IPT", "CIE XYZ", IPT_to_XYZ),
("CIE XYZ", "IPT Munish 2021", XYZ_to_IPT_Munish2021),
("IPT Munish 2021", "CIE XYZ", IPT_Munish2021_to_XYZ),
("CIE XYZ", "Jzazbz", XYZ_to_Jzazbz),
("Jzazbz", "CIE XYZ", Jzazbz_to_XYZ),
("CIE XYZ", "hdr-IPT", XYZ_to_hdr_IPT),
Expand Down
5 changes: 5 additions & 0 deletions colour/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
Izazbz_to_XYZ,
Jzazbz_to_XYZ,
)
from .munish2021 import XYZ_to_IPT_Munish2021, IPT_Munish2021_to_XYZ
from .hdr_ipt import HDR_IPT_METHODS, XYZ_to_hdr_IPT, hdr_IPT_to_XYZ
from .oklab import XYZ_to_Oklab, Oklab_to_XYZ
from .osa_ucs import XYZ_to_OSA_UCS, OSA_UCS_to_XYZ
Expand Down Expand Up @@ -452,6 +453,10 @@
"Izazbz_to_XYZ",
"Jzazbz_to_XYZ",
]
__all__ += [
"XYZ_to_IPT_Munish2021",
"IPT_Munish2021_to_XYZ",
]
__all__ += [
"HDR_IPT_METHODS",
"XYZ_to_hdr_IPT",
Expand Down
3 changes: 3 additions & 0 deletions colour/models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"ICaCb",
"ICtCp",
"IPT",
"IPT Munish 2021",
"IgPgTg",
"Jzazbz",
"OSA UCS",
Expand Down Expand Up @@ -110,6 +111,7 @@
"ICaCb": ("$I$", "$C_a$", "$C_b$"),
"ICtCp": ("$I$", "$C_T$", "$C_P$"),
"IPT": ("I", "P", "T"),
"IPT Munish 2021": ("I", "P", "T"),
"IgPgTg": ("$I_G$", "$P_G$", "$T_G$"),
"Jzazbz": ("$J_z$", "$a_z$", "$b_z$"),
"OSA UCS": ("L", "j", "g"),
Expand Down Expand Up @@ -145,6 +147,7 @@
"ICaCb": np.array([1, 1, 1]),
"ICtCp": np.array([1, 1, 1]),
"IPT": np.array([1, 1, 1]),
"IPT Munish 2021": np.array([1, 1, 1]),
"IgPgTg": np.array([1, 1, 1]),
"Jzazbz": np.array([1, 1, 1]),
"OSA UCS": np.array([100, 100, 100]),
Expand Down
179 changes: 179 additions & 0 deletions colour/models/munish2021.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
"""
Munish Ragoo and Farup (2021) Optimised IPT Colourspace
=======================================================
Defines the *Munish Ragoo and Farup (2021)* *Optimised IPT* colourspace
transformations:
- :func:`colour.XYZ_to_IPT_Munish2021`
- :func:`colour.IPT_Munish2021_to_XYZ`
References
----------
- :cite:`Munish2021` : Munish Ragoo, L., & Farup, I. (2021). Optimising
a Euclidean Colour Space Transform for Colour Order and Perceptual
Uniformity. Color and Imaging Conference, 29(1), 282-287.
doi:10.2352/issn.2169-2629.2021.29.282
"""

from __future__ import annotations

import numpy as np
from functools import partial

from colour.algebra import spow
from colour.models import Iab_to_XYZ, XYZ_to_Iab
from colour.hints import ArrayLike, NDArray

__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "colour-developers@colour-science.org"
__status__ = "Production"

__all__ = [
"MATRIX_IPT_XYZ_TO_LMS",
"MATRIX_IPT_LMS_TO_XYZ",
"MATRIX_IPT_LMS_P_TO_IPT",
"MATRIX_IPT_IPT_TO_LMS_P",
"XYZ_to_IPT_Munish2021",
"IPT_Munish2021_to_XYZ",
]

MATRIX_IPT_XYZ_TO_LMS: NDArray = np.array(
[
[0.4321, 0.6906, -0.0930],
[-0.1793, 1.1458, 0.0226],
[0.0631, 0.1532, 0.7226],
]
)
"""*CIE XYZ* tristimulus values to normalised cone responses matrix."""

MATRIX_IPT_LMS_TO_XYZ: NDArray = np.linalg.inv(MATRIX_IPT_XYZ_TO_LMS)
"""Normalised cone responses to *CIE XYZ* tristimulus values matrix."""

MATRIX_IPT_LMS_P_TO_IPT: NDArray = np.array(
[
[0.3037, 0.6688, 0.0276],
[3.9247, -4.7339, 0.8093],
[1.5932, -0.5205, -1.0727],
]
)
"""
Normalised non-linear cone responses to *Munish Ragoo and Farup (2021)*
*Optimised IPT* colourspace matrix.
"""

MATRIX_IPT_IPT_TO_LMS_P: NDArray = np.linalg.inv(MATRIX_IPT_LMS_P_TO_IPT)
"""
*Munish Ragoo and Farup (2021)* *Optimised IPT* colourspace to normalised
non-linear cone responses matrix.
"""


def XYZ_to_IPT_Munish2021(XYZ: ArrayLike) -> NDArray:
"""
Convert from *CIE XYZ* tristimulus values to
*Munish Ragoo and Farup (2021)* *Optimised IPT* colourspace.
Parameters
----------
XYZ
*CIE XYZ* tristimulus values.
Returns
-------
:class:`numpy.ndarray`
*Munish Ragoo and Farup (2021)* *Optimised IPT* colourspace array.
Notes
-----
+------------+-----------------------+-----------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+============+=======================+=================+
| ``XYZ`` | [0, 1] | [0, 1] |
+------------+-----------------------+-----------------+
+------------+-----------------------+-----------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+============+=======================+=================+
| ``IPT`` | ``I`` : [0, 1] | ``I`` : [0, 1] |
| | | |
| | ``P`` : [-1, 1] | ``P`` : [-1, 1] |
| | | |
| | ``T`` : [-1, 1] | ``T`` : [-1, 1] |
+------------+-----------------------+-----------------+
- Input *CIE XYZ* tristimulus values must be adapted to
*CIE Standard Illuminant D Series* *D65*.
References
----------
:cite:`Munish2021`
Examples
--------
>>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
>>> XYZ_to_IPT_Munish2021(XYZ) # doctest: +ELLIPSIS
array([ 0.4224824..., 0.2910514..., 0.2041066...])
"""

return XYZ_to_Iab(
XYZ,
partial(spow, p=0.4071),
MATRIX_IPT_XYZ_TO_LMS,
MATRIX_IPT_LMS_P_TO_IPT,
)


def IPT_Munish2021_to_XYZ(IPT: ArrayLike) -> NDArray:
"""
Convert from *Munish Ragoo and Farup (2021)* *Optimised IPT* colourspace to
*CIE XYZ* tristimulus values.
Parameters
----------
IPT
*Munish Ragoo and Farup (2021)* *Optimised IPT* colourspace array.
Returns
-------
:class:`numpy.ndarray`
*CIE XYZ* tristimulus values.
Notes
-----
+------------+-----------------------+-----------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+============+=======================+=================+
| ``IPT`` | ``I`` : [0, 1] | ``I`` : [0, 1] |
| | | |
| | ``P`` : [-1, 1] | ``P`` : [-1, 1] |
| | | |
| | ``T`` : [-1, 1] | ``T`` : [-1, 1] |
+------------+-----------------------+-----------------+
+------------+-----------------------+-----------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+============+=======================+=================+
| ``XYZ`` | [0, 1] | [0, 1] |
+------------+-----------------------+-----------------+
References
----------
:cite:`Munish2021`
Examples
--------
>>> IPT = np.array([0.42248243, 0.2910514, 0.20410663])
>>> IPT_Munish2021_to_XYZ(IPT) # doctest: +ELLIPSIS
array([ 0.2065400..., 0.1219722..., 0.0513695...])
"""

return Iab_to_XYZ(
IPT,
partial(spow, p=1 / 0.4071),
MATRIX_IPT_IPT_TO_LMS_P,
MATRIX_IPT_LMS_TO_XYZ,
)

0 comments on commit 24656e6

Please sign in to comment.