色调到波长映射

时间:2012-08-07 16:19:15

标签: matlab image-processing colors

是否有算法可以在给定色调值(0度到360度)之间找出颜色的波长。 MATLAB中是否有相同的内置函数?

6 个答案:

答案 0 :(得分:9)

尽管Mark Ransom和Franco Callari是完全正确的,你无法恢复感知颜色的光谱,也没有明确地将色调值映射到波长,如果你只想要相应的单色波长,你肯定可以拼凑一些东西。

270到360之间的色调周期部分是另一个问题。在光谱中没有与品红色相对应的东西,所以我们假设我们只使用0到270之间的色调值。

估计可见光谱的可用部分为450-620nm,波长为L(以nm为单位),色调值为H(以度为单位),您可以即兴发挥:

 L = 620 - 170 / 270 * H

620是最大波长,170是波长范围,270是色调范围。

我认为这应该是正确的方向,但我只检查了4或5种颜色。您可以在输入huesvisible spectrum chart上的相应颜色之间进行比较,然后稍微调整值,从而获得更好的结果。

答案 1 :(得分:0)

简短回答:不。给定的色调一般可以通过三个无限波长产生。

答案 2 :(得分:0)

我无法提供简单的解决方案,但您需要考虑以下事项:

  • spektrum的可见部分大致在380nm(UV边界)和780nm(IR边界)之间。但你所看到的(色调)取决于触发的锥细胞。在660nm以上,M锥体根本不被触发,因此660nm和780nm之间的所有物都是0°的色调。
  • 在580nm处有黄色,色调为60°,最纯的绿色为约535nm,因此为120°,最纯的蓝色(240°)为约457nm。
  • 如果你应用线性函数,黄色应该是597nm - 它不是,所以你需要一个更复杂的方法。
  • 在蓝色之上,红色圆锥仍然被触发,直到我们看到紫色,但是我们不会在更高的频率上再次达到红色,所以你不能超过大约300°。
  • 300°和360°之间的色调范围在可见光谱中没有相同的效果,它只能通过将高频光(蓝色或紫色)与红光混合来模拟,这会在紫色上产生品红色和红色之间的某种 - 线。

答案 3 :(得分:0)

没有转换,因为它们不重叠。

色相可在RGB颜色空间中移动,通常sRGB几乎是所有消费类数字设备使用的颜色空间。这是我们的视觉系统在正常条件下(由CIE 1931定义)识别的颜色的子集,并且根本不与在单色波长的光下感知到的鲜艳的颜色线重叠。

尽管色相介于0-120(红橙色至黄绿色)和接近240(靛蓝)之间,但如果您不关心所有被冲洗掉的绿色和蓝色,则sRGB相当有用。分别通过使它们的色调分别变深,使它们的紫色和红色端变暗,分别为270或330,并且您唯一无法真正估计的位置是180左右,计算机青色根本不接近单色鲜艳的蓝绿色。

答案 4 :(得分:0)

可以找到颜色/色相的主波长。但是,正如所说的那样,大多数颜色不是单色的,并且可以用不同的波长“混合”构造相同的颜色。即同色异谱。 同样,对于额外的品红色和紫色光谱,只能指定一个互补波长。即与白色相加的色相/主波长。此外,还必须指定白色,因为由于自适应,绝对不是绝对白色。 同样从心理上讲,我们对色相的感知并不遵循主要的色相线。 Se Munsell和NCS系统。

您可以在此处根据RGB值或不同的CIE系统计算主波长:http://www.brucelindbloom.com/index.html?Calc.html 我没有公式。

然后可以将RGB转换为HSL和类似的格式。往返于Munsell或NCS感知色调(NCS值是专有的,因此您必须付费并使用它们的软件)。

答案 5 :(得分:0)

我发现这个网站可以将给定的波长转换为色调。通过一些工作,您实际上可以逆转该过程。这并不理想,但在解决这个问题时,我比我更相信应用数学顾问。就是这样。

https://www.johndcook.com/wavelength_to_RGB.html

function convert(input) {
    var w = parseFloat(input);

    if (w >= 380 && w < 440) {
        r = -(w - 440) / (440 - 380);
        g = 0.0;
        b = 1.0;
    } else if (w >= 440 && w < 490) {
        r = 0.0;
        g = (w - 440) / (490 - 440);
        b = 1.0;
    } else if (w >= 490 && w < 510) {
        r = 0.0;
        g = 1.0;
        b = -(w - 510) / (510 - 490);
    } else if (w >= 510 && w < 580) {
        r = (w - 510) / (580 - 510);
        g = 1.0;
        b = 0.0;
    } else if (w >= 580 && w < 645) {
        r = 1.0;
        g = -(w - 645) / (645 - 580);
        b = 0.0;
    } else if (w >= 645 && w < 781) {
        r = 1.0;
        g = 0.0;
        b = 0.0;
    } else {
        r = 0.0;
        g = 0.0;
        b = 0.0;
    }


    // Let the intensity fall off near the vision limits
    if (w >= 380 && w < 420)
        factor = 0.3 + 0.7 * (w - 380) / (420 - 380);
    else if (w >= 420 && w < 701)
        factor = 1.0;
    else if (w >= 701 && w < 781)
        factor = 0.3 + 0.7 * (780 - w) / (780 - 700);
    else
        factor = 0.0;

    var gamma = 0.80;
    var R = (r > 0 ? 255 * Math.pow(r * factor, gamma) : 0);
    var G = (g > 0 ? 255 * Math.pow(g * factor, gamma) : 0);
    var B = (b > 0 ? 255 * Math.pow(b * factor, gamma) : 0);

    return [R, G, B]
}