disco / utils /cielab.py
menghanxia's picture
upload whole project
b3640b9
from functools import partial
import numpy as np
class ABGamut:
RESOURCE_POINTS = "./utils/gamut_pts.npy"
RESOURCE_PRIOR = "./utils/gamut_probs.npy"
DTYPE = np.float32
EXPECTED_SIZE = 313
def __init__(self):
self.points = np.load(self.RESOURCE_POINTS).astype(self.DTYPE)
self.prior = np.load(self.RESOURCE_PRIOR).astype(self.DTYPE)
assert self.points.shape == (self.EXPECTED_SIZE, 2)
assert self.prior.shape == (self.EXPECTED_SIZE,)
class CIELAB:
L_MEAN = 50
AB_BINSIZE = 10
AB_RANGE = [-110 - AB_BINSIZE // 2, 110 + AB_BINSIZE // 2, AB_BINSIZE]
AB_DTYPE = np.float32
Q_DTYPE = np.int64
RGB_RESOLUTION = 101
RGB_RANGE = [0, 1, RGB_RESOLUTION]
RGB_DTYPE = np.float64
def __init__(self, gamut=None):
self.gamut = gamut if gamut is not None else ABGamut()
a, b, self.ab = self._get_ab()
self.ab_gamut_mask = self._get_ab_gamut_mask(
a, b, self.ab, self.gamut)
self.ab_to_q = self._get_ab_to_q(self.ab_gamut_mask)
self.q_to_ab = self._get_q_to_ab(self.ab, self.ab_gamut_mask)
@classmethod
def _get_ab(cls):
a = np.arange(*cls.AB_RANGE, dtype=cls.AB_DTYPE)
b = np.arange(*cls.AB_RANGE, dtype=cls.AB_DTYPE)
b_, a_ = np.meshgrid(a, b)
ab = np.dstack((a_, b_))
return a, b, ab
@classmethod
def _get_ab_gamut_mask(cls, a, b, ab, gamut):
ab_gamut_mask = np.full(ab.shape[:-1], False, dtype=bool)
a = np.digitize(gamut.points[:, 0], a) - 1
b = np.digitize(gamut.points[:, 1], b) - 1
for a_, b_ in zip(a, b):
ab_gamut_mask[a_, b_] = True
return ab_gamut_mask
@classmethod
def _get_ab_to_q(cls, ab_gamut_mask):
ab_to_q = np.full(ab_gamut_mask.shape, -1, dtype=cls.Q_DTYPE)
ab_to_q[ab_gamut_mask] = np.arange(np.count_nonzero(ab_gamut_mask))
return ab_to_q
@classmethod
def _get_q_to_ab(cls, ab, ab_gamut_mask):
return ab[ab_gamut_mask] + cls.AB_BINSIZE / 2
def bin_ab(self, ab):
ab_discrete = ((ab + 110) / self.AB_RANGE[2]).astype(int)
a, b = np.hsplit(ab_discrete.reshape(-1, 2), 2)
return self.ab_to_q[a, b].reshape(*ab.shape[:2])