diff options
Diffstat (limited to 'test_coverage.py')
-rw-r--r-- | test_coverage.py | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/test_coverage.py b/test_coverage.py new file mode 100644 index 0000000..07ceb08 --- /dev/null +++ b/test_coverage.py @@ -0,0 +1,102 @@ +import numpy as np, os, multiprocessing +from colour import * +from colour.models import eotf_inverse_sRGB +from jakob_hanika import jakob_hanika, model_sd + + + +illuminant = "D65" +ill_xy = ILLUMINANTS["CIE 1931 2 Degree Standard Observer"][illuminant] +ill_sd = SpectralDistribution(ILLUMINANTS_SDS[illuminant]) # Note: changed in dev (to ILLUMINANTS_SD) + +# Resolution of the discretization cubes +# Both should be 64, but this code is a bit too slow at the moment +CHROMA_STEPS = 8 +LIGHTNESS_STEPS = 8 + + + +# Solve for a specific RGB color +def optimize_RGB(linear_RGB, ccp0): + RGB = eotf_inverse_sRGB(linear_RGB) + target = sRGB_to_XYZ(RGB, ill_xy) + ccp, error = jakob_hanika(target, ill_sd, ill_xy, ccp0, verbose=False) + if error > 0.1: + print("WARNING: convergence failed with L=%s, starting from %s" \ + % (linear_RGB, ccp0)) + + return ccp, error + +# Solve for all lightness values of a fully saturated RGB color +def optimize_chromaticity(argv): + linear_RGB, dirname = argv + + # alpha's aren't spaced equally (see the article) + def smoothstep(x): + return x**2 * (3 - 2 * x) + + ii = np.arange(0, LIGHTNESS_STEPS) + aa = smoothstep(smoothstep(ii / LIGHTNESS_STEPS)) + ccps = np.empty((LIGHTNESS_STEPS, 3)) # FIXME: dtype? + + def f(alpha, ccp0): + path = "%s/%.3f" % (dirname, alpha) + print("%s..." % path) + + ccp, error = optimize_RGB(linear_RGB * alpha, ccp0) + + try: + os.makedirs(os.path.dirname(path)) + except: + pass + with open(path, "w") as fd: + fd.write("%s, %s" % (ccp, error)) + if error > 0.1: + fd.write(" FAILED") + fd.write("\n") + + return ccp, error + + + i_mid = LIGHTNESS_STEPS // 2 + ccps[i_mid, :], _ = f(aa[i_mid], (0, 0, 0)) + + ccp0 = ccps[i_mid, :] + for i in range(i_mid + 1, LIGHTNESS_STEPS): + ccps[i, :], _ = f(aa[i], ccp0) + + ccp0 = ccps[i_mid, :] + for i in reversed(range(0, i_mid)): + ccps[i, :], _ = f(aa[i], ccp0) + + + +# This demo discretizes the sRGB space to three 8x8x8 cubes and tries to find +# the model parameters for all the colors. Coefficients are saved to a file +# somewhere in the 'out' directory (each color gets its own file). +# FIXME: This dumpster fire of an output format is to be replaced ASAP. +# FIXME: This takes a good while (on the order of an hour). +if __name__ == "__main__": + args = [] + + done = 0 + total = 0 + for A in np.linspace(0, 1, CHROMA_STEPS): + for B in np.linspace(0, 1, CHROMA_STEPS): + for RGB in [np.array([1, A, B]), + np.array([A, 1, B]), + np.array([A, B, 1])]: + + dirname = "out/R%.3fG%.3fB%.3f" % (*RGB,) + total += 1 + + if os.path.exists(dirname) and len(os.listdir(dirname)) == LIGHTNESS_STEPS: + done += 1 + continue + + args.append((RGB, dirname)) + + print("%d/%d already done" % (done, total)) + + pool = multiprocessing.Pool() + pool.map(optimize_chromaticity, args) |