Mid-August progress report

As outlined in the project proposal, the original plan was to implement at least two new spectral upsampling methods in Colour. Here's an overview of work done so far:

Jakob and Hanika (2019)

I've already written about this in detail here. The code was merged upstream.

Otsu et al. (2018)

This is a very interesting and quite complicated method that I covered in a four-part series of blog posts. The code for it is complete:

  • A new sub-module, colour.recovery.otsu2018.
  • XYZ_to_sd_otsu2018 provides a familiar interface for upsampling given XYZ tristimulus values.
  • Otsu2018Dataset allows reading and writing datasets to and from files, and can be passed to the upsampling function if one wishes to use their own data.
  • Otsu2018Tree represents kd-trees, as described in the original article. With this, one can create an optimized clustering from an arbitrary set of spectra. This should even work with emission spectra, though I haven't tested it yet. The code could also be extended to support more (or fewer) than three principal components, turning it into a more general, spectral representation method.
  • As usual, everything is well documented and unit tested.

The pull request is awaiting review.

Mallett and Yuksel (2019)

This method seeks to create reflectivities $\mathbf s_r$, $\mathbf s_g$, $\mathbf s_b$ that match RGB primaries. and use them for reconstruction. Given an $(r, g, b)$ triplet, the recovered spectrum is simply:

$$\mathbf s = r\mathbf s_r + g\mathbf s_g + b\mathbf s_b$$

For this to work, the basis reflectivites have to obey a few constraints:

  • They must color-match RGB primaries, ie. have RGB values of [1, 0, 0], [0, 1, 0] and [0, 0, 1].
  • They must sum up to an all-ones spectrum (100% reflectivity at all wavelengths), so that pure white can be recovered correctly.
  • None of them can have values outside [0, 1].
  • They must minimize a chosen scalar function, e.g. one quantizing “roughness,” so that the spectra are smooth and noisy solutions are avoided.

The code for this is surprisingly straightforward, thanks to SciPy's excellent interface to constrained and bounded optimization.

A quick overview of the code:

  • A new sub-module, colour.recovery.mallett2019.
  • sRGB_to_sd_mallett2019 implements upsampling of sRGB colors.
  • RGB_to_sd_mallett2019 can work with any RGB colorspace given the correct basis.
  • spectral_primary_decomposition_Mallett2019 implements the optimization process.

The pull request is awaiting review.

Peters et al. (2019)

The article, as its title suggests, primarily deals with the problem of representing spectra. To make a long story short, it's a compression algorithm that uses fancy math to store measured spectra using only a few, low-bitcount coefficients. It can be used for spectral upsampling by pre-computing a large table of those coefficients. The results aren't that great, though. The method is easily outperformed by e.g. Otsu, et al. (2018), as measured by the authors themselves. It was decided it wasn't the best fit for colour.recovery.

What's next?

There are no more spectral upsampling methods left to implement. Once the remaining pull requests are reviewed and merged, the New Spectral Upsampling Methods project will be concluded.

There's still some time left though and I'm not planning on slacking off for the rest of August. Thomas proposed that I work on New Colour Quality Metrics and I agreed. I'll leave the rest of the details for another post.