From 33278ad88f8290054aa2b421182019b9167f50ff Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Sun, 21 Jun 2020 18:41:07 +0200 Subject: Move the solver to Colour and update all tests --- test_coverage.py | 112 ++++++++++++++++++++++--------------------------------- 1 file changed, 44 insertions(+), 68 deletions(-) (limited to 'test_coverage.py') diff --git a/test_coverage.py b/test_coverage.py index 90e3c79..ee519f4 100644 --- a/test_coverage.py +++ b/test_coverage.py @@ -1,99 +1,75 @@ -import numpy as np, os, multiprocessing +import numpy as np +import multiprocessing from colour import * from colour.models import eotf_inverse_sRGB -from gsoc_common import D65, D65_xy, jakob_hanika, model_sd, plot_comparison - +from colour.recovery import coefficients_Jakob2019 +from gsoc_common import model_sd, D65, D65_xy, plot_comparison +# Solve for a specific RGB color +def optimize_RGB(linear_RGB, coeffs_0): + RGB = eotf_inverse_sRGB(linear_RGB) + XYZ = sRGB_to_XYZ(RGB, D65_xy) -# 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 + coeffs, error = coefficients_Jakob2019( + XYZ, + dimensionalise=False, + coefficients_0=coeffs_0 + ) + if error > 1e-6: + with open("out/bad.txt", "a") as fd: + fd.write("\n") + fd.write("linear_RGB=%s\n" % linear_RGB) + fd.write("XYZ=%s\n" % XYZ) + fd.write("coeffs_0=%s\n" % coeffs_0) + fd.write("coeffs=%s, error=%g\n" % (coeffs, error)) + # A low budget graph to quickly see what's going on + log_error = np.log10(error) + bars = "|" * max(0, int(5 * (log_error + 9))) -# Solve for a specific RGB color -def optimize_RGB(linear_RGB, ccp0): - RGB = eotf_inverse_sRGB(linear_RGB) - target = sRGB_to_XYZ(RGB, D65_xy) - ccp, error = jakob_hanika(target, D65, D65_xy, ccp0, verbose=False) - if error > 0.1: - print("WARNING: convergence failed with L=%s, starting from %s" - % (linear_RGB, ccp0)) - - return ccp, error + print("%12.5g %12.5g %12.5g %5.3f %s" % (*XYZ, log_error, bars)) + return coeffs # Solve for all lightness values of a fully saturated RGB color -def optimize_chromaticity(argv): - linear_RGB, dirname = argv - +def optimize_chromaticity(linear_RGB): # 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) + steps = np.arange(0, LIGHTNESS_STEPS) + alphas = smoothstep(smoothstep(steps / LIGHTNESS_STEPS)) - 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") + i_mid = LIGHTNESS_STEPS // 5 + coeffs_mid = optimize_RGB(linear_RGB * alphas[i_mid], (0, 0, 0)) - return ccp, error - - - i_mid = LIGHTNESS_STEPS // 2 - ccps[i_mid, :], _ = f(aa[i_mid], (0, 0, 0)) - - ccp0 = ccps[i_mid, :] + coeffs_0 = coeffs_mid for i in range(i_mid + 1, LIGHTNESS_STEPS): - ccps[i, :], _ = f(aa[i], ccp0) + coeffs_0 = optimize_RGB(linear_RGB * alphas[i], coeffs_0) - ccp0 = ccps[i_mid, :] + coeffs_0 = coeffs_mid for i in reversed(range(0, i_mid)): - ccps[i, :], _ = f(aa[i], ccp0) + coeffs_0 = optimize_RGB(linear_RGB * alphas[i], coeffs_0) -# 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). +# This program runs XYZ_to_sd_Jakob2019 converges on a large number of inputs, +# covering an entire RGB gamut, to see if it'll diverge somewhere. if __name__ == "__main__": - args = [] + CHROMA_STEPS = 8 + LIGHTNESS_STEPS = 64 + + with open("out/bad.txt", "w") as fd: + fd.write("Going through %dx%dx%d cubes\n" + % (LIGHTNESS_STEPS, CHROMA_STEPS, CHROMA_STEPS)) - done = 0 - total = 0 + args = [] 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)) + args.append(RGB) pool = multiprocessing.Pool() pool.map(optimize_chromaticity, args) -- cgit