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] = calibration_wb[style][0]
359 # wb[5] = calibration_wb[style][1]
360 # wb[10] = calibration_wb[style][2]
362 # cs.to_reference_transforms.append({
365 # 'direction': 'forward'})
366 cs.to_reference_transforms.append({
368 'matrix': (calibration_matrices[style][0] + [0.0] +
369 calibration_matrices[style][1] + [0.0] +
370 calibration_matrices[style][2] + [0.0] +
372 'direction': 'forward'})
374 # D50 -> ACES WP (~D60)
376 # colour.chromatic_adaptation_matrix_VonKries(
377 # colour.xy_to_XYZ(colour.ILLUMINANTS[
378 # 'CIE 1931 2 Degree Standard Observer']['D50']),
379 # colour.xy_to_XYZ(colour.V_GAMUT_COLOURSPACE.whitepoint),
382 cs.to_reference_transforms.append({
384 'matrix': [ 0.95991641, -0.02931741, 0.06566143, 0.0,
385 -0.02119542, 0.99887268, 0.02613247, 0.0,
386 0.00137075, 0.00443593, 1.31260073, 0.0,
388 'direction': 'forward'})
393 # colour.ACES_2065_1_COLOURSPACE.XYZ_to_RGB_matrix
394 cs.to_reference_transforms.append({
396 'matrix': [1.04981102e+00, 0.00000000e+00, -9.74845410e-05, 0.,
397 -4.95903023e-01, 1.37331305e+00, 9.82400365e-02, 0.,
398 0.00000000e+00, 0.00000000e+00, 9.91252022e-01, 0.,
400 'direction': 'forward'})
403 # matrix given py panasonic / calculated by nuke
404 # for one step transformation:
407 # if gamut == 'V-Log':
408 # cs.to_reference_transforms.append({
410 # 'matrix': [0.724383 , 0.166748 , 0.108497, 0.,
411 # 0.021354 , 0.985138 , -0.006319, 0.,
412 # -0.009234 , -0.001043 , 1.010273, 0.,
414 # 'direction': 'forward'})
416 # cs.to_reference_transforms.append({
418 # 'matrix': [0.43964687, 0.38298151, 0.17737158, 0.0,
419 # 0.08978026, 0.81343973, 0.09677973, 0.0,
420 # 0.01754464, 0.11155707, 0.87089837, 0.0,
422 # 'direction': 'forward'})
424 cs.from_reference_transforms = []
428 def create_colorspaces(lut_directory, lut_resolution_1d):
430 Generates the colorspace conversions.
434 lut_directory : str or unicode
435 The directory to use when generating LUTs
436 lut_resolution_1d : int
437 The resolution of generated 1D LUTs
442 A list of colorspaces for Panasonic cameras and encodings
447 styles_sort = styles.keys()
450 for style in styles_sort:
453 style_1 = create_gh4_style(
458 ['gh4_%s_gh4_gamut' % style.lower().replace('-','_')])
459 colorspaces.append(style_1)
462 style_2 = create_gh4_style(
467 ['crv_gh4_%s' % style.lower().replace('-','_')])
468 colorspaces.append(style_2)
470 # Linearization and XYZ conversion
471 style_3 = create_gh4_style(
476 ['gh4_%s_xyz' % style.lower().replace('-','_')],
478 colorspaces.append(style_3)
481 style_4 = create_gh4_style(
486 ['lin_gh4_%s_gamut' % style.lower().replace('-','_')])
487 colorspaces.append(style_4)
491 # Full conversion calibrated
492 style_5 = create_gh4_style(
497 ['gh4_%s_gh4_calibrated_gamut'% style.lower().replace('-','_')],
499 variant='Calibrated')
500 colorspaces.append(style_5)
502 # Primaries Only calibrated
503 style_6 = create_gh4_style(
504 '%s-Calibrated' % style,
508 ['lin_gh4_%s_calibrated_gamut'%style.lower().replace('-','_')],
510 variant='Calibrated')
511 colorspaces.append(style_6)
516 calibration_matrices = {
518 'Cinelike-D': [[1.165504, 0.251869, -0.118313],
519 [-0.369525, 1.80097, -0.096786],
520 [-0.05245, 0.097669, 1.326889]],
521 'Cinelike-V': [[1.060891, 0.353566, -0.102382],
522 [-0.460172, 1.927755, -0.122295],
523 [-0.129601, 0.137134, 1.373328]],
524 'Custom': [[0.946141, 0.485274, -0.087787],
525 [-0.555203, 2.05073, -0.100206],
526 [-0.128126, 0.12821, 1.426733]],
527 'Natural': [[0.874551, 0.439286, -0.085863],
528 [-0.516138, 1.916301, -0.11907],
529 [-0.071172, 0.056567, 1.347203]],
530 'Portrait': [[0.660386, 0.650877, -0.060211],
531 [-0.600758, 1.998228, -0.085769],
532 [-0.110666, 0.124363, 1.339439]],
533 'Scenery': [[0.812315, 0.534553, -0.098869],
534 [-0.542253, 1.934419, -0.071867],
535 [-0.123626, 0.142352, 1.292352]],
536 'Standard': [[0.886056, 0.415669, -0.073317],
537 [-0.482919, 1.84707, -0.088924],
538 [-0.117718, 0.126855, 1.321097]],
539 'V-Log': [[1.127527, 0.284008, -0.033005],
540 [-0.192653, 1.619262, -0.030388],
541 [-0.080181, 0.057527, 1.39992]],
542 'Vivid': [[0.754924, 0.526196, -0.061668],
543 [-0.503233, 1.851748, -0.065254],
544 [-0.197153, 0.267533, 1.212053]]