doevent commited on
Commit
35fa4b8
·
1 Parent(s): 4401a5e

Upload utils/cielab.py

Browse files
Files changed (1) hide show
  1. utils/cielab.py +71 -0
utils/cielab.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from functools import partial
2
+ import numpy as np
3
+
4
+ class ABGamut:
5
+ RESOURCE_POINTS = "./utils/gamut_pts.npy"
6
+ RESOURCE_PRIOR = "./utils/gamut_probs.npy"
7
+ DTYPE = np.float32
8
+ EXPECTED_SIZE = 313
9
+ def __init__(self):
10
+ self.points = np.load(self.RESOURCE_POINTS).astype(self.DTYPE)
11
+ self.prior = np.load(self.RESOURCE_PRIOR).astype(self.DTYPE)
12
+ assert self.points.shape == (self.EXPECTED_SIZE, 2)
13
+ assert self.prior.shape == (self.EXPECTED_SIZE,)
14
+
15
+
16
+ class CIELAB:
17
+ L_MEAN = 50
18
+ AB_BINSIZE = 10
19
+ AB_RANGE = [-110 - AB_BINSIZE // 2, 110 + AB_BINSIZE // 2, AB_BINSIZE]
20
+ AB_DTYPE = np.float32
21
+ Q_DTYPE = np.int64
22
+
23
+ RGB_RESOLUTION = 101
24
+ RGB_RANGE = [0, 1, RGB_RESOLUTION]
25
+ RGB_DTYPE = np.float64
26
+
27
+ def __init__(self, gamut=None):
28
+ self.gamut = gamut if gamut is not None else ABGamut()
29
+ a, b, self.ab = self._get_ab()
30
+ self.ab_gamut_mask = self._get_ab_gamut_mask(
31
+ a, b, self.ab, self.gamut)
32
+
33
+ self.ab_to_q = self._get_ab_to_q(self.ab_gamut_mask)
34
+ self.q_to_ab = self._get_q_to_ab(self.ab, self.ab_gamut_mask)
35
+
36
+ @classmethod
37
+ def _get_ab(cls):
38
+ a = np.arange(*cls.AB_RANGE, dtype=cls.AB_DTYPE)
39
+ b = np.arange(*cls.AB_RANGE, dtype=cls.AB_DTYPE)
40
+ b_, a_ = np.meshgrid(a, b)
41
+ ab = np.dstack((a_, b_))
42
+ return a, b, ab
43
+
44
+ @classmethod
45
+ def _get_ab_gamut_mask(cls, a, b, ab, gamut):
46
+ ab_gamut_mask = np.full(ab.shape[:-1], False, dtype=bool)
47
+ a = np.digitize(gamut.points[:, 0], a) - 1
48
+ b = np.digitize(gamut.points[:, 1], b) - 1
49
+ for a_, b_ in zip(a, b):
50
+ ab_gamut_mask[a_, b_] = True
51
+
52
+ return ab_gamut_mask
53
+
54
+ @classmethod
55
+ def _get_ab_to_q(cls, ab_gamut_mask):
56
+ ab_to_q = np.full(ab_gamut_mask.shape, -1, dtype=cls.Q_DTYPE)
57
+ ab_to_q[ab_gamut_mask] = np.arange(np.count_nonzero(ab_gamut_mask))
58
+
59
+ return ab_to_q
60
+
61
+ @classmethod
62
+ def _get_q_to_ab(cls, ab, ab_gamut_mask):
63
+ return ab[ab_gamut_mask] + cls.AB_BINSIZE / 2
64
+
65
+ def bin_ab(self, ab):
66
+ ab_discrete = ((ab + 110) / self.AB_RANGE[2]).astype(int)
67
+
68
+ a, b = np.hsplit(ab_discrete.reshape(-1, 2), 2)
69
+
70
+ return self.ab_to_q[a, b].reshape(*ab.shape[:2])
71
+