-
Notifications
You must be signed in to change notification settings - Fork 0
/
gen_old.py
231 lines (171 loc) · 5.8 KB
/
gen_old.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# -*- coding: utf-8 -*-
"""
Generates previous version(v0.1) of Roseus colormap.
It was originally developed for Audacity spectrogram.
Created on Sat Mar 20 11:54:56 2021
@author: dof
"""
import math
from colorspacious import cspace_convert
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
from scipy.ndimage import filters
from scipy.signal import savgol_filter
'''
J = lightness
C = chroma
h = hue
'''
# Resolution of colorspace
J_RES = 256
C_RES = 256
# NAME = 'So normal'
# ANGLE = np.pi * 2 * 0.7
# OFFSET = np.pi * 2 * 0.64
# CCW = False
# SMOOTH = 1/3
# NAME = 'Wow unique'
# ANGLE = np.pi * 2 * 1.0
# OFFSET = np.pi * 2 * 0.275
# CCW = True
# SMOOTH = 1/2
# NAME = 'Viridis-like (red bg)'
# ANGLE = np.pi * 2 * 1.0
# OFFSET = np.pi * 2 * 0.1
# CCW = True
# SMOOTH = 1/4
# NAME = 'Viridis-like (purple bg)'
# ANGLE = np.pi * 2 * 0.9
# OFFSET = np.pi * 2 * 0.1
# CCW = True
# SMOOTH = 1/5
NAME = 'AudaSpec v0.1'
ANGLE = np.pi * 2 * 0.875
OFFSET = np.pi * 2 * 0.5
CCW = False
SMOOTH = 1/3
DESATURATE = 0.9
# Generate CAM02-UCS(Jp, ap, bp) colorspace
j_space = np.linspace(0.1, 99, J_RES)
c_space = np.linspace(0, 50, C_RES)
if CCW:
h_ = np.linspace(ANGLE+OFFSET, OFFSET, J_RES)
else:
h_ = np.linspace(OFFSET, ANGLE+OFFSET, J_RES)
jpapbp = np.zeros([C_RES, J_RES, 3])
for jdx, jp in enumerate(j_space):
for cdx, chroma in enumerate(c_space):
ap = np.cos(h_[jdx]) * chroma
bp = np.sin(h_[jdx]) * chroma
jpapbp[cdx, jdx] = (jp, ap, bp)
# Convert to sRGB
rgb = cspace_convert(jpapbp, "CAM02-UCS", "sRGB1")
# Get chroma limit of sRGB
c_limit = np.zeros_like(j_space)
for jdx in range(J_RES):
max_cdx = 0
for cdx in range(1, C_RES):
if np.any(rgb[cdx, jdx] <= 0) or np.any(1 < rgb[cdx, jdx]):
max_cdx = cdx - 1
break
c_limit[jdx] = max_cdx
# Smooth chroma limit contour
c_smoothed = np.concatenate([-c_limit[::-1][:-1], c_limit, -c_limit[::-1][1:]])
c_smoothed = savgol_filter(c_smoothed, math.ceil(J_RES*SMOOTH*1.5/2)*2 - 1, 3)
c_smoothed = filters.uniform_filter1d(c_smoothed, int(J_RES*SMOOTH*1.5/2)) * DESATURATE
c_smoothed = c_smoothed[J_RES:2*J_RES]
c_selected = c_smoothed.clip(min=0).astype(int)
# Generate and plot gaumt
gamut_image = np.copy(rgb)
gamut_image[gamut_image<=0] = 1
gamut_image[1<gamut_image] = 0
# Mark smoothed contour on image
for jdx, max_c in enumerate(c_selected):
if 0 == jdx % 2:
gamut_image[max_c, jdx] = 1
else:
gamut_image[max_c, jdx] = 0
plt.figure(figsize=[5, 5])
plt.imshow(gamut_image)
# Get colors on contour
cm_jpapbp = []
for jdx, cdx in enumerate(c_smoothed):
chroma = cdx * 50 / C_RES
jp = j_space[jdx]
ap = np.cos(h_[jdx]) * chroma
bp = np.sin(h_[jdx]) * chroma
cm_jpapbp.append([jp, ap, bp])
cm_rgb = cspace_convert(cm_jpapbp, "CAM02-UCS", "sRGB1")
cm_data = np.clip(cm_rgb, 0, 1)
if __name__ == "__main__":
plt.rcParams['figure.autolayout'] = True
# Display viscm
test_cm = ListedColormap(cm_data, name=NAME)
try:
from roseus.viscm_cam16ucs import viscm
viscm(test_cm)
except ImportError:
print("viscm not found, falling back on simple display")
plt.imshow(np.linspace(0, 100, 256)[None, :], aspect='auto', cmap=test_cm)
# Plot RGB value graph
cm255 = np.asarray(cm_data) * 255
seg_simple = 8
fix, ax = plt.subplots()
plt.plot(cm255[:,0], 'r')
plt.plot(cm255[:,1], 'g')
plt.plot(cm255[:,2], 'b')
plt.plot(np.mean(cm255, axis=1))
ax.set_xticks(np.linspace(0, J_RES, seg_simple+1, endpoint=True))
ax.set_yticks(np.arange(0, 257, 16))
ax.grid(which='both')
plt.show()
# plot gamut
cm_jpapbp = np.asarray(cm_jpapbp)
ax = np.linspace(-45, 45, 1000)
bx = np.linspace(-35, 35, 1000)
ax, bx = np.meshgrid(ax, bx)
phi = np.arctan2(bx, ax)
jx = np.searchsorted(h_, phi+np.pi*2) / J_RES * (99 - 0.1) + 0.1
data = cspace_convert(np.stack([jx, ax, bx], axis=-1), "CAM02-UCS", "sRGB1")
# get sRGB gamut
r = data[..., 0]
g = data[..., 1]
b = data[..., 2]
clipped = np.any([r<0, g<0, b<0, 1<r, 1<g, 1<b], axis=0)
clipped = np.stack([clipped, clipped, clipped], axis=-1)
# gray outside gamut
data[clipped] = 0.4426
fig = plt.subplot()
fig.plot(cm_jpapbp[..., 1], cm_jpapbp[..., 2])
fig.axis('equal')
fig.imshow(data, extent=[ax.min(), ax.max(), bx.max(), bx.min()])
fig.invert_yaxis()
fig.set_title('sRGB color gamut in CAM02-UCS')
fig.set_xlabel("a' (green → red)")
fig.set_ylabel("b' (blue → yellow)")
plt.show()
# Generate uint8 format colormaps
cm_data_u8 = (cm_data*255 + 0.5).astype('uint8')
cm_selected = cm_rgb*0.8 + 0.3
cm_selected_u8 = (np.clip(cm_selected, 0, 1)*255 + 0.5).astype('uint8')
cm_data_JCh = cspace_convert(cm_rgb, "sRGB1", "JCh")
cm_data_JCh[..., 0] += 20 # Boost lightness
cm_data_JCh[..., 1] += 20 # Boost chroma
cm_data_JCh[..., 2] += 90 # Change hue
cm_sel_freq = cspace_convert(cm_data_JCh, "JCh", "sRGB1")
cm_sel_freq_u8 = (np.clip(cm_sel_freq, 0, 1)*255 + 0.5).astype('uint8')
# Save colormaps to C format
with open('AColorResources.h', 'wt') as ofile:
ofile.write('const unsigned char specColormap[%d][3] = {\n' % J_RES)
for r, g, b in cm_data_u8:
ofile.write(' {%3d, %3d, %3d},\n' % (r, g, b))
ofile.write('};\n\n')
ofile.write('const unsigned char selColormap[%d][3] = {\n' % J_RES)
for r, g, b in cm_selected_u8:
ofile.write(' {%3d, %3d, %3d},\n' % (r, g, b))
ofile.write('};\n\n')
ofile.write('const unsigned char freqSelColormap[%d][3] = {\n' % J_RES)
for r, g, b in cm_sel_freq_u8:
ofile.write(' {%3d, %3d, %3d},\n' % (r, g, b))
ofile.write('};\n\n')