-
-
Notifications
You must be signed in to change notification settings - Fork 252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PR: Add "colour.models.rgb.transfer_functions.log" module. #600
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,6 +58,7 @@ | |
log_encoding_SLog3, log_decoding_SLog3) | ||
from .srgb import eotf_inverse_sRGB, eotf_sRGB | ||
from .viper_log import log_encoding_ViperLog, log_decoding_ViperLog | ||
from .log import log_encoding_Log2, log_decoding_Log2 | ||
|
||
__all__ = ['CV_range', 'legal_to_full', 'full_to_legal'] | ||
__all__ += ['gamma_function'] | ||
|
@@ -116,6 +117,7 @@ | |
] | ||
__all__ += ['eotf_inverse_sRGB', 'eotf_sRGB'] | ||
__all__ += ['log_encoding_ViperLog', 'log_decoding_ViperLog'] | ||
__all__ += ['log_encoding_Log2', 'log_decoding_Log2'] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alphabetical ordering here too please. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted! |
||
|
||
LOG_ENCODINGS = CaseInsensitiveMapping({ | ||
'ACEScc': log_encoding_ACEScc, | ||
|
@@ -142,7 +144,8 @@ | |
'S-Log3': log_encoding_SLog3, | ||
'T-Log': log_encoding_FilmLightTLog, | ||
'V-Log': log_encoding_VLog, | ||
'ViperLog': log_encoding_ViperLog | ||
'ViperLog': log_encoding_ViperLog, | ||
'Log2': log_encoding_Log2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure :) |
||
}) | ||
LOG_ENCODINGS.__doc__ = """ | ||
Supported *log* encoding functions. | ||
|
@@ -152,7 +155,7 @@ | |
'Canon Log 3', 'Canon Log', 'Cineon', 'D-Log', 'ERIMM RGB', 'F-Log', | ||
'Filmic Pro 6', 'Log3G10', 'Log3G12', 'Panalog', 'PLog', 'Protune', | ||
'REDLog', 'REDLogFilm', 'S-Log', 'S-Log2', 'S-Log3', 'T-Log', 'V-Log', | ||
'ViperLog'}** | ||
'ViperLog', 'Log2'}** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted! |
||
""" | ||
|
||
|
||
|
@@ -170,7 +173,7 @@ def log_encoding(value, function='Cineon', **kwargs): | |
'Canon Log 3', 'Canon Log', 'Cineon', 'D-Log', 'ERIMM RGB', 'F-Log', | ||
'Filmic Pro 6', 'Log3G10', 'Log3G12', 'Panalog', 'PLog', 'Protune', | ||
'REDLog', 'REDLogFilm', 'S-Log', 'S-Log2', 'S-Log3', 'T-Log', | ||
'V-Log', 'ViperLog'}**, | ||
'V-Log', 'ViperLog', 'Log2'}**, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And same for the remaining instances (even in the docs). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will take care, Thankyou! |
||
Computation function. | ||
|
||
Other Parameters | ||
|
@@ -286,7 +289,8 @@ def log_encoding(value, function='Cineon', **kwargs): | |
'S-Log3': log_decoding_SLog3, | ||
'T-Log': log_decoding_FilmLightTLog, | ||
'V-Log': log_decoding_VLog, | ||
'ViperLog': log_decoding_ViperLog | ||
'ViperLog': log_decoding_ViperLog, | ||
'Log2': log_decoding_Log2 | ||
}) | ||
LOG_DECODINGS.__doc__ = """ | ||
Supported *log* decoding functions. | ||
|
@@ -296,7 +300,7 @@ def log_encoding(value, function='Cineon', **kwargs): | |
'Canon Log 3', 'Canon Log', 'Cineon', 'D-Log', 'ERIMM RGB', 'F-Log', | ||
'Filmic Pro 6', 'Log3G10', 'Log3G12', 'Panalog', 'PLog', 'Protune', | ||
'REDLog', 'REDLogFilm', 'S-Log', 'S-Log2', 'S-Log3', 'T-Log', 'V-Log', | ||
'ViperLog'}** | ||
'ViperLog', 'Log2'}** | ||
""" | ||
|
||
|
||
|
@@ -314,7 +318,7 @@ def log_decoding(value, function='Cineon', **kwargs): | |
'Canon Log 3', 'Canon Log', 'Cineon', 'D-Log', 'ERIMM RGB', 'F-Log', | ||
'Filmic Pro 6', 'Log3G10', 'Log3G12', 'Panalog', 'PLog', 'Protune', | ||
'REDLog', 'REDLogFilm', 'S-Log', 'S-Log2', 'S-Log3', 'T-Log', | ||
'V-Log', 'ViperLog'}**, | ||
'V-Log', 'ViperLog', 'Log2'}**, | ||
Computation function. | ||
|
||
Other Parameters | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
# | ||
""" | ||
Log2 Shaper Implementation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The title could be Common Log Encodings or alike, what do you think @nick-shaw? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would make sense to keep it more general. This module could be expanded later to include things like the generic camera log function for CLF 3.0. |
||
========================== | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Careful at title marker length: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, should have taken care. Noted anyways! |
||
|
||
Defines the *Log2 shaper* log encodings: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Defines the common log encodings: |
||
|
||
- :func:`colour.models.log_encoding_Log2` | ||
- :func:`colour.models.log_decoding_Log2` | ||
|
||
References | ||
---------- | ||
- :cite:`TheAcademyofMotionPictureArtsandSciencesa` : | ||
The Academy of Motion Picture Arts and Sciences, | ||
Science and Technology Council, | ||
& Academy Color Encoding System (ACES) Project Subcommittee.(n.d.-a). | ||
ACESutil.Lin_to_Log2_param.ctl. Retrieved June 14, 2020, | ||
from https://github.com/ampas/aces-dev/blob/\ | ||
518c27f577e99cdecfddf2ebcfaa53444b1f9343/transforms/ctl/utilities/ACESutil.Lin_to_Log2_param.ctl | ||
- :cite:`TheAcademyofMotionPictureArtsandSciencesb` : | ||
The Academy of Motion Picture Arts and Sciences, | ||
Science and Technology Council, | ||
& Academy Color Encoding System (ACES) Project Subcommittee.(n.d.-b). | ||
ACESutil.Log2_to_Lin_param.ctl. Retrieved June 14, 2020, | ||
from https://github.com/ampas/aces-dev/blob/\ | ||
518c27f577e99cdecfddf2ebcfaa53444b1f9343/transforms/ctl/utilities/ACESutil.Log2_to_Lin_param.ctl | ||
""" | ||
|
||
from __future__ import division, unicode_literals | ||
|
||
import numpy as np | ||
from colour.utilities import from_range_1, to_domain_1 | ||
|
||
__author__ = 'Colour Developers' | ||
__copyright__ = 'Copyright (C) 2013-2020 - 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__ = ['log_encoding_Log2', 'log_decoding_Log2'] | ||
|
||
|
||
def log_encoding_Log2(lin, | ||
middle_grey=0.18, | ||
min_exposure=0.18 * 2 ** -6.5, | ||
max_exposure=0.18 * 2 ** 6.5): | ||
""" | ||
Defines the *Log2 shaper* log encoding function. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can drop shaper here, the function is generic enough that it is not necessarily used as a shaper. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that would make sense. Will make the change accordingly! :) |
||
|
||
Parameters | ||
---------- | ||
lin : numeric or array_like | ||
Linear data to undergo encoding. | ||
middle_grey : numeric, optional | ||
'Middle Grey' exposure value. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want to use quotes, prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted, will take care. |
||
min_exposure : numeric, optional | ||
Minimum exposure level. | ||
max_exposure : numeric, optional | ||
Maximum exposure level. | ||
|
||
Returns | ||
------- | ||
numeric or ndarray | ||
Non-linear *Log2 shaper* encoded data | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Full stop at the end ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted! |
||
|
||
Notes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the section is empty, we should get rid of it, maybe here is a good place to mention how this function is used to build various shapers in the ACES OCIO configuration. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good, will go about it! |
||
----- | ||
|
||
References | ||
---------- | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thankyou! |
||
Examples | ||
-------- | ||
Linear numeric input gets encoded as follows: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure :) |
||
|
||
>>> log_encoding_Log2(18) | ||
0.40773288970434662 | ||
|
||
Linear array-like input gets encoded as follows: | ||
|
||
>>> log_encoding_Log2(np.linspace(1, 2, 3)) | ||
array([ 0.15174832, 0.18765817, 0.21313661]) | ||
""" | ||
|
||
lin = to_domain_1(lin) | ||
|
||
lg2 = np.log2(lin / middle_grey) | ||
log_norm = (lg2 - min_exposure) / (max_exposure - min_exposure) | ||
|
||
return from_range_1(log_norm) | ||
|
||
|
||
def log_decoding_Log2(log_norm, | ||
middle_grey=0.18, | ||
min_exposure=0.18 * 2 ** -6.5, | ||
max_exposure=0.18 * 2 ** 6.5): | ||
""" | ||
Defines the *Log2 shaper* log decoding function. | ||
|
||
Parameters | ||
---------- | ||
log_norm : numeric or array_like | ||
Logarithmic data to undergo decoding. | ||
middle_grey : numeric, optional | ||
'Middle Grey' exposure value. | ||
min_exposure : numeric, optional | ||
Minimum exposure level. | ||
max_exposure : numeric, optional | ||
Maximum exposure level. | ||
|
||
Returns | ||
------- | ||
numeric or ndarray | ||
Linear *Log2 shaper* decoded data | ||
|
||
Notes | ||
----- | ||
|
||
References | ||
---------- | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thankyou! |
||
Examples | ||
-------- | ||
Logarithmic input gets decoded as follows: | ||
|
||
>>> log_decoding_Log2(0.40773288970434662) | ||
17.999999999999993 | ||
|
||
Linear array-like input gets encoded as follows: | ||
|
||
>>> log_decoding_Log2(np.linspace(0, 1, 4)) | ||
array([ 1.80248299e-01, 7.77032379e+00, 3.34970882e+02, | ||
1.44402595e+04]) | ||
""" | ||
|
||
log_norm = to_domain_1(log_norm) | ||
|
||
lg2 = log_norm * (max_exposure - min_exposure) + min_exposure | ||
lin = (2 ** lg2) * middle_grey | ||
|
||
return from_range_1(lin) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
# | ||
""" | ||
Defines unit tests for :mod:`colour.models.rgb.transfer_functions.log` | ||
module. | ||
""" | ||
|
||
from __future__ import division, unicode_literals | ||
|
||
import numpy as np | ||
import unittest | ||
|
||
from colour.models.rgb.transfer_functions import (log_encoding_Log2, | ||
log_decoding_Log2) | ||
from colour.utilities import domain_range_scale, ignore_numpy_errors | ||
|
||
__author__ = 'Colour Developers' | ||
__copyright__ = 'Copyright (C) 2013-2020 - 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__ = [ | ||
'TestLogEncoding_Log2', | ||
'TestLogDecoding_Log2', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra coma at the end prevents Yapf inlining. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted |
||
] | ||
|
||
|
||
class TestLogEncoding_Log2(unittest.TestCase): | ||
""" | ||
Defines :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_encoding_Log2` definition unit tests methods. | ||
""" | ||
|
||
def test_log_encoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_encoding_Log2` definition. | ||
""" | ||
|
||
self.assertAlmostEqual(log_encoding_Log2(18), 0.407732889704, places=7) | ||
|
||
self.assertAlmostEqual( | ||
log_encoding_Log2(18, 0.12), 0.443642737727, places=7) | ||
|
||
self.assertAlmostEqual( | ||
log_encoding_Log2(18, 0.12, 0.0045), 0.443556955303, places=7) | ||
|
||
self.assertAlmostEqual( | ||
log_encoding_Log2(18, 0.12, 0.0045, 15.0), | ||
0.481765775766, | ||
places=7) | ||
|
||
def test_n_dimensional_log_encoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_encoding_Log2` definition n-dimensional arrays support. | ||
""" | ||
|
||
x = 18 | ||
y = log_encoding_Log2(x) | ||
|
||
x = np.tile(x, 6) | ||
y = np.tile(y, 6) | ||
np.testing.assert_almost_equal(log_encoding_Log2(x), y, decimal=7) | ||
|
||
x = np.reshape(x, (2, 3)) | ||
y = np.reshape(y, (2, 3)) | ||
np.testing.assert_almost_equal(log_encoding_Log2(x), y, decimal=7) | ||
|
||
x = np.reshape(x, (2, 3, 1)) | ||
y = np.reshape(y, (2, 3, 1)) | ||
np.testing.assert_almost_equal(log_encoding_Log2(x), y, decimal=7) | ||
|
||
def test_domain_range_scale_log_encoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_encoding_Log2` definition domain and range scale support. | ||
""" | ||
|
||
x = 18 | ||
y = log_encoding_Log2(x) | ||
|
||
d_r = (('reference', 1), (1, 1), (100, 100)) | ||
for scale, factor in d_r: | ||
with domain_range_scale(scale): | ||
np.testing.assert_almost_equal( | ||
log_encoding_Log2(x * factor), y * factor, decimal=7) | ||
|
||
@ignore_numpy_errors | ||
def test_nan_log_encoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_encoding_Log2` definition nan support. | ||
""" | ||
|
||
log_encoding_Log2(np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan])) | ||
|
||
|
||
class TestLogDecoding_Log2(unittest.TestCase): | ||
""" | ||
Defines :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_decoding_Log2` definition unit tests methods. | ||
""" | ||
|
||
def test_log_decoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_decoding_Log2` definition. | ||
""" | ||
|
||
self.assertAlmostEqual( | ||
log_decoding_Log2(0.40773288970434662), 17.9999999991, places=7) | ||
|
||
self.assertAlmostEqual( | ||
log_decoding_Log2(0.4077328897, 0.12), 11.9999999994, places=7) | ||
|
||
self.assertAlmostEqual( | ||
log_decoding_Log2(0.4077328897, 0.12, 0.0045), | ||
12.0123777083, | ||
places=7) | ||
|
||
self.assertAlmostEqual( | ||
log_decoding_Log2(0.4077328897, 0.12, 0.0045, 15.0), | ||
8.33836692466, | ||
places=7) | ||
|
||
def test_n_dimensional_log_decoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_decoding_Log2` definition n-dimensional arrays support. | ||
""" | ||
|
||
y = 0.384970815928670 | ||
x = log_decoding_Log2(y) | ||
|
||
y = np.tile(y, 6) | ||
x = np.tile(x, 6) | ||
np.testing.assert_almost_equal(log_decoding_Log2(y), x, decimal=7) | ||
|
||
y = np.reshape(y, (2, 3)) | ||
x = np.reshape(x, (2, 3)) | ||
np.testing.assert_almost_equal(log_decoding_Log2(y), x, decimal=7) | ||
|
||
y = np.reshape(y, (2, 3, 1)) | ||
x = np.reshape(x, (2, 3, 1)) | ||
np.testing.assert_almost_equal(log_decoding_Log2(y), x, decimal=7) | ||
|
||
def test_domain_range_scale_log_decoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_decoding_Log2` definition domain and range scale support. | ||
""" | ||
|
||
y = 0.384970815928670 | ||
x = log_decoding_Log2(y) | ||
|
||
d_r = (('reference', 1), (1, 1), (100, 100)) | ||
for scale, factor in d_r: | ||
with domain_range_scale(scale): | ||
np.testing.assert_almost_equal( | ||
log_decoding_Log2(y * factor), x * factor, decimal=7) | ||
|
||
@ignore_numpy_errors | ||
def test_nan_log_decoding_Log2(self): | ||
""" | ||
Tests :func:`colour.models.rgb.transfer_functions.log.\ | ||
log_decoding_Log2` definition nan support. | ||
""" | ||
|
||
log_decoding_Log2(np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan])) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -588,6 +588,8 @@ Log Encoding and Decoding | |
log_decoding_VLog | ||
log_encoding_ViperLog | ||
log_decoding_ViperLog | ||
log_encoding_Log2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alphabetical ordering please :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noted, Thankyou! |
||
log_decoding_Log2 | ||
|
||
Colour Encodings | ||
~~~~~~~~~~~~~~~~ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the module does not depend on anything nor anything really depends on it, please import it in alphabetical order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted! Will take care of that in the future! 👍