色温(Kelvin)RGB的转换:算法和样例

据我所知,还不太可能找到从色温到RGB转换的一个可靠的公式。虽然,有很多算法实现了类似的功能,但是,大多是都是从色温转换到XYZ颜色空间。这之后你再可以根据需要从XYZ空间在转换到RGB颜色空间。这种算法的一种实现方式你可以在这找到。

很不幸的是,这种方式并不是真正意义上的数学公式,只是一种美化的查找表实现方式。在某些情况下,这是一种可靠地实现方式。但是,当涉及到XYZ->RGB转换的时候,对简单的实时色温调整而言,这种方式太慢了。

因此,我实现了一套色温到RGB转换的算法。这个算法转换相当不错。以下是我的一些思路。

使用这种算法的一些限制:

  1. 我的算法是一种高精度的估算。但是,对科学研究而言精度还是不够。这种算法主要是用在照片的一些处理,所以,不要尝试在天文学和医学图像处理领域使用这种算法。
  2. 由于算法相对简单,这种算法在处理合适大小的图像时,实时性已经足够快速。但是,为了获取更好的实时性能,你必须对你所使用的编程语言实现这种算法再做些优化。
  3. 这个算法只适用于1000K到40000K的色温转换。对摄影学来说,这么大的光谱范围已经足够了。当色温超过这个范围使用时,精度将会降低。

算法实现:样例输出

下图是算法输出1000K到40000K的图像。

下图是摄影学感兴趣的色温范围:从1500K到15000K

算法实现思路

我的第一步工作是从Charity’s original blackbody values 逆向工程方式实现一个可靠的公式。

Charity’s original blackbody values 的数据用图表的形式表示为:

 

从图表可以看出,有一些上限值和下限值,使得我们的算法很容易实现。特别的:

  1. 红色分量在6600K以下的时候总保持255
  2. 蓝色分量在2000K的时候总保持0
  3. 蓝色问了在6500K以上总保持255

为了更好地拟合这些数据,绿色分量被划分为两部分进行拟合。一部分是低于6600K;另一部分是高于6600K。

之后,我把数据分成独立的颜色分量进行拟合。(不包括那些总是为0和255的数据)。理想状态下,有一条曲线将经过每一个数据点。但现实情况,往往没这么理想。因为对于上图中X轴和Y轴的数据而言,它们的数值相差太大。X轴的数值都大于1000,对于Y轴而言,其数值范围在0到255之间。我们必须对X轴的数据做相应的转换才能更好的进行曲线拟合。为了达到最优拟合的目的,我对X轴的数据做了除100处理,并进行了相应的偏移。以下是每个分量的数据分布和最优的拟合曲线:

 

 

 

 

如上图所述,其曲线拟合的很好。

算法实现

以下是算法实现的伪代码:

输入:1000K到40000K的色温;色温和颜色分量的变量必须是双精度

Set Temperature = Temperature \ 100


    Calculate Red:

    If Temperature <= 66 Then

        Red = 255

    Else

        Red = Temperature - 60

        Red = 329.698727446 * (Red ^ -0.1332047592)

        If Red < 0 Then Red = 0

        If Red > 255 Then Red = 255

    End If

   
    Calculate Green:

    If Temperature <= 66 Then

        Green = Temperature

        Green = 99.4708025861 * Ln(Green) - 161.1195681661

        If Green < 0 Then Green = 0

        If Green > 255 Then Green = 255

    Else

        Green = Temperature - 60

        Green = 288.1221695283 * (Green ^ -0.0755148492)

        If Green < 0 Then Green = 0

        If Green > 255 Then Green = 255

    End If

Calculate Blue:

    If Temperature >= 66 Then

        Blue = 255

    Else

        If Temperature <= 19 Then

            Blue = 0

        Else

            Blue = Temperature - 10

            Blue = 138.5177312231 * Ln(Blue) - 305.0447927307

            If Blue < 0 Then Blue = 0

            If Blue > 255 Then Blue = 255

        End If


    End If

上述伪代码中,Ln()表示的是自然对数。

以下是VB的代码实现。以下代码未做优化,但是代码简短可读性好。

Static tmpCalc As Double


    'Temperature must fall between 1000 and 40000 degrees

    If tmpKelvin < 1000 Then tmpKelvin = 1000

    If tmpKelvin > 40000 Then tmpKelvin = 40000

   

    'All calculations require tmpKelvin \ 100, so only do the conversion once

    tmpKelvin = tmpKelvin \ 100

   

    'Calculate each color in turn

   

    'First: red

    If tmpKelvin <= 66 Then

        r = 255

    Else

        'Note: the R-squared value for this approximation is .988

        tmpCalc = tmpKelvin - 60

        tmpCalc = 329.698727446 * (tmpCalc ^ -0.1332047592)

        r = tmpCalc

        If r < 0 Then r = 0

        If r > 255 Then r = 255

    End If

    'Second: green

    If tmpKelvin <= 66 Then

        'Note: the R-squared value for this approximation is .996

        tmpCalc = tmpKelvin

        tmpCalc = 99.4708025861 * Log(tmpCalc) - 161.1195681661

        g = tmpCalc

        If g < 0 Then g = 0

        If g > 255 Then g = 255

    Else

        'Note: the R-squared value for this approximation is .987

        tmpCalc = tmpKelvin - 60

        tmpCalc = 288.1221695283 * (tmpCalc ^ -0.0755148492)

        g = tmpCalc

        If g < 0 Then g = 0

        If g > 255 Then g = 255

    End If


    'Third: blue

    If tmpKelvin >= 66 Then

        b = 255

    ElseIf tmpKelvin <= 19 Then

        b = 0

    Else

        'Note: the R-squared value for this approximation is .998

        tmpCalc = tmpKelvin - 10

        tmpCalc = 138.5177312231 * Log(tmpCalc) - 305.0447927307

       

        b = tmpCalc

        If b < 0 Then b = 0

        If b > 255 Then b = 255

    End If

   

End Sub

算法效果:

下图是色温调整算法实现的效果图。左侧是原始图像,有测试经过上述色温调整算法后的图像。

实际在工具中实现的效果如下图所示:

 有选择的翻译至:http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐