Skip to content

Commit

Permalink
Merge branch 'feature/v0.3.16' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
KelSolaar committed Aug 8, 2020
2 parents 960ef6e + faf4936 commit 80c23b2
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 50 deletions.
7 changes: 4 additions & 3 deletions colour/difference/__init__.py
Expand Up @@ -37,14 +37,15 @@

from .cam02_ucs import delta_E_CAM02LCD, delta_E_CAM02SCD, delta_E_CAM02UCS
from .cam16_ucs import delta_E_CAM16LCD, delta_E_CAM16SCD, delta_E_CAM16UCS
from .delta_e import (delta_E_CIE1976, delta_E_CIE1994, delta_E_CIE2000,
delta_E_CMC)
from .delta_e import (JND_CIE1976, delta_E_CIE1976, delta_E_CIE1994,
delta_E_CIE2000, delta_E_CMC)
from .din99 import delta_E_DIN99

__all__ = ['delta_E_CAM02LCD', 'delta_E_CAM02SCD', 'delta_E_CAM02UCS']
__all__ += ['delta_E_CAM16LCD', 'delta_E_CAM16SCD', 'delta_E_CAM16UCS']
__all__ += [
'delta_E_CIE1976', 'delta_E_CIE1994', 'delta_E_CIE2000', 'delta_E_CMC'
'JND_CIE1976', 'delta_E_CIE1976', 'delta_E_CIE1994', 'delta_E_CIE2000',
'delta_E_CMC'
]
__all__ += ['delta_E_DIN99']

Expand Down
43 changes: 37 additions & 6 deletions colour/difference/delta_e.py
@@ -1,12 +1,13 @@
# -*- coding: utf-8 -*-
"""
:math:`\\Delta E_{ab}` - Delta E Colour Difference
=================================================
:math:`\\Delta E^*_{ab}` - Delta E Colour Difference
====================================================
Defines :math:`\\Delta E_{ab}` colour difference computation objects:
Defines :math:`\\Delta E^*_{ab}` colour difference computation objects:
The following methods are available:
The following attributes and methods are available:
- :attr:`colour.difference.JND_CIE1976`
- :func:`colour.difference.delta_E_CIE1976`
- :func:`colour.difference.delta_E_CIE1994`
- :func:`colour.difference.delta_E_CIE2000`
Expand All @@ -28,6 +29,8 @@
- :cite:`Melgosa2013b` : Melgosa, M. (2013). CIE / ISO new standard:
CIEDE2000. http://www.color.org/events/colorimetry/\
Melgosa_CIEDE2000_Workshop-July4.pdf
- :cite:`Mokrzycki2011` : Mokrzycki, W., & Tatol, M. (2011). Color difference
Delta E - A survey. Machine Graphics and Vision, 20, 383–411.
"""

from __future__ import division, unicode_literals
Expand All @@ -36,7 +39,8 @@

from colour.algebra import euclidean_distance
from colour.utilities import to_domain_100, tsplit

from colour.utilities.documentation import (DocstringFloat,
is_documentation_building)
__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2013-2020 - Colour Developers'
__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause'
Expand All @@ -45,9 +49,36 @@
__status__ = 'Production'

__all__ = [
'delta_E_CIE1976', 'delta_E_CIE1994', 'delta_E_CIE2000', 'delta_E_CMC'
'JND_CIE1976', 'delta_E_CIE1976', 'delta_E_CIE1994', 'delta_E_CIE2000',
'delta_E_CMC'
]

JND_CIE1976 = 2.3 / 100
if is_documentation_building(): # pragma: no cover
JND_CIE1976 = DocstringFloat(JND_CIE1976)
JND_CIE1976.__doc__ = """
Just Noticeable Difference (JND) according to *CIE 1976* colour difference
formula, i.e. Euclidean distance in *CIE L\\*a\\*b\\** colourspace.
Notes
-----
A standard observer sees the difference in colour as follows:
- 0 < :math:`\\Delta E^*_{ab}` < 1 : Observer does not notice the difference.
- 1 < :math:`\\Delta E^*_{ab}` < 2 : Only experienced observer can notice the
difference.
- 2 < :math:`\\Delta E^*_{ab}` < 3:5 : Unexperienced observer also notices
the difference.
- 3:5 < :math:`\\Delta E^*_{ab}` < 5 : Clear difference in colour is noticed.
- 5 < :math:`\\Delta E^*_{ab}` : Observer notices two different colours.
References
----------
:cite:`Mokrzycki2011`
JND_CIE1976 : numeric
"""


def delta_E_CIE1976(Lab_1, Lab_2):
"""
Expand Down
45 changes: 13 additions & 32 deletions colour/recovery/jakob2019.py
Expand Up @@ -30,6 +30,7 @@
from colour.colorimetry import (
STANDARD_OBSERVER_CMFS, SpectralDistribution, SpectralShape,
intermediate_lightness_function_CIE1976, sd_ones, sd_to_XYZ)
from colour.difference import JND_CIE1976
from colour.models import XYZ_to_xy, XYZ_to_Lab, RGB_to_XYZ
from colour.utilities import (as_float_array, domain_range_scale, full,
index_along_last_axis, to_domain_1,
Expand All @@ -43,37 +44,17 @@
__status__ = 'Production'

__all__ = [
'DEFAULT_SPECTRAL_SHAPE_JAKOB_2019', 'ACCEPTABLE_DELTA_E',
'StopMinimizationEarly', 'sd_Jakob2019', 'error_function',
'dimensionalise_coefficients', 'lightness_scale',
'JAKOB2019_SPECTRAL_SHAPE', 'StopMinimizationEarly', 'sd_Jakob2019',
'error_function', 'dimensionalise_coefficients', 'lightness_scale',
'find_coefficients_Jakob2019', 'XYZ_to_sd_Jakob2019',
'Jakob2019Interpolator'
]

DEFAULT_SPECTRAL_SHAPE_JAKOB_2019 = SpectralShape(360, 780, 5)
JAKOB2019_SPECTRAL_SHAPE = SpectralShape(360, 780, 5)
"""
Default spectral shape for *Jakob and Hanika (2019)* method.
Spectral shape for *Jakob and Hanika (2019)* method.
DEFAULT_SPECTRAL_SHAPE_JAKOB_2019 : SpectralShape
"""

ACCEPTABLE_DELTA_E = 2.4 / 100 # 1% of JND
"""
Acceptable *perceptual* distance in the *CIE L\\*a\\*b\\** colourspace.
Notes
-----
*Jakob and Hanika (2019)* uses :math:`\\Delta E_{76}` in the
*CIE L\\*a\\*b\\** colourspace as an error metric during the optimization
process. While the *CIE L\\*a\\*b\\** colourspace features decent perceptual
uniformity, it was deemed unsatisfactory when comparing some pair of colors,
compelling the CIE into improving the metric with the CIE 1994
(:math:`\\Delta E_{94}`) quasimetric whose perceptual uniformity was
subsequently corrected with the CIE 2000 (:math:`\\Delta E_{00}`) quasimetric.
Thus, the error metric could be improved by adopting CIE 2000 or even a more
perceptually uniform colourspace such as :math:`IC_TC_P` or :math:`J_zA_zB_z`.
ACCEPTABLE_DELTA_E = 2.4 / 100 : float
JAKOB2019_SPECTRAL_SHAPE : SpectralShape
"""


Expand All @@ -96,7 +77,7 @@ def __init__(self, coefficients, error):
self.error = error


def sd_Jakob2019(coefficients, shape=DEFAULT_SPECTRAL_SHAPE_JAKOB_2019):
def sd_Jakob2019(coefficients, shape=JAKOB2019_SPECTRAL_SHAPE):
"""
Returns a spectral distribution following the spectral model given by
*Jakob and Hanika (2019)*.
Expand Down Expand Up @@ -327,11 +308,11 @@ def lightness_scale(steps):
def find_coefficients_Jakob2019(
XYZ,
cmfs=STANDARD_OBSERVER_CMFS['CIE 1931 2 Degree Standard Observer']
.copy().align(DEFAULT_SPECTRAL_SHAPE_JAKOB_2019),
.copy().align(JAKOB2019_SPECTRAL_SHAPE),
illuminant=ILLUMINANT_SDS['D65'].copy().align(
DEFAULT_SPECTRAL_SHAPE_JAKOB_2019),
JAKOB2019_SPECTRAL_SHAPE),
coefficients_0=zeros(3),
max_error=ACCEPTABLE_DELTA_E,
max_error=JND_CIE1976,
dimensionalise=True):
"""
Computes the coefficients for *Jakob and Hanika (2019)* reflectance
Expand Down Expand Up @@ -430,8 +411,8 @@ def optimize(target_o, coefficients_0_o):
def XYZ_to_sd_Jakob2019(
XYZ,
cmfs=STANDARD_OBSERVER_CMFS['CIE 1931 2 Degree Standard Observer']
.copy().align(DEFAULT_SPECTRAL_SHAPE_JAKOB_2019),
illuminant=sd_ones(DEFAULT_SPECTRAL_SHAPE_JAKOB_2019),
.copy().align(JAKOB2019_SPECTRAL_SHAPE),
illuminant=sd_ones(JAKOB2019_SPECTRAL_SHAPE),
optimisation_kwargs=None,
additional_data=False):
"""
Expand Down Expand Up @@ -617,7 +598,7 @@ def RGB_to_coefficients(self, RGB):

return self.cube(coords).squeeze()

def RGB_to_sd(self, RGB, shape=DEFAULT_SPECTRAL_SHAPE_JAKOB_2019):
def RGB_to_sd(self, RGB, shape=JAKOB2019_SPECTRAL_SHAPE):
"""
Looks up a given *RGB* colourspace array and return the corresponding
spectral distribution.
Expand Down
18 changes: 9 additions & 9 deletions colour/recovery/tests/test_jakob2019.py
Expand Up @@ -15,12 +15,12 @@
from colour.colorimetry import (ILLUMINANTS, ILLUMINANT_SDS,
STANDARD_OBSERVER_CMFS, SpectralDistribution,
sd_to_XYZ)
from colour.difference import delta_E_CIE1976
from colour.difference import JND_CIE1976, delta_E_CIE1976
from colour.models import RGB_COLOURSPACES, RGB_to_XYZ, XYZ_to_Lab
from colour.recovery.jakob2019 import (
XYZ_to_sd_Jakob2019, sd_Jakob2019, error_function,
dimensionalise_coefficients, DEFAULT_SPECTRAL_SHAPE_JAKOB_2019,
ACCEPTABLE_DELTA_E, Jakob2019Interpolator)
dimensionalise_coefficients, JAKOB2019_SPECTRAL_SHAPE,
Jakob2019Interpolator)
from colour.utilities import domain_range_scale, full, ones, zeros

__author__ = 'Colour Developers'
Expand Down Expand Up @@ -78,7 +78,7 @@ def test_compare_intermediates(self):
]

# error_function will not align these for us.
shape = DEFAULT_SPECTRAL_SHAPE_JAKOB_2019
shape = JAKOB2019_SPECTRAL_SHAPE
aligned_cmfs = CMFS.copy().align(shape)
illuminant = D65.copy().align(shape)
XYZ_n = sd_to_XYZ(D65)
Expand All @@ -101,16 +101,16 @@ def test_compare_intermediates(self):

np.testing.assert_allclose(sd.values, R, atol=1e-14)
np.testing.assert_allclose(XYZ, sd_XYZ, atol=1e-14)
self.assertLess(abs(error_reference - error), ACCEPTABLE_DELTA_E)
self.assertLess(delta_E_CIE1976(Lab, sd_Lab), ACCEPTABLE_DELTA_E)
self.assertLess(abs(error_reference - error), JND_CIE1976)
self.assertLess(delta_E_CIE1976(Lab, sd_Lab), JND_CIE1976)

def test_derivatives(self):
"""
Compares gradients computed using closed-form expressions of
derivatives with finite difference approximations.
"""

shape = DEFAULT_SPECTRAL_SHAPE_JAKOB_2019
shape = JAKOB2019_SPECTRAL_SHAPE
aligned_cmfs = CMFS.copy().align(shape)
illuminant = D65.copy().align(shape)
XYZ_n = sd_to_XYZ(D65)
Expand Down Expand Up @@ -161,7 +161,7 @@ def test_XYZ_to_sd_Jakob2019(self):
_recovered_sd, error = XYZ_to_sd_Jakob2019(
XYZ, illuminant=D65, additional_data=True)

if error > ACCEPTABLE_DELTA_E:
if error > JND_CIE1976:
self.fail('Delta E for \'{0}\' is {1}!'.format(name, error))

def test_domain_range_scale_XYZ_to_sd_Jakob2019(self):
Expand Down Expand Up @@ -232,7 +232,7 @@ def test_Jakob2019Interpolator(self):
recovered_Lab = XYZ_to_Lab(recovered_XYZ, D65_XY)

error = delta_E_CIE1976(Lab, recovered_Lab)
if error > 2 * ACCEPTABLE_DELTA_E:
if error > 2 * JND_CIE1976:
self.fail('Delta E for RGB={0} in colourspace {1} is {2}!'
.format(RGB, sRGB.name, error))

Expand Down
1 change: 1 addition & 0 deletions docs/colour.difference.rst
Expand Up @@ -26,6 +26,7 @@ CIE 1976
.. autosummary::
:toctree: generated/

JND_CIE1976
delta_E_CIE1976

CIE 1994
Expand Down

0 comments on commit 80c23b2

Please sign in to comment.