Source code for colour_hdri.calibration.absolute_luminance

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Absolute Luminance Calibration - Lagarde (2016)
===============================================

Defines *Lagarde (2016)* panoramic images absolute *Luminance* calibration
objects:

-   :func:`absolute_luminance_calibration_Lagarde2016`
-   :func:`upper_hemisphere_illuminance_Lagarde2016`
-   :func:`upper_hemisphere_illuminance_weights_Lagarde2016`

References
----------
.. [1]  Lagarde, S., Lachambre, S., & Jover, C. (2016). An Artist-Friendly
        Workflow for Panoramic HDRI. Retrieved from
        http://blog.selfshadow.com/publications/s2016-shading-course/\
unity/s2016_pbs_unity_hdri_notes.pdf
"""

from __future__ import division, unicode_literals

import numpy as np

from colour import RGB_COLOURSPACES, RGB_luminance

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2015-2017 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'

__all__ = ['upper_hemisphere_illuminance_Lagarde2016',
           'upper_hemisphere_illuminance_weights_Lagarde2016',
           'absolute_luminance_calibration_Lagarde2016']


[docs]def upper_hemisphere_illuminance_Lagarde2016( RGB, colourspace=RGB_COLOURSPACES['sRGB']): """ Computes upper hemisphere illuminance :math:`E_v` of given RGB panoramic image. Parameters ---------- RGB : array_like *RGB* panoramic image array. colourspace : `colour.RGB_Colourspace`, optional *RGB* colourspace used for internal *Luminance* computation. Returns ------- numeric Upper hemisphere illuminance :math:`E_v`. Examples -------- >>> RGB = np.ones((16, 32, 3)) >>> upper_hemisphere_illuminance_Lagarde2016(RGB) # doctest: +ELLIPSIS 2.9344691... """ RGB = np.asarray(RGB) height, width, channels = RGB.shape L = RGB_luminance(RGB, colourspace.primaries, colourspace.whitepoint) theta = np.linspace(0, 1, height) * np.pi theta_cos = np.cos(theta)[..., np.newaxis] theta_sin = np.sin(theta)[..., np.newaxis] E_v = np.sum(np.where(theta_cos > 0, L * theta_cos * theta_sin, 0)) E_v *= 2 * np.pi ** 2 / (width * height) return E_v
[docs]def upper_hemisphere_illuminance_weights_Lagarde2016(height, width): """ Computes upper hemisphere illuminance weights for use with applications unable to perform the computation directly, i.e. *Adobe Photoshop*. Parameters ---------- height : int Output array height. width : int Output array width. Returns ------- ndarray Upper hemisphere illuminance weights. Examples -------- >>> upper_hemisphere_illuminance_weights_Lagarde2016( # doctest: +ELLIPSIS ... 16, 1) array([[ 0... ], [ 4.0143297...], [ 7.3345454...], [ 9.3865515...], [ 9.8155376...], [ 8.5473281...], [ 5.8012079...], [ 2.0520061...], [ 0... ], [ 0... ], [ 0... ], [ 0... ], [ 0... ], [ 0... ], [ 0... ], [ 0... ]]) """ w = np.zeros((height, width)) theta = (np.linspace(0, 1, height) * np.pi) theta = np.tile(theta[..., np.newaxis], (1, width)) theta_cos = np.cos(theta) theta_sin = np.sin(theta) w[theta_cos > 0] = (theta_cos[theta_cos > 0] * theta_sin[theta_cos > 0] * 2 * np.pi ** 2) return w
[docs]def absolute_luminance_calibration_Lagarde2016( RGB, measured_illuminance, colourspace=RGB_COLOURSPACES['sRGB']): """ Performs absolute *Luminance* calibration of given *RGB* panoramic image using *Lagarde (2016)* method. Parameters ---------- RGB : array_like *RGB* panoramic image to calibrate. measured_illuminance : numeric Measured illuminance :math:`E_v`. colourspace : `colour.RGB_Colourspace`, optional *RGB* colourspace used for internal *Luminance* computation. Returns ------- ndarray Absolute *Luminance* calibrated *RGB* panoramic image. Examples -------- >>> RGB = np.ones((4, 8, 3)) >>> absolute_luminance_calibration_Lagarde2016( # doctest: +ELLIPSIS ... RGB, 500) array([[[ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...]], <BLANKLINE> [[ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...]], <BLANKLINE> [[ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...]], <BLANKLINE> [[ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...], [ 233.9912506..., 233.9912506..., 233.9912506...]]]) """ RGB = np.asarray(RGB) E_v = upper_hemisphere_illuminance_Lagarde2016(RGB, colourspace) return RGB / E_v * measured_illuminance