algorithm - Double cone model of HSI Color Space to RGB - Stack Overflow

admin2025-05-02  1

I've come across a rather trigonometric implementation for converting colours from RGB to HSI. In particular, converting from RGB to the "HSI-colour space, given by a double cone", which I presume is another name for the bi-hexcone model of HSL.

The authors describe equations for "their preferred choice of transformation" of RGB-->HSI, which I have implemented in Python as below. Nothing is given the reverse transformation, HSI-->RGB.

def rgb_to_hsi(r, g, b):
    # r, g, b in [0..1]
    x = min(r, g, b)
    y = max(r, g, b)
    I = (x + y) / 2.0
    S = y - x
    c1 = r - (g + b) / 2.0
    c2 = (np.sqrt(3) * (b - g)) / 2.0
    H = np.arctan2(c2, c1)
    H = np.mod(-H, 2 * pi) # re-range to [0..2PI], rotating from red at 0 to green at 2/3PI, etc.

    return [H, S, I] # H in [0..2PI], S in [0..1], I in [0..1]

Both the algorithm and my implementation seem to be correct, and provide results that accord with this diagram (i.e. red (rgb(1,0,0)) gives [0.0, 1, 0.5]):

But I'm unable to find, or derive, a working inverse of this conversion – a hsi_to_rgb() method.

I've tried a few implementations but they tend to map hsi(0.0, 1, 0.5) to rgb(0.5, 0, 0) (red at half brightness, rather than full).

I suspect this is because most HSL implementations use the cylindrical model of HSL, and not the double cone model – is this true?

Either way, what is a working (and ideally trigonometric) algorithm for converts from the HSL double cone model to rgb?

I've come across a rather trigonometric implementation for converting colours from RGB to HSI. In particular, converting from RGB to the "HSI-colour space, given by a double cone", which I presume is another name for the bi-hexcone model of HSL.

The authors describe equations for "their preferred choice of transformation" of RGB-->HSI, which I have implemented in Python as below. Nothing is given the reverse transformation, HSI-->RGB.

def rgb_to_hsi(r, g, b):
    # r, g, b in [0..1]
    x = min(r, g, b)
    y = max(r, g, b)
    I = (x + y) / 2.0
    S = y - x
    c1 = r - (g + b) / 2.0
    c2 = (np.sqrt(3) * (b - g)) / 2.0
    H = np.arctan2(c2, c1)
    H = np.mod(-H, 2 * pi) # re-range to [0..2PI], rotating from red at 0 to green at 2/3PI, etc.

    return [H, S, I] # H in [0..2PI], S in [0..1], I in [0..1]

Both the algorithm and my implementation seem to be correct, and provide results that accord with this diagram (i.e. red (rgb(1,0,0)) gives [0.0, 1, 0.5]):

But I'm unable to find, or derive, a working inverse of this conversion – a hsi_to_rgb() method.

I've tried a few implementations but they tend to map hsi(0.0, 1, 0.5) to rgb(0.5, 0, 0) (red at half brightness, rather than full).

I suspect this is because most HSL implementations use the cylindrical model of HSL, and not the double cone model – is this true?

Either way, what is a working (and ideally trigonometric) algorithm for converts from the HSL double cone model to rgb?

Share Improve this question asked Jan 2 at 2:41 micyclemicycle 3,83017 silver badges34 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

Here you go:

SQRT3BY2 = math.sqrt(3)/2.0

def hsi_to_rgb(H, S, I):
    c2 = math.sin(-H)*SQRT3BY2
    c1 = math.cos(-H)
    # (r,g,b) = A*c1*(1, -.5, -.5) + A*c2*(0, -1, 1) + B*(1,1,1)
    r = c1
    g = c1*-0.5 - c2
    b = c1*-0.5 + c2
    # multiply to match S
    fac = S/(max(r,g,b)-min(r,g,b))
    r *= fac
    g *= fac
    b *= fac
    # add white to match I
    x = I - (S / 2.0)
    w = x - min(r,g,b)
    r += w
    g += w
    b += w
    return [r, g, b]
转载请注明原文地址:http://www.anycun.com/QandA/1746136211a92072.html