1

I want to create a color spectrum of constant perceived luminance.

This is my attempt so far (here's the codesandbox):

enter image description here

The code

  • goes through 8-bit RGB values of increasing hue and constant (and irrelevant) lightness,
  • transforms the triples to the corresponding linear values (un-"gamma", code for that taken from here),
  • calculates the luminance by forming the scalar product with the sRGB luminance values,
  • normalized the color by dividing by the luma and finally
  • convert back to 8-bit RGB (re-"gamma").

As I annotated in the image, the second stripe from the bottom has a rather bright blue if you ask me though. Now that could be because

  • my screen is off of sRGB (although my phone agrees),
  • my eyeballs are off the human average,
  • sRGB luminance values don't reflect luminance perception to begin with

I think it's more likely I've made some mistake or haven't understood something here.

I tweaked the sRGB luminance values slightly to get the bottom stripe that is on the verge of being what I would expect (perhaps still a bit bright that blue though).

So my question:

  • What do you guys see on your screens, subjectively? Which of the bottom two stripes do you think is closer to perceived constant brightness?
  • Presuming I'm not the only one, what's wrong here?
4

2 回答 2

3

RGB colourspaces are not perceptually uniform spaces. Generating a perceptually uniform hue stripe requires using a perceptually uniform colourspace or colour appearance model such as ICtCp or CAM16.

With Colour, it could be achieved as follows:

import colour
import numpy as np


def colour_stripe(S=1, samples=360):
    H = np.linspace(0, 1, samples)

    HSV = colour.utilities.tstack([H, np.ones(samples) * S, np.ones(samples)])
    RGB = colour.HSV_to_RGB(HSV)
 
    return RGB[np.newaxis, ...]


RGB = np.resize(colour_stripe(), [36, 360, 3])

colour.plotting.plot_image(colour.cctf_encoding(RGB * 0.5));

CAM16 = colour.convert(RGB, 'RGB', 'CAM16')
CAM16_UL = colour.CAM16_Specification(
    np.full(CAM16.J.shape, 0.5), CAM16.C, CAM16.h)

RGB_PU = colour.convert(CAM16_UL, 'CAM16', 'RGB')

colour.plotting.plot_image(colour.cctf_encoding(RGB_PU));

RGB RGB PU

Keep in mind that the assumptions here are sRGB display calibration and viewing conditions.

于 2020-08-01T05:32:17.587 回答
1

It depends on what you want "perceived luminance" to model. When you consider the Helmholtz-Kohlrausch effect, NOT modeled by CAM02, you should see that you need to decide on a model or a range of colour appearance effects you would like your model to fit.

https://en.wikipedia.org/wiki/Helmholtz%E2%80%93Kohlrausch_effect

于 2020-08-10T06:00:01.483 回答