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, legal_range=False, debug_plot=False):
175 # 18% gray card exposure offset
178 exp = np.linspace( (corr-39)/3.0, corr/3.0, 40)
179 l = np.power(2, exp) * 0.18
180 vals = np.array(styles[style])
182 vals = vals/255.0 * (235-16)/255.0 + 16/255.0
186 # remove visible edges at some exposure values
188 for n in [24, 21, 4]:
190 plt.semilogy(vals[n], l[n], 'bx' )
191 vals = np.delete(vals, n)
194 # modify equal values to get an invertable monotone function
195 force_monotone = np.linspace(0,0.00001,len(vals))
196 vals = vals+force_monotone
198 #interp = interpolate.Akima1DInterpolator(vals, l)
199 interp = interpolate.PchipInterpolator(vals, l, extrapolate=False)
202 plt.semilogy(vals, l, 'b+' )
203 x = np.linspace(0., 1.0, 4096)
205 plt.semilogy(x, y, 'r.', ms=1 )
206 x = np.linspace(0., 1.0, 256)
208 plt.semilogy(x, y, 'bo', ms=2 )
214 def create_gh4_style(gamut,
223 Creates colorspace covering the conversion from GH4 picture styles
224 to ACES based on empirical data
229 The name of the encoding gamut to use.
230 transfer_function : str
231 The name of the transfer function to use
232 lut_directory : str or unicode
233 The directory to use when generating LUTs
234 lut_resolution_1d : int
235 The resolution of generated 1D LUTs
236 aliases : list of str
237 Aliases for this colorspace
239 Add legal range shaper
241 Associated Photo Style
243 Variant of processing
248 A ColorSpace container class referencing the LUTs, matrices
249 and identifying information for the requested colorspace.
253 legal_str = 'Legal range '
257 name = ('%sGH4-%s - GH4-%s-Gamut %s' % ( legal_str, transfer_function,
258 gamut, variant)).strip()
259 if transfer_function == '':
260 name = ('Linear - GH4-%s-Gamut %s' % (gamut, variant)).strip()
262 name = 'Curve - %sGH4-%s' % (legal_str, transfer_function)
264 cs = ColorSpace(name)
265 cs.description = name
267 cs.equality_group = ''
268 cs.family = 'Input/Panasonic/GH4 %s' %style
271 # A linear space needs allocation variables
272 if transfer_function == '':
273 cs.allocation_type = ocio.Constants.ALLOCATION_LG2
274 cs.allocation_vars = [-8, 6, 0.00390625]
276 cs.to_reference_transforms = []
278 if transfer_function != '':
281 lut = 'gh4_%s_legal_to_linear.spi1d' % transfer_function.lower()
283 lut = 'gh4_%s_to_linear.spi1d' % transfer_function.lower()
284 f = prepare_photostyle_to_linear(transfer_function, legal_range)
286 dom = np.linspace(0.0, 1.0, lut_resolution_1d)
289 # constant extrapolation
290 data_min = np.nanmin(data)
291 data_max = np.nanmax(data)
292 inds = np.where(np.isnan(data))
294 if i < lut_resolution_1d/2:
301 os.path.join(lut_directory, lut),
308 cs.to_reference_transforms.append({
311 'interpolation': 'linear',
312 'direction': 'forward'})
315 # matrix calculations based on:
316 # http://www.colour-science.org
324 cs.to_reference_transforms.append({
326 # colour.V_GAMUT_COLOURSPACE.RGB_to_XYZ_matrix
327 'matrix': [0.679644, 0.152211, 0.1186 , 0.,
328 0.260686, 0.774894, -0.03558, 0.,
329 -0.00931 , -0.004612, 1.10298, 0.,
331 'direction': 'forward'})
333 cs.to_reference_transforms.append({
335 # colour.sRGB_COLOURSPACE.RGB_to_XYZ_matrix
336 'matrix': [0.41238656, 0.35759149, 0.18045049, 0.0,
337 0.21263682, 0.71518298, 0.0721802 , 0.0,
338 0.01933062, 0.11919716, 0.95037259, 0.0,
340 'direction': 'forward'})
342 # D65 -> D50 adaption
344 # colour.chromatic_adaptation_matrix_VonKries(
345 # colour.xy_to_XYZ(c.sRGB_COLOURSPACE.whitepoint),
346 # colour.xy_to_XYZ(colour.ILLUMINANTS[
347 # 'CIE 1931 2 Degree Standard Observer']['D50']), 'CAT02')
350 cs.to_reference_transforms.append({
352 'matrix': [1.04251352, 0.03083262, -0.05276445, 0.0,
353 0.0221519 , 1.00187227, -0.02105432, 0.0,
354 -0.00116356, -0.00341802, 0.76197255, 0.0,
356 'direction': 'forward'})
358 if variant == ('XYZ'):
359 cs.from_reference_transforms = []
362 if variant == ('Calibrated'):
364 wb[0] = 1/calibration_wb[style][0]
365 wb[5] = 1/calibration_wb[style][1]
366 wb[10] = 1/calibration_wb[style][2]
368 cs.to_reference_transforms.append({
371 'direction': 'forward'})
373 # calibrat_matrices = clibration_matrices_argyll
375 cs.to_reference_transforms.append({
377 'matrix': (calibration_matrices[style][0] + [0.0] +
378 calibration_matrices[style][1] + [0.0] +
379 calibration_matrices[style][2] + [0.0] +
381 'direction': 'forward'})
383 # D50 -> ACES WP (~D60)
385 # colour.chromatic_adaptation_matrix_VonKries(
386 # colour.xy_to_XYZ(colour.ILLUMINANTS[
387 # 'CIE 1931 2 Degree Standard Observer']['D50']),
388 # colour.xy_to_XYZ(colour.ACES_2065_1_COLOURSPACE.whitepoint),
391 cs.to_reference_transforms.append({
393 'matrix': [ 9.71197151e-01, -2.17328334e-02, 4.59761326e-02, 0.0,
394 -1.56890302e-02, 1.00002082e+00, 1.83070138e-02, 0.0,
395 9.70076767e-04, 3.08175255e-03, 1.21767128e+00, 0.0,
397 'direction': 'forward'})
402 # colour.ACES_2065_1_COLOURSPACE.XYZ_to_RGB_matrix
403 cs.to_reference_transforms.append({
405 'matrix': [1.04981102e+00, 0.00000000e+00, -9.74845410e-05, 0.,
406 -4.95903023e-01, 1.37331305e+00, 9.82400365e-02, 0.,
407 0.00000000e+00, 0.00000000e+00, 9.91252022e-01, 0.,
409 'direction': 'forward'})
412 # matrix given py panasonic / calculated by nuke
413 # for one step transformation:
416 # if gamut == 'V-Log':
417 # cs.to_reference_transforms.append({
419 # 'matrix': [0.724383 , 0.166748 , 0.108497, 0.,
420 # 0.021354 , 0.985138 , -0.006319, 0.,
421 # -0.009234 , -0.001043 , 1.010273, 0.,
423 # 'direction': 'forward'})
425 # cs.to_reference_transforms.append({
427 # 'matrix': [0.43964687, 0.38298151, 0.17737158, 0.0,
428 # 0.08978026, 0.81343973, 0.09677973, 0.0,
429 # 0.01754464, 0.11155707, 0.87089837, 0.0,
431 # 'direction': 'forward'})
433 cs.from_reference_transforms = []
437 def create_colorspaces(lut_directory, lut_resolution_1d):
439 Generates the colorspace conversions.
443 lut_directory : str or unicode
444 The directory to use when generating LUTs
445 lut_resolution_1d : int
446 The resolution of generated 1D LUTs
451 A list of colorspaces for Panasonic cameras and encodings
456 styles_sort = styles.keys()
459 for legal_range in [True, False]:
461 for style in styles_sort:
464 lower_style='%s_legal' % style.lower().replace('-','_')
466 lower_style='%s' % style.lower().replace('-','_')
469 style_1 = create_gh4_style(
474 ['gh4_%s_gh4_gamut' % lower_style],
475 legal_range=legal_range,
477 colorspaces.append(style_1)
480 style_2 = create_gh4_style(
485 ['crv_gh4_%s' % lower_style],
486 legal_range=legal_range,
488 colorspaces.append(style_2)
490 # # Linearization and XYZ conversion
491 # # only necessary for matrix calculation
493 # style_3 = create_gh4_style(
498 # ['gh4_%s_xyz' % lower_style],
499 # legal_range=legal_range,
502 # colorspaces.append(style_3)
505 style_4 = create_gh4_style(
510 ['lin_gh4_%s_gamut' % lower_style],
511 legal_range=legal_range,
514 colorspaces.append(style_4)
518 # Full conversion calibrated
519 style_5 = create_gh4_style(
524 ['gh4_%s_gh4_calibrated_gamut'% lower_style],
525 legal_range=legal_range,
527 variant='Calibrated')
528 colorspaces.append(style_5)
530 # Primaries Only calibrated
531 style_6 = create_gh4_style(
536 ['lin_gh4_%s_calibrated_gamut'%lower_style],
537 legal_range=legal_range,
539 variant='Calibrated')
540 colorspaces.append(style_6)