Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def f_df(omega):
omega = numpy.full_like(ap, omega)
cbrt_RGB = numpy.array([omega, omega + ap, omega + bp])
# A = numpy.array([[-13.7, 17.7, -4], [1.7, 8, -9.7], [0.0, 1.0, 0.0]])
# Ainv = numpy.linalg.inv(A)
# rhs = numpy.array(
# [numpy.full(omega.shape, a), numpy.full(omega.shape, b), omega]
# )
# cbrt_RGB = dot(Ainv, rhs)
# # a = -13.7 * numpy.cbrt(R) + 17.7 * numpy.cbrt(G) - 4 * numpy.cbrt(B)
# # b = 1.7 * numpy.cbrt(R) + 8 * numpy.cbrt(G) - 9.7 * numpy.cbrt(B)
RGB = cbrt_RGB ** 3
xyz100 = dot(self.Minv, RGB)
X, Y, Z = xyz100
sum_xyz = numpy.sum(xyz100, axis=0)
x = X / sum_xyz
y = Y / sum_xyz
K = (
4.4934 * x ** 2
+ 4.3034 * y ** 2
- 4.276 * x * y
- 1.3744 * x
- 2.5643 * y
+ 1.8103
)
f = Y * K - Y0
# df/domega
# no 0.305
p2_ = A / cs.N_bb
# Step 3: Calculate a and b
# ENH Much more straightforward computation of a, b
p1_ = e_t * 50000 / 13 * cs.N_c * cs.N_cb
sinh = numpy.sin(h * numpy.pi / 180)
cosh = numpy.cos(h * numpy.pi / 180)
a, b = numpy.array([cosh, sinh]) * (
23 * (p2_ + 0.305) * t / (23 * p1_ + 11 * t * cosh + 108 * t * sinh)
)
# Step 4: Calculate RGB_a_
rgb_a_ = (
dot(
numpy.array([[460, 451, 288], [460, -891, -261], [460, -220, -6300]]),
numpy.array([p2_, a, b]),
)
/ 1403
)
# Step 5: Calculate RGB_
t = numpy.array(
[
1.0
if cs.F_L == numpy.inf
else ((27.13 * abs(r)) / (400 - abs(r))) ** (1 / 0.42) / cs.F_L
for r in rgb_a_
]
)
rgb_ = numpy.sign(rgb_a_) * 100 * t
y = Y / sum_xyz
K = (
4.4934 * x ** 2
+ 4.3034 * y ** 2
- 4.276 * x * y
- 1.3744 * x
- 2.5643 * y
+ 1.8103
)
f = Y * K - Y0
# df/domega
# dcbrt_RGB = 1.0
# dRGB = 3 * cbrt_RGB ** 2 * dcbrt_RGB
dRGB = 3 * cbrt_RGB ** 2
dxyz100 = dot(self.Minv, dRGB)
dX, dY, dZ = dxyz100
dsum_xyz = numpy.sum(dxyz100, axis=0)
dx = (dX * sum_xyz - X * dsum_xyz) / sum_xyz ** 2
dy = (dY * sum_xyz - Y * dsum_xyz) / sum_xyz ** 2
dK = (
4.4934 * 2 * x * dx
+ 4.3034 * 2 * y * dy
- 4.276 * (dx * y + x * dy)
- 1.3744 * dx
- 2.5643 * dy
)
df = dY * K + Y * dK
return f, df, xyz100
def from_xyz100(self, xyz):
# x, y, z = (xyz.T / self.whitepoint).T
# In nit units, ranging from 0 to 10000?
x, y, z = xyz
x_ = self.b * x - (self.b - 1) * z
y_ = self.g * y - (self.g - 1) * x
lms = dot(self.M1, [x_, y_, z])
lms_ = (
(self.c1 + self.c2 * (lms / 10000) ** self.n)
/ (1 + self.c3 * (lms / 10000) ** self.n)
) ** self.p
iz, az, bz = dot(self.M2, lms_)
jz = (1 + self.d) * iz / (1 + self.d * iz) - self.d0
return numpy.array([jz, az, bz])
# Omit the 0.1 here; that's canceled out in almost all cases below anyways (except
# the computation of `t`).
# Deal with alpha == 0, alpha == inf
beta = numpy.empty(alpha.shape)
idx = alpha < 1.0
beta[idx] = alpha[idx] / (alpha[idx] + 27.13) # + 0.1
idx = ~idx
beta[idx] = 1.0 / (1.0 + 27.13 / alpha[idx]) # + 0.1
rgb_a_ = numpy.sign(rgb_) * 400 * beta # + 0.1
# Mix steps 5, 7, and part of step 10 here in one big dot-product.
# Step 5: Calculate Redness-Greenness (a) , Yellowness-Blueness (b)
# components and hue angle (h)
# Step 7: Calculate achromatic response A
a, b, p2_, u = dot(
numpy.array([[11, -12, 1], [1, 1, -2], [40, 20, 1], [20, 20, 21]]), rgb_a_
)
a /= 11
b /= 9
p2_ /= 20
u /= 20
A = p2_ * cs.N_bb
if numpy.any(A < 0):
raise NegativeAError("CIECAM02 breakdown")
# Make sure that h is in [0, 360]
h = numpy.rad2deg(numpy.arctan2(b, a)) % 360
# Step 6: Calculate eccentricity (e_t) and hue composition (H), using the unique hue
# data given in Table 2.4.
def from_xyz100(self, xyz):
# x, y, z = (xyz.T / self.whitepoint).T
# In nit units, ranging from 0 to 10000?
x, y, z = xyz
x_ = self.b * x - (self.b - 1) * z
y_ = self.g * y - (self.g - 1) * x
lms = dot(self.M1, [x_, y_, z])
lms_ = (
(self.c1 + self.c2 * (lms / 10000) ** self.n)
/ (1 + self.c3 * (lms / 10000) ** self.n)
) ** self.p
iz, az, bz = dot(self.M2, lms_)
jz = (1 + self.d) * iz / (1 + self.d * iz) - self.d0
return numpy.array([jz, az, bz])
def from_xyz100(self, xyz):
# Step 1: Calculate (sharpened) cone responses (transfer
# colour-matching functions to sharper sensors)
#
# Step 2: Calculate the corresponding (sharpened) cone response
# (considering various luminance level and surround conditions
# included in D; hence, in DR, DG and DB)
#
# Step 3: Calculate the Hunt-Pointer-Estevez response
rgb_ = dot(self.M_, xyz)
# Steps 4-10
return compute_from(rgb_, self)
def from_rec2100(self, rgb):
lms = dot(self.M1, rgb)
lms_ = (
(self.c1 + self.c2 * lms ** self.m1) / (1 + self.c3 * lms ** self.m1)
) ** self.m2
ictcp = dot(self.M2, lms_)
return ictcp
def from_xyz100(self, xyz):
# First, the stimuli xyz are translated into reference stimuli xyz_ref to
# account for the environment adaptation of the human visual system.
lms_dash = (self.a_lms * dot(self.M, xyz).T).T
xyz_ref = dot(self.R, lms_dash)
x_ref_s, y_ref_s, z_ref_s = xyz_ref ** self.sigma
# LR represents an achromatic response analogous to CIELAB L*. The redgreen
# chromatic response is given by a R (analogous to CIELAB a*) and the
# yellow–blue chromatic response is given by bR (analogous to CIELAB b*).
L_R = 100 * y_ref_s
a_R = 430 * (x_ref_s - y_ref_s)
b_R = 170 * (y_ref_s - z_ref_s)
return numpy.array([L_R, a_R, b_R])