Skip to content

Commit

Permalink
Merge 8e96fbb into 607f928
Browse files Browse the repository at this point in the history
  • Loading branch information
KelSolaar committed Dec 22, 2022
2 parents 607f928 + 8e96fbb commit 7b73804
Show file tree
Hide file tree
Showing 21 changed files with 530 additions and 484 deletions.
6 changes: 0 additions & 6 deletions BIBLIOGRAPHY.bib
Expand Up @@ -2132,12 +2132,6 @@ @misc{Lindbloom2009d
year = 2009,
howpublished = {http://www.brucelindbloom.com/Eqn\_xyY\_to\_XYZ.html},
}
@misc{Lindbloom2009e,
title = {Delta {{E}} ({{CIE}} 2000)},
author = {Lindbloom, Bruce},
year = 2009,
howpublished = {http://brucelindbloom.com/Eqn\_DeltaE\_CIE2000.html},
}
@misc{Lindbloom2009f,
title = {Delta {{E}} ({{CMC}})},
author = {Lindbloom, Bruce},
Expand Down
19 changes: 10 additions & 9 deletions colour/characterisation/correction.py
Expand Up @@ -64,6 +64,7 @@
from colour.hints import ArrayLike, Any, Literal, NDArrayFloat, Union
from colour.utilities import (
CanonicalMapping,
as_float,
as_float_array,
as_int,
closest,
Expand Down Expand Up @@ -414,9 +415,9 @@ def polynomial_expansion_Finlayson2015(
if root_polynomial_expansion:
return tstack(
[
R,
G,
B,
as_float(R),
as_float(G),
as_float(B),
spow(R * G, 1 / 2),
spow(G * B, 1 / 2),
spow(R * B, 1 / 2),
Expand All @@ -441,9 +442,9 @@ def polynomial_expansion_Finlayson2015(
if root_polynomial_expansion:
return tstack(
[
R,
G,
B,
as_float(R),
as_float(G),
as_float(B),
spow(R * G, 1 / 2),
spow(G * B, 1 / 2),
spow(R * B, 1 / 2),
Expand Down Expand Up @@ -484,9 +485,9 @@ def polynomial_expansion_Finlayson2015(
if root_polynomial_expansion:
return tstack(
[
R,
G,
B,
as_float(R),
as_float(G),
as_float(B),
spow(R * G, 1 / 2),
spow(G * B, 1 / 2),
spow(R * B, 1 / 2),
Expand Down
24 changes: 12 additions & 12 deletions colour/characterisation/tests/test_correction.py
Expand Up @@ -683,8 +683,8 @@ def test_nan_matrix_colour_correction_Cheung2004(self): # pragma: no cover
matrix_colour_correction_Cheung2004` definition nan support.
"""

# NOTE: Hangs on "Linux".
if platform.system() == "Linux":
# NOTE: Hangs on "macOS" and "Linux".
if platform.system() in ("Darwin", "Linux"):
return

cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
Expand Down Expand Up @@ -790,8 +790,8 @@ def test_nan_matrix_colour_correction_Finlayson2015(
matrix_colour_correction_Finlayson2015` definition nan support.
"""

# NOTE: Hangs on "Linux".
if platform.system() == "Linux":
# NOTE: Hangs on "macOS" and "Linux".
if platform.system() in ("Darwin", "Linux"):
return

cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
Expand Down Expand Up @@ -888,8 +888,8 @@ def test_nan_matrix_colour_correction_Vandermonde(
matrix_colour_correction_Vandermonde` definition nan support.
"""

# NOTE: Hangs on "Linux".
if platform.system() == "Linux":
# NOTE: Hangs on "macOS" and "Linux".
if platform.system() in ("Darwin", "Linux"):
return

cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
Expand Down Expand Up @@ -966,8 +966,8 @@ def test_nan_colour_correction_Cheung2004(self): # pragma: no cover
colour_correction_Cheung2004` definition nan support.
"""

# NOTE: Hangs on "Linux".
if platform.system() == "Linux":
# NOTE: Hangs on "macOS" and "Linux".
if platform.system() in ("Darwin", "Linux"):
return

cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
Expand Down Expand Up @@ -1051,8 +1051,8 @@ def test_nan_colour_correction_Finlayson2015(self): # pragma: no cover
colour_correction_Finlayson2015` definition nan support.
"""

# NOTE: Hangs on "Linux".
if platform.system() == "Linux":
# NOTE: Hangs on "macOS" and "Linux".
if platform.system() in ("Darwin", "Linux"):
return

cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
Expand Down Expand Up @@ -1130,8 +1130,8 @@ def test_nan_colour_correction_Vandermonde(self): # pragma: no cover
colour_correction_Vandermonde` definition nan support.
"""

# NOTE: Hangs on "Linux".
if platform.system() == "Linux":
# NOTE: Hangs on "macOS" and "Linux".
if platform.system() in ("Darwin", "Linux"):
return

cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]
Expand Down
135 changes: 83 additions & 52 deletions colour/difference/delta_e.py
Expand Up @@ -23,9 +23,6 @@
- :cite:`Lindbloom2003c` : Lindbloom, B. (2003). Delta E (CIE 1976).
Retrieved February 24, 2014, from
http://brucelindbloom.com/Eqn_DeltaE_CIE76.html
- :cite:`Lindbloom2009e` : Lindbloom, B. (2009). Delta E (CIE 2000).
Retrieved February 24, 2014, from
http://brucelindbloom.com/Eqn_DeltaE_CIE2000.html
- :cite:`Lindbloom2009f` : Lindbloom, B. (2009). Delta E (CMC). Retrieved
February 24, 2014, from http://brucelindbloom.com/Eqn_DeltaE_CMC.html
- :cite:`Lindbloom2011a` : Lindbloom, B. (2011). Delta E (CIE 1994).
Expand All @@ -34,6 +31,10 @@
- :cite:`Melgosa2013b` : Melgosa, M. (2013). CIE / ISO new standard:
CIEDE2000. http://www.color.org/events/colorimetry/\
Melgosa_CIEDE2000_Workshop-July4.pdf
- :cite:`Sharma2005b` : Sharma, G., Wu, W., & Dalal, E. N. (2005). The
CIEDE2000 color-difference formula: Implementation notes, supplementary
test data, and mathematical observations. Color Research & Application,
30(1), 21-30. doi:10.1002/col.20070
- :cite:`Mokrzycki2011` : Mokrzycki, W., & Tatol, M. (2011). Color difference
Delta E - A survey. Machine Graphics and Vision, 20, 383-411.
"""
Expand Down Expand Up @@ -292,7 +293,7 @@ def delta_E_CIE2000(
References
----------
:cite:`Lindbloom2009e`, :cite:`Melgosa2013b`
:cite:`Melgosa2013b`, :cite:`Sharma2005b`
Examples
--------
Expand All @@ -314,72 +315,102 @@ def delta_E_CIE2000(
k_C = 1
k_H = 1

l_bar_prime = 0.5 * (L_1 + L_2)
C_1_ab = np.hypot(a_1, b_1)
C_2_ab = np.hypot(a_2, b_2)

c_1 = np.hypot(a_1, b_1)
c_2 = np.hypot(a_2, b_2)
C_bar_ab = (C_1_ab + C_2_ab) / 2
C_bar_ab_7 = C_bar_ab**7

c_bar = 0.5 * (c_1 + c_2)
c_bar7 = c_bar**7
G = 0.5 * (1 - np.sqrt(C_bar_ab_7 / (C_bar_ab_7 + 25**7)))

g = 0.5 * (1 - np.sqrt(c_bar7 / (c_bar7 + 25**7)))
a_p_1 = (1 + G) * a_1
a_p_2 = (1 + G) * a_2

a_1_prime = a_1 * (1 + g)
a_2_prime = a_2 * (1 + g)
c_1_prime = np.hypot(a_1_prime, b_1)
c_2_prime = np.hypot(a_2_prime, b_2)
c_bar_prime = 0.5 * (c_1_prime + c_2_prime)
C_p_1 = np.hypot(a_p_1, b_1)
C_p_2 = np.hypot(a_p_2, b_2)

h_p_1 = np.where(
np.logical_and(b_1 == 0, a_p_1 == 0),
0,
np.degrees(np.arctan2(b_1, a_p_1)) % 360,
)
h_p_2 = np.where(
np.logical_and(b_2 == 0, a_p_2 == 0),
0,
np.degrees(np.arctan2(b_2, a_p_2)) % 360,
)

h_1_prime = np.degrees(np.arctan2(b_1, a_1_prime)) % 360
h_2_prime = np.degrees(np.arctan2(b_2, a_2_prime)) % 360
delta_L_p = L_2 - L_1

delta_C_p = C_p_2 - C_p_1

h_p_2_s_1 = h_p_2 - h_p_1
C_p_1_m_2 = C_p_1 * C_p_2
delta_h_p = np.select(
[
C_p_1_m_2 == 0,
np.fabs(h_p_2_s_1) <= 180,
h_p_2_s_1 > 180,
h_p_2_s_1 < -180,
],
[
0,
h_p_2_s_1,
h_p_2_s_1 - 360,
h_p_2_s_1 + 360,
],
)

h_bar_prime = np.where(
np.fabs(h_1_prime - h_2_prime) <= 180,
0.5 * (h_1_prime + h_2_prime),
(0.5 * (h_1_prime + h_2_prime + 360)),
delta_H_p = 2 * np.sqrt(C_p_1_m_2) * np.sin(np.deg2rad(delta_h_p / 2))

L_bar_p = (L_1 + L_2) / 2

C_bar_p = (C_p_1 + C_p_2) / 2

a_h_p_1_s_2 = np.fabs(h_p_1 - h_p_2)
h_p_1_a_2 = h_p_1 + h_p_2
h_bar_p = np.select(
[
C_p_1_m_2 == 0,
a_h_p_1_s_2 <= 180,
np.logical_and(a_h_p_1_s_2 > 180, h_p_1_a_2 < 360),
np.logical_and(a_h_p_1_s_2 > 180, h_p_1_a_2 >= 360),
],
[
h_p_1_a_2,
h_p_1_a_2 / 2,
(h_p_1_a_2 + 360) / 2,
(h_p_1_a_2 - 360) / 2,
],
)

t = (
T = (
1
- 0.17 * np.cos(np.deg2rad(h_bar_prime - 30))
+ 0.24 * np.cos(np.deg2rad(2 * h_bar_prime))
+ 0.32 * np.cos(np.deg2rad(3 * h_bar_prime + 6))
- 0.20 * np.cos(np.deg2rad(4 * h_bar_prime - 63))
- 0.17 * np.cos(np.deg2rad(h_bar_p - 30))
+ 0.24 * np.cos(np.deg2rad(2 * h_bar_p))
+ 0.32 * np.cos(np.deg2rad(3 * h_bar_p + 6))
- 0.20 * np.cos(np.deg2rad(4 * h_bar_p - 63))
)

h = h_2_prime - h_1_prime
delta_h_prime = np.where(h_2_prime <= h_1_prime, h - 360, h + 360)
delta_h_prime = np.where(np.fabs(h) <= 180, h, delta_h_prime)
delta_theta = 30 * np.exp(-(((h_bar_p - 275) / 25) ** 2))

delta_L_prime = L_2 - L_1
delta_C_prime = c_2_prime - c_1_prime
delta_H_prime = (
2
* np.sqrt(c_1_prime * c_2_prime)
* np.sin(np.deg2rad(0.5 * delta_h_prime))
)
C_bar_p_7 = C_bar_p**7
R_C = 2 * np.sqrt(C_bar_p_7 / (C_bar_p_7 + 25**7))

s_L = 1 + (
(0.015 * (l_bar_prime - 50) * (l_bar_prime - 50))
/ np.sqrt(20 + (l_bar_prime - 50) * (l_bar_prime - 50))
)
s_C = 1 + 0.045 * c_bar_prime
s_H = 1 + 0.015 * c_bar_prime * t
L_bar_p_2 = (L_bar_p - 50) ** 2
S_L = 1 + ((0.015 * L_bar_p_2) / np.sqrt(20 + L_bar_p_2))

delta_theta = 30 * np.exp(
-((h_bar_prime - 275) / 25) * ((h_bar_prime - 275) / 25)
)
S_C = 1 + 0.045 * C_bar_p

c_bar_prime7 = c_bar_prime**7
S_H = 1 + 0.015 * C_bar_p * T

r_C = np.sqrt(c_bar_prime7 / (c_bar_prime7 + 25**7))
r_T = -2 * r_C * np.sin(np.deg2rad(2 * delta_theta))
R_T = -np.sin(np.deg2rad(2 * delta_theta)) * R_C

d_E = np.sqrt(
(delta_L_prime / (k_L * s_L)) ** 2
+ (delta_C_prime / (k_C * s_C)) ** 2
+ (delta_H_prime / (k_H * s_H)) ** 2
+ (delta_C_prime / (k_C * s_C)) * (delta_H_prime / (k_H * s_H)) * r_T
(delta_L_p / (k_L * S_L)) ** 2
+ (delta_C_p / (k_C * S_C)) ** 2
+ (delta_H_p / (k_H * S_H)) ** 2
+ R_T * (delta_C_p / (k_C * S_C)) * (delta_H_p / (k_H * S_H))
)

return as_float(d_E)
Expand Down
4 changes: 2 additions & 2 deletions colour/difference/tests/test_delta_e.py
Expand Up @@ -255,7 +255,7 @@ def test_delta_E_CIE2000(self):
np.array([100.00000000, 21.57210357, 272.22819350]),
np.array([100.00000000, 8.32281957, -73.58297716]),
),
68.23094879,
68.23111251,
places=7,
)

Expand Down Expand Up @@ -285,7 +285,7 @@ def test_delta_E_CIE2000(self):
np.array([50.00000000, 8.32281957, -73.58297716]),
textiles=True,
),
70.63198003,
70.63213819,
places=7,
)

Expand Down
14 changes: 10 additions & 4 deletions colour/io/luts/lut.py
Expand Up @@ -49,6 +49,7 @@
cast,
)
from colour.utilities import (
as_array,
as_float_array,
as_int,
as_int_array,
Expand Down Expand Up @@ -2118,10 +2119,15 @@ def linear_table(
if domain.shape != (2, 3):
samples = list(
np.flip(
[
axes[: (~np.isnan(axes)).cumsum().argmax() + 1]
for axes in np.transpose(domain)
],
# NOTE: "dtype=object" is required for ragged array support
# in "Numpy" 1.24.0.
as_array(
[
axes[: (~np.isnan(axes)).cumsum().argmax() + 1]
for axes in np.transpose(domain)
],
dtype=object, # pyright: ignore
),
-1,
)
)
Expand Down
2 changes: 1 addition & 1 deletion colour/models/rgb/transfer_functions/canon.py
Expand Up @@ -112,7 +112,7 @@ def log_encoding_CanonLog(
are obtained as follows:
>>> x = np.array([0, 2, 18, 90, 720]) / 100
>>> np.around(log_encoding_CanonLog(x) * (2**10 - 1)).astype(np.int)
>>> np.around(log_encoding_CanonLog(x) * (2**10 - 1)).astype(np.int_)
array([ 128, 169, 351, 614, 1016])
>>> np.around(log_encoding_CanonLog(x, 10, False) * 100, 1)
array([ 7.3, 12. , 32.8, 62.7, 108.7])
Expand Down
4 changes: 2 additions & 2 deletions colour/models/rgb/transfer_functions/fujifilm_f_log.py
Expand Up @@ -125,7 +125,7 @@ def log_encoding_FLog(
>>> x = np.array([0, 18, 90]) / 100
>>> np.around(log_encoding_FLog(x, 10, False) * 100, 1)
array([ 3.5, 46.3, 73.2])
>>> np.around(log_encoding_FLog(x) * (2**10 - 1)).astype(np.int)
>>> np.around(log_encoding_FLog(x) * (2**10 - 1)).astype(np.int_)
array([ 95, 470, 705])
"""

Expand Down Expand Up @@ -294,7 +294,7 @@ def log_encoding_FLog2(
>>> x = np.array([0, 18, 90]) / 100
>>> np.around(log_encoding_FLog2(x, 10, False) * 100, 1)
array([ 3.5, 38.4, 57.8])
>>> np.around(log_encoding_FLog2(x) * (2**10 - 1)).astype(np.int)
>>> np.around(log_encoding_FLog2(x) * (2**10 - 1)).astype(np.int_)
array([ 95, 400, 570])
"""

Expand Down
6 changes: 3 additions & 3 deletions colour/models/rgb/transfer_functions/panasonic_v_log.py
Expand Up @@ -98,11 +98,11 @@ def log_encoding_VLog(
are obtained as follows:
>>> L_in = np.array([0, 18, 90]) / 100
>>> np.around(log_encoding_VLog(L_in, 10, False) * 100).astype(np.int)
>>> np.around(log_encoding_VLog(L_in, 10, False) * 100).astype(np.int_)
array([ 7, 42, 61])
>>> np.around(log_encoding_VLog(L_in) * (2**10 - 1)).astype(np.int)
>>> np.around(log_encoding_VLog(L_in) * (2**10 - 1)).astype(np.int_)
array([128, 433, 602])
>>> np.around(log_encoding_VLog(L_in) * (2**12 - 1)).astype(np.int)
>>> np.around(log_encoding_VLog(L_in) * (2**12 - 1)).astype(np.int_)
array([ 512, 1733, 2409])
Note that some values in the last column values of
Expand Down

0 comments on commit 7b73804

Please sign in to comment.