2 # -*- coding: utf-8 -*-
5 Implements support for *Panasonic GH4* colorspaces conversions and transfer
6 functions based on empirical data.
8 from panasonic_gh4_data import *
11 from scipy import interpolate
12 import matplotlib.pyplot as plt
18 import PyOpenColorIO as ocio
20 import aces_ocio.generate_lut as genlut
21 from aces_ocio.utilities import ColorSpace
23 __author__ = 'Martin Schitter'
24 __copyright__ = 'Copyright (C) 2015 - Martin Schitter'
25 __license__ = 'GNU General Public License'
26 __maintainer__ = 'Martin Schitter'
27 __email__ = 'ms+aces@mur.at'
28 __status__ = 'Experimental'
30 __all__ = ['create_gh4_style',
33 'Scenery': [0.0079310344827586213, 0.017241379310344827,
34 0.053448275862068968, 0.27517241379310342, 0.7501724137931034,
35 1.3010344827586207, 2.1315517241379309, 3.0501724137931037,
36 4.3113793103448277, 5.8546551724137927, 7.9153448275862068,
37 10.296551724137931, 13.276896551724137, 16.769310344827588,
38 21.641896551724138, 27.386034482758621, 34.62258620689655,
39 43.353448275862071, 53.682931034482756, 65.670000000000002,
40 80.268275862068961, 102.43344827586206, 116.53896551724138,
41 134.62586206896552, 156.84931034482759, 170.11293103448276,
42 184.20775862068965, 196.58258620689656, 207.89155172413794,
43 217.53241379310344, 227.18224137931034, 236.08120689655172,
44 244.85396551724139, 252.55293103448275, 254.95758620689656,
45 255.0, 255.0, 255.0, 255.0, 255.0],
47 'Natural': [0.032758620689655175, 0.048275862068965517,
48 0.16224137931034482, 0.4613793103448276, 1.0034482758620689,
49 1.7708620689655172, 2.6732758620689654, 3.9575862068965519,
50 5.5139655172413793, 7.4403448275862072, 9.6510344827586199,
51 12.639310344827587, 16.452758620689654, 20.901551724137931,
52 26.867241379310343, 34.115862068965519, 43.008448275862072,
53 52.998448275862067, 64.548103448275867, 76.758448275862065,
54 90.370862068965522, 109.64431034482759, 121.71120689655173,
55 137.56103448275863, 157.60396551724139, 169.77672413793104,
56 182.39965517241379, 194.02293103448275, 205.00258620689655,
57 214.89431034482757, 224.41034482758621, 233.6396551724138,
58 242.20258620689654, 250.67862068965516, 254.0, 254.0, 254.0,
61 'Vivid': [0.0013793103448275861, 0.0025862068965517241,
62 0.024482758620689656, 0.11120689655172414, 0.16810344827586207,
63 0.79741379310344829, 1.2001724137931034, 1.9437931034482758,
64 2.9256896551724139, 4.0244827586206897, 5.4912068965517244,
65 7.490344827586207, 10.088448275862069, 13.246379310344828,
66 17.292586206896551, 22.015862068965518, 28.217068965517242,
67 35.784310344827588, 44.731379310344828, 56.00931034482759,
68 70.820689655172416, 93.825344827586207, 108.79879310344828,
69 128.2251724137931, 152.32620689655172, 166.44137931034481,
70 181.00758620689655, 193.65810344827585, 205.37741379310344,
71 215.1153448275862, 224.87586206896552, 234.14637931034483,
72 242.44327586206896, 250.86465517241379, 254.98724137931035,
73 255.0, 255.0, 255.0, 255.0, 255.0],
75 'Cinelike-D': [0.21293103448275863, 0.27379310344827584,
76 0.55500000000000005, 1.0448275862068965, 1.5686206896551724,
77 2.7260344827586205, 3.9756896551724137, 5.5051724137931037,
78 7.6129310344827585, 10.310344827586206, 13.517931034482759,
79 17.027586206896551, 21.260862068965519, 25.73741379310345,
80 30.967241379310344, 37.214310344827588, 44.142931034482757,
81 51.230689655172412, 58.622068965517244, 66.37155172413793,
82 75.241034482758621, 88.354310344827582, 96.904655172413797,
83 108.34051724137932, 125.1453448275862, 136.35637931034483,
84 150.76827586206898, 168.86913793103449, 185.40758620689655,
85 200.0305172413793, 213.47120689655173, 227.06482758620689,
86 242.42689655172413, 253.55879310344827, 254.97620689655173,
87 255.0, 255.0, 255.0, 255.0, 255.0],
89 'V-Log': [31.429137931034482, 31.752758620689654,
90 31.977413793103448, 32.531551724137934, 32.976551724137934,
91 33.822586206896553, 34.706206896551727, 36.100344827586206,
92 37.966551724137929, 40.231724137931032, 42.8301724137931,
93 46.389482758620687, 50.373103448275863, 54.91965517241379,
94 60.101724137931036, 65.1351724137931, 70.557586206896545,
95 76.224827586206899, 81.544655172413798, 87.275517241379305,
96 93.204999999999998, 100.89396551724138, 105.2244827586207,
97 111.05396551724138, 118.80051724137931, 123.33396551724138,
98 129.31517241379311, 135.62620689655174, 141.68793103448274,
99 148.09086206896552, 154.73741379310346, 160.67603448275861,
100 167.00999999999999, 173.17275862068965, 179.17706896551724,
101 185.62896551724137, 190.93706896551726, 191.0, 191.0, 191.0],
103 'Standard': [0.019827586206896553, 0.030344827586206897,
104 0.1296551724137931, 0.39862068965517239, 0.84431034482758616,
105 1.5265517241379309, 2.3403448275862071, 3.3762068965517242,
106 4.9127586206896554, 6.6224137931034486, 8.8127586206896549,
107 11.51948275862069, 14.727241379310344, 18.599482758620688,
108 23.895862068965517, 30.157413793103448, 38.333275862068966,
109 47.146724137931038, 57.659999999999997, 68.3953448275862,
110 81.231034482758616, 99.765517241379314, 111.80913793103448,
111 127.22586206896551, 147.36137931034483, 160.73448275862069,
112 174.77620689655171, 188.09258620689656, 200.56137931034482,
113 212.24275862068964, 222.05310344827586, 231.96775862068966,
114 240.85534482758621, 250.1894827586207, 255.0, 255.0, 255.0,
115 255.0, 255.0, 255.0],
117 'BW': [0.012068965517241379, 0.03017241379310345,
118 0.15879310344827585, 0.40379310344827585, 1.039655172413793,
119 1.5532758620689655, 2.5448275862068965, 3.6275862068965519,
120 5.1298275862068969, 7.1593103448275865, 9.1227586206896554,
121 12.219482758620689, 15.602413793103448, 19.667068965517242,
122 25.558793103448277, 32.138103448275864, 40.762413793103448,
123 50.295862068965519, 61.059655172413791, 72.762758620689652,
124 86.235172413793109, 105.61879310344827, 118.42362068965517,
125 134.05362068965516, 155.23034482758621, 168.7403448275862,
126 182.65913793103448, 195.72913793103447, 208.67896551724138,
127 220.05086206896553, 229.83293103448275, 238.34137931034482,
128 246.78810344827585, 254.53086206896552, 255.0, 255.0, 255.0,
129 255.0, 255.0, 255.0],
131 'Cinelike-V': [0.0, 0.0, 0.00034482758620689653,
132 0.017586206896551725, 0.16534482758620689, 0.71965517241379307,
133 1.0924137931034483, 1.8994827586206897, 2.7312068965517242,
134 3.7174137931034483, 5.0798275862068962, 7.0439655172413795,
135 9.4998275862068962, 12.756379310344828, 17.174827586206895,
136 22.375, 29.295000000000002, 37.235344827586204,
137 47.138448275862068, 58.181034482758619, 71.008103448275861,
138 89.295000000000002, 101.09810344827586, 117.49913793103448,
139 138.71793103448275, 152.10293103448276, 166.64051724137931,
140 181.39448275862068, 194.29568965517242, 206.1453448275862,
141 218.05224137931035, 229.84310344827585, 243.2646551724138,
142 254.25103448275863, 254.99310344827586, 255.0, 255.0, 255.0,
145 'Portrait': [0.044999999999999998, 0.10706896551724138,
146 0.21482758620689654, 0.61827586206896556, 1.258448275862069,
147 1.9755172413793103, 2.8977586206896553, 4.243620689655172,
148 5.7982758620689658, 7.8572413793103451, 10.573620689655172,
149 13.566896551724138, 17.62396551724138, 22.091724137931035,
150 28.537068965517243, 36.138103448275864, 45.346551724137932,
151 55.862241379310348, 67.451379310344834, 79.880689655172418,
152 94.139827586206891, 113.69862068965517, 126.13396551724138,
153 141.94724137931036, 161.84068965517241, 173.89344827586206,
154 186.02206896551724, 196.99051724137931, 207.93103448275863,
155 217.54758620689654, 227.05655172413793, 235.96586206896552,
156 245.08810344827586, 253.00948275862069, 253.97603448275862,
157 254.0, 254.0, 254.0, 254.0, 254.0],
159 'Custom': [0.039310344827586205, 0.1, 0.31086206896551727,
160 0.73482758620689659, 1.3484482758620691, 2.046551724137931,
161 3.1565517241379308, 4.5710344827586207, 6.1872413793103451,
162 8.3953448275862073, 10.947068965517241, 14.126724137931035,
163 18.054827586206898, 22.778965517241378, 29.185689655172414,
164 36.938448275862072, 45.952931034482759, 56.380000000000003,
165 67.094310344827591, 79.601724137931029, 93.560000000000002,
166 113.16017241379311, 125.54551724137932, 141.44189655172414,
167 162.21155172413793, 174.12517241379311, 186.3755172413793,
168 199.36862068965516, 211.13103448275862, 221.01068965517243,
169 230.70120689655172, 239.67758620689656, 249.01879310344827,
170 254.96413793103449, 255.0, 255.0, 255.0, 255.0, 255.0, 255.0]
173 def prepare_photostyle_to_linear(style, corr=None, debug_plot=False):
175 # 18% gray card correction
179 # if style == 'V-Log':
185 exp = np.linspace( (corr-39)/3.0, corr/3.0, 40)
186 l = np.power(2, exp) * 0.18
187 vals = np.array(styles[style])
190 # remove visible edges at some exposure values
192 for n in [24, 21, 4]:
194 plt.semilogy(vals[n], l[n], 'bx' )
195 vals = np.delete(vals, n)
198 # modify equal values to get an invertable monotone function
199 force_monotone = np.linspace(0,0.00001,len(vals))
200 vals = vals+force_monotone
202 #interp = interpolate.Akima1DInterpolator(vals, l)
203 interp = interpolate.PchipInterpolator(vals, l, extrapolate=False)
206 plt.semilogy(vals, l, 'b+' )
207 x = np.linspace(0., 1.0, 4096)
209 plt.semilogy(x, y, 'r.', ms=1 )
210 x = np.linspace(0., 1.0, 256)
212 plt.semilogy(x, y, 'bo', ms=2 )
218 def create_gh4_style(gamut,
226 Creates colorspace covering the conversion from GH4 picture styles
227 to ACES based on empirical data
232 The name of the encoding gamut to use.
233 transfer_function : str
234 The name of the transfer function to use
235 lut_directory : str or unicode
236 The directory to use when generating LUTs
237 lut_resolution_1d : int
238 The resolution of generated 1D LUTs
239 aliases : list of str
240 Aliases for this colorspace
242 Associated Photo Style
244 Variant of processing
249 A ColorSpace container class referencing the LUTs, matrices
250 and identifying information for the requested colorspace.
253 name = ('GH4-%s - GH4-%s-Gamut %s' % (transfer_function, gamut, variant)).strip()
254 if transfer_function == '':
255 name = ('Linear - GH4-%s-Gamut %s' % (gamut, variant)).strip()
257 name = 'Curve - GH4-%s' % transfer_function
259 cs = ColorSpace(name)
260 cs.description = name
262 cs.equality_group = ''
263 cs.family = 'Input/Panasonic/GH4'
266 # A linear space needs allocation variables
267 if transfer_function == '':
268 cs.allocation_type = ocio.Constants.ALLOCATION_LG2
269 cs.allocation_vars = [-8, 6, 0.00390625]
271 cs.to_reference_transforms = []
273 if transfer_function != '':
274 f = prepare_photostyle_to_linear(transfer_function)
276 #data = array.array('f', '\0' * lut_resolution_1d * 4)
277 #for c in range(lut_resolution_1d):
278 # data[c] = v_log_to_linear(float(c) / (lut_resolution_1d - 1))
279 dom = np.linspace(0.0, 1.0, lut_resolution_1d)
282 # constant extrapolation
283 data_min = np.nanmin(data)
284 data_max = np.nanmax(data)
285 inds = np.where(np.isnan(data))
287 if i < lut_resolution_1d/2:
293 lut = 'gh4_%s_to_linear.spi1d' % transfer_function
295 os.path.join(lut_directory, lut),
302 cs.to_reference_transforms.append({
305 'interpolation': 'linear',
306 'direction': 'forward'})
309 # matrix calculations based on:
310 # http://www.colour-science.org
318 cs.to_reference_transforms.append({
320 # colour.V_GAMUT_COLOURSPACE.RGB_to_XYZ_matrix
321 'matrix': [0.679644, 0.152211, 0.1186 , 0.,
322 0.260686, 0.774894, -0.03558, 0.,
323 -0.00931 , -0.004612, 1.10298, 0.,
325 'direction': 'forward'})
327 cs.to_reference_transforms.append({
329 # colour.sRGB_COLOURSPACE.RGB_to_XYZ_matrix
330 'matrix': [0.41238656, 0.35759149, 0.18045049, 0.0,
331 0.21263682, 0.71518298, 0.0721802 , 0.0,
332 0.01933062, 0.11919716, 0.95037259, 0.0,
334 'direction': 'forward'})
336 # D65 -> D50 adaption
338 # colour.chromatic_adaptation_matrix_VonKries(
339 # colour.xy_to_XYZ(c.sRGB_COLOURSPACE.whitepoint),
340 # colour.xy_to_XYZ(colour.ILLUMINANTS[
341 # 'CIE 1931 2 Degree Standard Observer']['D50']), 'CAT02')
344 cs.to_reference_transforms.append({
346 'matrix': [1.04251352, 0.03083262, -0.05276445, 0.0,
347 0.0221519 , 1.00187227, -0.02105432, 0.0,
348 -0.00116356, -0.00341802, 0.76197255, 0.0,
350 'direction': 'forward'})
352 if variant == ('XYZ'):
353 cs.from_reference_transforms = []
356 if variant == ('Calibrated'):
358 wb[0] = 1/calibration_wb[style][0]
359 wb[5] = 1/calibration_wb[style][1]
360 wb[10] = 1/calibration_wb[style][2]
362 cs.to_reference_transforms.append({
365 'direction': 'forward'})
367 # calibrat_matrices = clibration_matrices_argyll
369 cs.to_reference_transforms.append({
371 'matrix': (calibration_matrices[style][0] + [0.0] +
372 calibration_matrices[style][1] + [0.0] +
373 calibration_matrices[style][2] + [0.0] +
375 'direction': 'forward'})
377 # D50 -> ACES WP (~D60)
379 # colour.chromatic_adaptation_matrix_VonKries(
380 # colour.xy_to_XYZ(colour.ILLUMINANTS[
381 # 'CIE 1931 2 Degree Standard Observer']['D50']),
382 # colour.xy_to_XYZ(colour.ACES_2065_1_COLOURSPACE.whitepoint),
385 cs.to_reference_transforms.append({
387 'matrix': [ 9.71197151e-01, -2.17328334e-02, 4.59761326e-02, 0.0,
388 -1.56890302e-02, 1.00002082e+00, 1.83070138e-02, 0.0,
389 9.70076767e-04, 3.08175255e-03, 1.21767128e+00, 0.0,
391 'direction': 'forward'})
396 # colour.ACES_2065_1_COLOURSPACE.XYZ_to_RGB_matrix
397 cs.to_reference_transforms.append({
399 'matrix': [1.04981102e+00, 0.00000000e+00, -9.74845410e-05, 0.,
400 -4.95903023e-01, 1.37331305e+00, 9.82400365e-02, 0.,
401 0.00000000e+00, 0.00000000e+00, 9.91252022e-01, 0.,
403 'direction': 'forward'})
406 # matrix given py panasonic / calculated by nuke
407 # for one step transformation:
410 # if gamut == 'V-Log':
411 # cs.to_reference_transforms.append({
413 # 'matrix': [0.724383 , 0.166748 , 0.108497, 0.,
414 # 0.021354 , 0.985138 , -0.006319, 0.,
415 # -0.009234 , -0.001043 , 1.010273, 0.,
417 # 'direction': 'forward'})
419 # cs.to_reference_transforms.append({
421 # 'matrix': [0.43964687, 0.38298151, 0.17737158, 0.0,
422 # 0.08978026, 0.81343973, 0.09677973, 0.0,
423 # 0.01754464, 0.11155707, 0.87089837, 0.0,
425 # 'direction': 'forward'})
427 cs.from_reference_transforms = []
431 def create_colorspaces(lut_directory, lut_resolution_1d):
433 Generates the colorspace conversions.
437 lut_directory : str or unicode
438 The directory to use when generating LUTs
439 lut_resolution_1d : int
440 The resolution of generated 1D LUTs
445 A list of colorspaces for Panasonic cameras and encodings
450 styles_sort = styles.keys()
453 for style in styles_sort:
456 style_1 = create_gh4_style(
461 ['gh4_%s_gh4_gamut' % style.lower().replace('-','_')])
462 colorspaces.append(style_1)
465 style_2 = create_gh4_style(
470 ['crv_gh4_%s' % style.lower().replace('-','_')])
471 colorspaces.append(style_2)
473 # Linearization and XYZ conversion
474 style_3 = create_gh4_style(
479 ['gh4_%s_xyz' % style.lower().replace('-','_')],
481 colorspaces.append(style_3)
484 style_4 = create_gh4_style(
489 ['lin_gh4_%s_gamut' % style.lower().replace('-','_')])
490 colorspaces.append(style_4)
494 # Full conversion calibrated
495 style_5 = create_gh4_style(
500 ['gh4_%s_gh4_calibrated_gamut'% style.lower().replace('-','_')],
502 variant='Calibrated')
503 colorspaces.append(style_5)
505 # Primaries Only calibrated
506 style_6 = create_gh4_style(
507 '%s-Calibrated' % style,
511 ['lin_gh4_%s_calibrated_gamut'%style.lower().replace('-','_')],
513 variant='Calibrated')
514 colorspaces.append(style_6)