jvruo

【蒟蒻科技】实现光的波长和RGB值的转换
我们都知道,一种波长的可见光会对应一种固定的颜色。你是否会好奇,波长为X的可见光所对应的颜色的RGB值为多少呢?...
扫描右侧二维码阅读全文
23
2018/02

【蒟蒻科技】实现光的波长和RGB值的转换

我们都知道,一种波长的可见光会对应一种固定的颜色。你是否会好奇,波长为X的可见光所对应的颜色的RGB值为多少呢?这篇博客就是要告诉你如何实现光的波长和RGB值的转换。

原理部分

说到波长与颜色的转换,第一反应便是色度图,而我采用的就是1931CIE-XYZ标准色度系统

所谓1931CIE-XYZ系统,就是在RGB系统的基础上,用数学方法,选用三个理想的原色来代替实际的三原色,从而将CIE-RGB系统中的光谱三刺激值 和色度坐标r、g、b均变为正值。

下面我们来介绍一下CIE-RGB系统CIE-XYZ系统的转换关系。选择三个理想的原色(三刺激值)X、Y、Z,X代表红原色,Y代表绿原色,Z代表蓝原色,这三个原色不是物理上的真实色,而是虚构的假想色。它们在色度图中的色度坐标分别为:
sf0.png

从下图中可以看到虚线三角形将整个光谱轨迹包含在内。因此整个光谱色变成了以XYZ三角形作为色域的域内色。在XYZ系统中所得到的光谱三刺激值x(γ)、y(γ) 、z(γ)、和色度坐标x、y、z将完全变成正值。经数学变换,两组颜色空间的三刺激值有以下关系:

X=0.490R+0.310G+0.200B

Y=0.177R+0.812G+0.011B         

Z= 0.010G+0.990B

timg.jpg

经过数学公式的推演和反推,我们得到两组颜色空间色度坐标的相互转换关系为:

x=(0.490r+0.310g+0.200b)/(0.667r+1.132g+1.200b)

y=(0.117r+0.812g+0.010b)/(0.667r+1.132g+1.200b)

z=(0.000r+0.010g+0.990b)/(0.667r+1.132g+1.200b)

这就是我们通常用来进行变换的关系式,所以,只要知道某一颜色的色度坐标r、g、b,即可以求出它们在新设想的三原色XYZ颜色空间的的色度坐标x、y、z。通过式的变换,对光谱色或一切自然界的色彩而言,变换后的色度坐标均为正值,而且等能白光的色度坐标仍然是(0.33,0.33),没有改变。

同理,经过数学的计算,也能得出光的波长与三原色XYZ颜色空间的的色度坐标x、y、z的相互转换,其大致表格如下:
sf233.JPG

也就是说我们要做的是通过算法把光的波长转换为色度坐标x、y、z,再把色度坐标转化为该波长所对应的可见光的R,G,B值。

至此,我们就已经完成了光的波长到R,G,B值的理论转化,接下来我就介绍一下我的程序算法。

程序部分

首先,我们要做的是把波长转化为所对应的X,Y,Z值,在这里为了尽可能快速的计算完成,我们采用了打表的以空间换取时间的高效算法,在这种算法的条件下,我们可以轻松的做到在O(1)的时间复杂度下计算长转化为所对应的X,Y,Z值。

其次,我们需要对X,Y,Z值进行数学操作,使其转化为对应的RGB值。在这里我们只需要将X,Y,Z值代入两组颜色空间色度坐标的相互转换关系,运用高斯消元的方法解出方程组的解即可。

但是我们发现,这只是关于R,G,B三个值的方程,使用高斯消元固然可以,但有些大材小用,所以在这里,我们也可运用暴力枚举R,G,B值的方式找到方程的解,具体代码如下:

xx=x[b];yy=y[b];zz=z[b];mi=32768;
    for(int i=0;i<=255;i++)
    for(int j=0;j<=255;j++)
    for(int k=0;k<=255;k++)
    {
        if(i+k+j>0)
        {
            rr=0.490*i+0.310*j+0.200*k;
            rr=rr/(0.667*i+1.132*j+1.200*k);

            gg=0.117*i+0.812*j+0.010*k;
            gg=gg/(0.667*i+1.132*j+1.200*k);

            bb=0.000*i+0.010*j+0.990*k;
            bb=bb/(0.667*i+1.132*j+1.200*k);

            m=(rr-xx)*(rr-xx)+(gg-yy)*(gg-yy)+(bb-zz)*(bb-zz);
            if(m<mi)
            {
                mi=m;
                rrr=i;
                ggg=j;
                bbb=k;
            }
        }
    }

其中的rrr,ggg,bbb就是我们要求解的R,G,B值。

接着我们的问题就是如何用c++输出一组R,G,B对应的颜色的图像?这里我们给出模板,其中a[i][j][0] a[i][j][1] a[i][j][2] 分别代表第i行第j列的像素点所对应的R,G,B值,所以总的模板如下:
sf44.png

总的程序如下:
sf5.pngsf6.pngsf7.pngsf8.pngsf9.pngsf10.png

PS不知道为什么代码上传不了(服务器认为对它有威胁拦截了),只好附上图片,程序在下面的链接也会附加给大家下载学习。picture_make.cpp

程序运用与检验

由于在这之前没有人做过波长与颜色转化的相关尝试,所以我们也算是这种算法的创始人了(自吹自擂)。令人振奋的是该程序在多次检验调试后终于到达了最优状态,下面我就展示该程序的效果。

经过双缝干涉测量,红光的波长为620nm左右,将其放入程序检验。
sf11.png
并打开对应的输出文件。
sf12.png
输出颜色为红色,颜色及RGB值符合观察所测值。

同理对绿光波长进行测试(观测得绿光波长约为510nm)
sf13.png
并打开对应的输出文件。
sf14.png
输出颜色为绿色,颜色及RGB值符合观察所测值。至此,程序的效果及正确性展示完成。

结语及展望

由上面的测试我们可以发现。该程序能快速有效的计算出波长与RGB颜色的对应关系,这将极大的便利艺术工作者及人类日后的生活,对艺术乃至人类视觉进步的发展有着极其深远的影响!
kkk.gif

Last modification:July 12th, 2018 at 05:31 pm
If you think my article is useful to you, please feel free to appreciate

13 comments

  1. 时已惘然

    你好,你这个由波长转换成x,y,z是如何做到的呢

  2. 贺裕鹏

    博主:您好!我能向您请教细节的问题吗?我现在要做的就是反向的过程,即从RGB到波长的转换!

  3. 贺裕鹏

    博主,您好!可以向您请教细节的问题吗?我现在面临的问题和您的这个是颠倒过来的,我需要从RGB转换成波长!

    1. jvruo
      @贺裕鹏

      诶……没有研究过比较简便的方法,这里提供两种解决方案吧,首先RGB值最多才256*246*256才不足两千万个……实在不行用我的算法打个表就出来了(可能有点大);当然,你已经知道了RGB值,就可以直接计算出色度坐标,接着只要O(n)扫描一遍,寻找差值最小的波长就是要求解的啦!

      1. 贺裕鹏
        @jvruo

        您的色度坐标和波长之间有公式计算吗?

        1. jvruo
          @贺裕鹏

          然后x,y,z值计算得出后参照我给出的那个表寻找对应的波长就行了!

        2. jvruo
          @贺裕鹏

          x=(0.490r+0.310g+0.200b)/(0.667r+1.132g+1.200b)
          y=(0.117r+0.812g+0.010b)/(0.667r+1.132g+1.200b)
          z=(0.000r+0.010g+0.990b)/(0.667r+1.132g+1.200b)
          这个就是呢,我就是根据这个枚举出RGB值的。

          1. 贺裕鹏
            @jvruo

            嗯,这个是x,y,z与R,G,B之间的转化,有没有波长bz和x,y,z之间的转换公式,您的博文上写的是经过数学计算的出来的表格!

            1. jvruo
              @贺裕鹏

              没有直接推到过x,y,z到波长耶……只有波长到x,y,z,不过可以给出一种解决方案,就是在计算得出x,y,z值后,用程序直接判断与波长为多少的光的x,y,z值最接近直接来得出一个近似的答案……现在博主高三了可能没那么多时间继续推了,望谅解QwQ

              1. 贺裕鹏
                @jvruo

                好的,多谢博主,棒棒哒!祝高考顺利!

                1. jvruo
                  @贺裕鹏

                  谢谢谢谢!最后感谢您喜欢这篇BLOG,祝您生活愉快!OωO

  4. YYF

    你怎么这么优秀

    1. jvruo
      @YYF

      您比较优秀ORZ

Leave a Comment