X-Git-Url: http://users.mur.at/ms/git/gitweb/?p=OpenColorIO-Configs.git;a=blobdiff_plain;f=aces_1.0.1%2Fpython%2Faces_ocio%2Fcolorspaces%2Fpanasonic_gh4.py;fp=aces_1.0.1%2Fpython%2Faces_ocio%2Fcolorspaces%2Fpanasonic_gh4.py;h=b5cdf28a05fb5791063078d2c895b50b312874f4;hp=0000000000000000000000000000000000000000;hb=d63bee171a979802ad9885fd73e73f44e39918d5;hpb=b1a546829f360c09bda9356783bd2a456d8d531c diff --git a/aces_1.0.1/python/aces_ocio/colorspaces/panasonic_gh4.py b/aces_1.0.1/python/aces_ocio/colorspaces/panasonic_gh4.py new file mode 100644 index 0000000..b5cdf28 --- /dev/null +++ b/aces_1.0.1/python/aces_ocio/colorspaces/panasonic_gh4.py @@ -0,0 +1,507 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Implements support for *Panasonic GH4* colorspaces conversions and transfer +functions based on empirical data. +""" +from panasonic_gh4_data import * + +import numpy as np +from scipy import interpolate +import matplotlib.pyplot as plt +import math, sys + +import array +import os + +import PyOpenColorIO as ocio + +import aces_ocio.generate_lut as genlut +from aces_ocio.utilities import ColorSpace + +__author__ = 'Martin Schitter' +__copyright__ = 'Copyright (C) 2015 - Martin Schitter' +__license__ = 'GNU General Public License' +__maintainer__ = 'Martin Schitter' +__email__ = 'ms+aces@mur.at' +__status__ = 'Experimental' + +__all__ = ['create_gh4_style', + 'create_colorspaces'] +styles = { + 'Scenery': [0.0079310344827586213, 0.017241379310344827, + 0.053448275862068968, 0.27517241379310342, 0.7501724137931034, + 1.3010344827586207, 2.1315517241379309, 3.0501724137931037, + 4.3113793103448277, 5.8546551724137927, 7.9153448275862068, + 10.296551724137931, 13.276896551724137, 16.769310344827588, + 21.641896551724138, 27.386034482758621, 34.62258620689655, + 43.353448275862071, 53.682931034482756, 65.670000000000002, + 80.268275862068961, 102.43344827586206, 116.53896551724138, + 134.62586206896552, 156.84931034482759, 170.11293103448276, + 184.20775862068965, 196.58258620689656, 207.89155172413794, + 217.53241379310344, 227.18224137931034, 236.08120689655172, + 244.85396551724139, 252.55293103448275, 254.95758620689656, + 255.0, 255.0, 255.0, 255.0, 255.0], + + 'Natural': [0.032758620689655175, 0.048275862068965517, + 0.16224137931034482, 0.4613793103448276, 1.0034482758620689, + 1.7708620689655172, 2.6732758620689654, 3.9575862068965519, + 5.5139655172413793, 7.4403448275862072, 9.6510344827586199, + 12.639310344827587, 16.452758620689654, 20.901551724137931, + 26.867241379310343, 34.115862068965519, 43.008448275862072, + 52.998448275862067, 64.548103448275867, 76.758448275862065, + 90.370862068965522, 109.64431034482759, 121.71120689655173, + 137.56103448275863, 157.60396551724139, 169.77672413793104, + 182.39965517241379, 194.02293103448275, 205.00258620689655, + 214.89431034482757, 224.41034482758621, 233.6396551724138, + 242.20258620689654, 250.67862068965516, 254.0, 254.0, 254.0, + 254.0, 254.0, 254.0], + + 'Vivid': [0.0013793103448275861, 0.0025862068965517241, + 0.024482758620689656, 0.11120689655172414, 0.16810344827586207, + 0.79741379310344829, 1.2001724137931034, 1.9437931034482758, + 2.9256896551724139, 4.0244827586206897, 5.4912068965517244, + 7.490344827586207, 10.088448275862069, 13.246379310344828, + 17.292586206896551, 22.015862068965518, 28.217068965517242, + 35.784310344827588, 44.731379310344828, 56.00931034482759, + 70.820689655172416, 93.825344827586207, 108.79879310344828, + 128.2251724137931, 152.32620689655172, 166.44137931034481, + 181.00758620689655, 193.65810344827585, 205.37741379310344, + 215.1153448275862, 224.87586206896552, 234.14637931034483, + 242.44327586206896, 250.86465517241379, 254.98724137931035, + 255.0, 255.0, 255.0, 255.0, 255.0], + + 'Cinelike-D': [0.21293103448275863, 0.27379310344827584, + 0.55500000000000005, 1.0448275862068965, 1.5686206896551724, + 2.7260344827586205, 3.9756896551724137, 5.5051724137931037, + 7.6129310344827585, 10.310344827586206, 13.517931034482759, + 17.027586206896551, 21.260862068965519, 25.73741379310345, + 30.967241379310344, 37.214310344827588, 44.142931034482757, + 51.230689655172412, 58.622068965517244, 66.37155172413793, + 75.241034482758621, 88.354310344827582, 96.904655172413797, + 108.34051724137932, 125.1453448275862, 136.35637931034483, + 150.76827586206898, 168.86913793103449, 185.40758620689655, + 200.0305172413793, 213.47120689655173, 227.06482758620689, + 242.42689655172413, 253.55879310344827, 254.97620689655173, + 255.0, 255.0, 255.0, 255.0, 255.0], + + 'V-Log': [31.429137931034482, 31.752758620689654, + 31.977413793103448, 32.531551724137934, 32.976551724137934, + 33.822586206896553, 34.706206896551727, 36.100344827586206, + 37.966551724137929, 40.231724137931032, 42.8301724137931, + 46.389482758620687, 50.373103448275863, 54.91965517241379, + 60.101724137931036, 65.1351724137931, 70.557586206896545, + 76.224827586206899, 81.544655172413798, 87.275517241379305, + 93.204999999999998, 100.89396551724138, 105.2244827586207, + 111.05396551724138, 118.80051724137931, 123.33396551724138, + 129.31517241379311, 135.62620689655174, 141.68793103448274, + 148.09086206896552, 154.73741379310346, 160.67603448275861, + 167.00999999999999, 173.17275862068965, 179.17706896551724, + 185.62896551724137, 190.93706896551726, 191.0, 191.0, 191.0], + + 'Standard': [0.019827586206896553, 0.030344827586206897, + 0.1296551724137931, 0.39862068965517239, 0.84431034482758616, + 1.5265517241379309, 2.3403448275862071, 3.3762068965517242, + 4.9127586206896554, 6.6224137931034486, 8.8127586206896549, + 11.51948275862069, 14.727241379310344, 18.599482758620688, + 23.895862068965517, 30.157413793103448, 38.333275862068966, + 47.146724137931038, 57.659999999999997, 68.3953448275862, + 81.231034482758616, 99.765517241379314, 111.80913793103448, + 127.22586206896551, 147.36137931034483, 160.73448275862069, + 174.77620689655171, 188.09258620689656, 200.56137931034482, + 212.24275862068964, 222.05310344827586, 231.96775862068966, + 240.85534482758621, 250.1894827586207, 255.0, 255.0, 255.0, + 255.0, 255.0, 255.0], + + 'BW': [0.012068965517241379, 0.03017241379310345, + 0.15879310344827585, 0.40379310344827585, 1.039655172413793, + 1.5532758620689655, 2.5448275862068965, 3.6275862068965519, + 5.1298275862068969, 7.1593103448275865, 9.1227586206896554, + 12.219482758620689, 15.602413793103448, 19.667068965517242, + 25.558793103448277, 32.138103448275864, 40.762413793103448, + 50.295862068965519, 61.059655172413791, 72.762758620689652, + 86.235172413793109, 105.61879310344827, 118.42362068965517, + 134.05362068965516, 155.23034482758621, 168.7403448275862, + 182.65913793103448, 195.72913793103447, 208.67896551724138, + 220.05086206896553, 229.83293103448275, 238.34137931034482, + 246.78810344827585, 254.53086206896552, 255.0, 255.0, 255.0, + 255.0, 255.0, 255.0], + + 'Cinelike-V': [0.0, 0.0, 0.00034482758620689653, + 0.017586206896551725, 0.16534482758620689, 0.71965517241379307, + 1.0924137931034483, 1.8994827586206897, 2.7312068965517242, + 3.7174137931034483, 5.0798275862068962, 7.0439655172413795, + 9.4998275862068962, 12.756379310344828, 17.174827586206895, + 22.375, 29.295000000000002, 37.235344827586204, + 47.138448275862068, 58.181034482758619, 71.008103448275861, + 89.295000000000002, 101.09810344827586, 117.49913793103448, + 138.71793103448275, 152.10293103448276, 166.64051724137931, + 181.39448275862068, 194.29568965517242, 206.1453448275862, + 218.05224137931035, 229.84310344827585, 243.2646551724138, + 254.25103448275863, 254.99310344827586, 255.0, 255.0, 255.0, + 255.0, 255.0], + + 'Portrait': [0.044999999999999998, 0.10706896551724138, + 0.21482758620689654, 0.61827586206896556, 1.258448275862069, + 1.9755172413793103, 2.8977586206896553, 4.243620689655172, + 5.7982758620689658, 7.8572413793103451, 10.573620689655172, + 13.566896551724138, 17.62396551724138, 22.091724137931035, + 28.537068965517243, 36.138103448275864, 45.346551724137932, + 55.862241379310348, 67.451379310344834, 79.880689655172418, + 94.139827586206891, 113.69862068965517, 126.13396551724138, + 141.94724137931036, 161.84068965517241, 173.89344827586206, + 186.02206896551724, 196.99051724137931, 207.93103448275863, + 217.54758620689654, 227.05655172413793, 235.96586206896552, + 245.08810344827586, 253.00948275862069, 253.97603448275862, + 254.0, 254.0, 254.0, 254.0, 254.0], + + 'Custom': [0.039310344827586205, 0.1, 0.31086206896551727, + 0.73482758620689659, 1.3484482758620691, 2.046551724137931, + 3.1565517241379308, 4.5710344827586207, 6.1872413793103451, + 8.3953448275862073, 10.947068965517241, 14.126724137931035, + 18.054827586206898, 22.778965517241378, 29.185689655172414, + 36.938448275862072, 45.952931034482759, 56.380000000000003, + 67.094310344827591, 79.601724137931029, 93.560000000000002, + 113.16017241379311, 125.54551724137932, 141.44189655172414, + 162.21155172413793, 174.12517241379311, 186.3755172413793, + 199.36862068965516, 211.13103448275862, 221.01068965517243, + 230.70120689655172, 239.67758620689656, 249.01879310344827, + 254.96413793103449, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0] +} + +def prepare_photostyle_to_linear(style, corr=None, debug_plot=False): + + # 18% gray card correction + corr = 16.5 + + #if not corr: + # if style == 'V-Log': + # corr = 16.5 + # else: + # #corr = 17.3 + # corr = 16.5 + + exp = np.linspace( (corr-39)/3.0, corr/3.0, 40) + l = np.power(2, exp) * 0.18 + vals = np.array(styles[style]) + vals = vals/255 + + # remove visible edges at some exposure values + print 'DIR:', dir() + for n in [24, 21, 4]: + if debug_plot: + plt.semilogy(vals[n], l[n], 'bx' ) + vals = np.delete(vals, n) + l = np.delete(l, n) + + # modify equal values to get an invertable monotone function + force_monotone = np.linspace(0,0.00001,len(vals)) + vals = vals+force_monotone + + #interp = interpolate.Akima1DInterpolator(vals, l) + interp = interpolate.PchipInterpolator(vals, l, extrapolate=False) + + if debug_plot: + plt.semilogy(vals, l, 'b+' ) + x = np.linspace(0., 1.0, 4096) + y = interp(x) + plt.semilogy(x, y, 'r.', ms=1 ) + x = np.linspace(0., 1.0, 256) + y = interp(x) + plt.semilogy(x, y, 'bo', ms=2 ) + plt.show() + + return interp + + +def create_gh4_style(gamut, + transfer_function, + lut_directory, + lut_resolution_1d, + aliases, + style=None): + """ + Creates colorspace covering the conversion from GH4 picture styles + to ACES based on empirical data + + Parameters + ---------- + gamut : str + The name of the encoding gamut to use. + transfer_function : str + The name of the transfer function to use + lut_directory : str or unicode + The directory to use when generating LUTs + lut_resolution_1d : int + The resolution of generated 1D LUTs + aliases : list of str + Aliases for this colorspace + + Returns + ------- + ColorSpace + A ColorSpace container class referencing the LUTs, matrices + and identifying information for the requested colorspace. + """ + + name = 'GH4-%s - GH4-%s-Gamut' % (transfer_function, gamut) + if transfer_function == '': + name = 'Linear - GH4-%s-Gamut' % gamut + if gamut == '': + name = 'Curve - GH4-%s' % transfer_function + + cs = ColorSpace(name) + cs.description = name + cs.aliases = aliases + cs.equality_group = '' + cs.family = 'Input/Panasonic/GH4' + cs.is_data = False + + # A linear space needs allocation variables + if transfer_function == '': + cs.allocation_type = ocio.Constants.ALLOCATION_LG2 + cs.allocation_vars = [-8, 6, 0.00390625] + + cs.to_reference_transforms = [] + + if transfer_function != '': + f = prepare_photostyle_to_linear(transfer_function) + + #data = array.array('f', '\0' * lut_resolution_1d * 4) + #for c in range(lut_resolution_1d): + # data[c] = v_log_to_linear(float(c) / (lut_resolution_1d - 1)) + dom = np.linspace(0.0, 1.0, lut_resolution_1d) + data = f(dom) + + # constant extrapolation + data_min = np.nanmin(data) + data_max = np.nanmax(data) + inds = np.where(np.isnan(data)) + for i in inds[0]: + if i < lut_resolution_1d/2: + data[i] = data_min + #data[i] = 0.0 + else: + data[i] = data_max + + lut = 'gh4_%s_to_linear.spi1d' % transfer_function + genlut.write_SPI_1d( + os.path.join(lut_directory, lut), + 0.0, + 1.0, + data, + lut_resolution_1d, + 1) + + cs.to_reference_transforms.append({ + 'type': 'lutFile', + 'path': lut, + 'interpolation': 'linear', + 'direction': 'forward'}) + + # + # matrix calculations based on: + # http://www.colour-science.org + # + + if gamut != '': + + # Lin -> XYZ + + if gamut == 'V-Log': + cs.to_reference_transforms.append({ + 'type': 'matrix', + # colour.V_GAMUT_COLOURSPACE.RGB_to_XYZ_matrix + 'matrix': [0.679644, 0.152211, 0.1186 , 0., + 0.260686, 0.774894, -0.03558, 0., + -0.00931 , -0.004612, 1.10298, 0., + 0, 0, 0, 1.], + 'direction': 'forward'}) + else: + cs.to_reference_transforms.append({ + 'type': 'matrix', + # colour.sRGB_COLOURSPACE.RGB_to_XYZ_matrix + 'matrix': [0.41238656, 0.35759149, 0.18045049, 0.0, + 0.21263682, 0.71518298, 0.0721802 , 0.0, + 0.01933062, 0.11919716, 0.95037259, 0.0, + 0, 0, 0, 1.0], + 'direction': 'forward'}) + + # D65 -> D50 adaption + # + # colour.chromatic_adaptation_matrix_VonKries( + # colour.xy_to_XYZ(c.sRGB_COLOURSPACE.whitepoint), + # colour.xy_to_XYZ(colour.ILLUMINANTS[ + # 'CIE 1931 2 Degree Standard Observer']['D50']), 'CAT02') + # + + cs.to_reference_transforms.append({ + 'type': 'matrix', + 'matrix': [1.04251352, 0.03083262, -0.05276445, 0.0, + 0.0221519 , 1.00187227, -0.02105432, 0.0, + -0.00116356, -0.00341802, 0.76197255, 0.0, + 0, 0, 0, 1.0], + 'direction': 'forward'}) + + if gamut.endswith('XYZ'): + cs.from_reference_transforms = [] + return cs + + if gamut.endswith('Calibrated'): + wb = [0.]*16 + wb[0] = calibration_wb[style][0] + wb[5] = calibration_wb[style][1] + wb[10] = calibration_wb[style][2] + wb[15] = 1.0 + cs.to_reference_transforms.append({ + 'type': 'matrix', + 'matrix': wb, + 'direction': 'forward'}) + cs.to_reference_transforms.append({ + 'type': 'matrix', + 'matrix': (calibration_matrices[style][0] + [0.0] + + calibration_matrices[style][1] + [0.0] + + calibration_matrices[style][2] + [0.0] + + [0, 0, 0, 1.0]), + 'direction': 'forward'}) + + # D50 -> ACES WP (~D60) + + # colour.chromatic_adaptation_matrix_VonKries( + # colour.xy_to_XYZ(colour.ILLUMINANTS[ + # 'CIE 1931 2 Degree Standard Observer']['D50']), + # colour.xy_to_XYZ(colour.V_GAMUT_COLOURSPACE.whitepoint), + # 'CAT02') + + cs.to_reference_transforms.append({ + 'type': 'matrix', + 'matrix': [ 0.95991641, -0.02931741, 0.06566143, 0.0, + -0.02119542, 0.99887268, 0.02613247, 0.0, + 0.00137075, 0.00443593, 1.31260073, 0.0, + 0, 0, 0, 1.0], + 'direction': 'forward'}) + + + # XYZ -> ACES + + # colour.ACES_2065_1_COLOURSPACE.XYZ_to_RGB_matrix + cs.to_reference_transforms.append({ + 'type': 'matrix', + 'matrix': [1.04981102e+00, 0.00000000e+00, -9.74845410e-05, 0., + -4.95903023e-01, 1.37331305e+00, 9.82400365e-02, 0., + 0.00000000e+00, 0.00000000e+00, 9.91252022e-01, 0., + 0, 0, 0, 1.], + 'direction': 'forward'}) + + # + # matrix given py panasonic / calculated by nuke + # for one step transformation: + # + + # if gamut == 'V-Log': + # cs.to_reference_transforms.append({ + # 'type': 'matrix', + # 'matrix': [0.724383 , 0.166748 , 0.108497, 0., + # 0.021354 , 0.985138 , -0.006319, 0., + # -0.009234 , -0.001043 , 1.010273, 0., + # 0, 0, 0, 1.], + # 'direction': 'forward'}) + # elif gamut != '': + # cs.to_reference_transforms.append({ + # 'type': 'matrix', + # 'matrix': [0.43964687, 0.38298151, 0.17737158, 0.0, + # 0.08978026, 0.81343973, 0.09677973, 0.0, + # 0.01754464, 0.11155707, 0.87089837, 0.0, + # 0, 0, 0, 1.0], + # 'direction': 'forward'}) + + cs.from_reference_transforms = [] + return cs + + +def create_colorspaces(lut_directory, lut_resolution_1d): + """ + Generates the colorspace conversions. + + Parameters + ---------- + lut_directory : str or unicode + The directory to use when generating LUTs + lut_resolution_1d : int + The resolution of generated 1D LUTs + + Returns + ------- + list + A list of colorspaces for Panasonic cameras and encodings + """ + + colorspaces = [] + + styles_sort = styles.keys() + styles_sort.sort() + + for style in styles_sort: + + # Full conversion + style_1 = create_gh4_style( + style, + style, + lut_directory, + lut_resolution_1d, + ['gh4_%s_gh4_gamut' % style.lower().replace('-','_')]) + colorspaces.append(style_1) + + # Linearization Only + style_2 = create_gh4_style( + '', + style, + lut_directory, + lut_resolution_1d, + ['crv_gh4_%s' % style.lower().replace('-','_')]) + colorspaces.append(style_2) + + # Linearization and XYZ conversion + style_3 = create_gh4_style( + '%s-XYZ' % style, + style, + lut_directory, + lut_resolution_1d, + ['gh4_%s_xyz' % style.lower().replace('-','_')]) + colorspaces.append(style_3) + + # Primaries Only + style_4 = create_gh4_style( + style, + '', + lut_directory, + lut_resolution_1d, + ['lin_gh4_%s_gamut' % style.lower().replace('-','_')]) + colorspaces.append(style_4) + + if style != 'BW': + + # Full conversion calibrated + style_5 = create_gh4_style( + '%s-Calibrated' % style, + style, + lut_directory, + lut_resolution_1d, + ['gh4_%s_gh4_calibrated_gamut'% style.lower().replace('-','_')], + style) + colorspaces.append(style_5) + + # Primaries Only calibrated + style_6 = create_gh4_style( + '%s-Calibrated' % style, + '', + lut_directory, + lut_resolution_1d, + ['lin_gh4_%s_calibrated_gamut'%style.lower().replace('-','_')], + style) + colorspaces.append(style_6) + + + return colorspaces +