在HSV / HSB中淡出更多天然彩虹光谱

时间:2011-03-02 01:31:55

标签: colors rgb hsv

我正在尝试控制一些RGB LED并从红色渐变为紫色。我正在使用HSV到RGB的转换,这样我就可以从色调0扫到色调300(除此之外它会向红色移动)。我注意到的问题是它似乎在光谱的青色和蓝色部分花了很长时间。所以我查看了HSV频谱的样子,发现了这个L

enter image description here

我没有意识到超过一半的光谱花费在绿色和蓝色之间。

但我真的希望它看起来更像这样:

enter image description here

与“标准”彩虹色相得益彰。 我想这会最终成为正常色调值的某种曲线,但我不确定如何计算该曲线。

在内部处理这种情况的实际HSV到RGB算法会很棒(任何代码都是真的,虽然它适用于Arduino)但是,即使只是解释我如何计算色调曲线也会非常感激。

2 个答案:

答案 0 :(得分:2)

http://www.fourmilab.ch/documents/specrend/详细描述了如何将波长转换为CIE组件(大致对应于您眼中三种锥形传感器的输出),然后如何将这些转换为RGB值(警告某些波长在典型的RGB色域中 RGB等效物。)

或者:有各种“感知上均匀的颜色空间”,如CIE L * a * b *(参见例如http://en.wikipedia.org/wiki/Lab_color_space);你可以选择其中一个,沿着一条直线连接你在该空间中的起始和结束颜色,并转换为RGB。

但是,对于你的应用程序来说,这些中的任何一个都可能是过度的,并且没有明显的理由说明为什么它们应该更多 - 或者说 - 更好 - 比简单和纯粹的经验更好。那么为什么不这样做呢?

  1. 选择您的开始和结束颜色。为简单起见,我们假设它们在HSV空间中具有S = 1和V = 1。记下来。
  2. 查看您发布的色调“光谱”,找到一个颜色,在您的起点和终点之间找到一半。请注意这一点。
  3. 再次平分:在开始和中间之间找到颜色,在中间和结束之间找到颜色。
  4. 重复一次或两次以上,以便将色调比例分为8或16“感知上相等”的部分。
  5. 转换为RGB,将它们粘贴在查找表中,并在它们之间进行线性插值。
  6. 稍微调整RGB值,直到看起来很好。
  7. 这完全是临时的,并没有任何关于它的原则,但它可能工作得很好,最终的代码基本上是微不足道的:

    void compute_rgb(int * rp, int * gp, int * bp, int t) {
      // t in the range 0..255 (for convenience)
      int segment = t>>5; // 0..7
      int delta = t&31;
      int a=rgb_table[segment].r, b=rgb_table[segment+1].r;
      *rp = a + ((delta*(b-a))>>5);
      a=rgb_table[segment].g; b=rgb_table[segment+1].g;
      *gp = a + ((delta*(b-a))>>5);
      a=rgb_table[segment].b; b=rgb_table[segment+1].b;
      *bp = a + ((delta*(b-a))>>5);
    }
    

    (如果你不关心保存每个可用周期,你可以使代码更清晰。)

    对于它的价值,我的眼睛将分割点设置为大约(0),40,60,90,150,180,240,270,(300)的色调值。您的里程可能会有所不同。

答案 1 :(得分:1)

FastLED执行以下操作:https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors

Fast LED HSV

HSLUV是另一种选择:http://www.hsluv.org/。他们有多种不同语言的库。

HSLUV

此外,这是一种有趣的技术:https://www.shadertoy.com/view/4l2cDm

const float tau = acos(-1.)*2.;

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy / iResolution.xy;

    vec3 rainbow = sqrt( //gamma
        sin( (uv.x+vec3(0,2,1)/3.)*tau ) * .5 + .5
    );

    fragColor.rgb = rainbow;
}

enter image description here

另请参阅: https://en.wikipedia.org/wiki/Rainbow#Number_of_colours_in_spectrum_or_rainbow了解更多信息。