色温(Kelvin)到RGB的转换:算法和样例
色温(Kelvin)到RGB的转换:算法和样例据我所知,还不太可能找到从色温到RGB转换的一个可靠的公式。虽然,有很多算法实现了类似的功能,但是,大多是都是从色温转换到XYZ颜色空间。这之后你再可以根据需要从XYZ空间在转换到RGB颜色空间。这种算法的一种实现方式你可以在这找到。很不幸的是,这种方式并不是真正意义上的数学公式,只是一种美化的...
色温(Kelvin)到RGB的转换:算法和样例
据我所知,还不太可能找到从色温到RGB转换的一个可靠的公式。虽然,有很多算法实现了类似的功能,但是,大多是都是从色温转换到XYZ颜色空间。这之后你再可以根据需要从XYZ空间在转换到RGB颜色空间。这种算法的一种实现方式你可以在这找到。
很不幸的是,这种方式并不是真正意义上的数学公式,只是一种美化的查找表实现方式。在某些情况下,这是一种可靠地实现方式。但是,当涉及到XYZ->RGB转换的时候,对简单的实时色温调整而言,这种方式太慢了。
因此,我实现了一套色温到RGB转换的算法。这个算法转换相当不错。以下是我的一些思路。
使用这种算法的一些限制:
- 我的算法是一种高精度的估算。但是,对科学研究而言精度还是不够。这种算法主要是用在照片的一些处理,所以,不要尝试在天文学和医学图像处理领域使用这种算法。
- 由于算法相对简单,这种算法在处理合适大小的图像时,实时性已经足够快速。但是,为了获取更好的实时性能,你必须对你所使用的编程语言实现这种算法再做些优化。
- 这个算法只适用于1000K到40000K的色温转换。对摄影学来说,这么大的光谱范围已经足够了。当色温超过这个范围使用时,精度将会降低。
算法实现:样例输出
下图是算法输出1000K到40000K的图像。
下图是摄影学感兴趣的色温范围:从1500K到15000K
算法实现思路
我的第一步工作是从Charity’s original blackbody values 逆向工程方式实现一个可靠的公式。
Charity’s original blackbody values 的数据用图表的形式表示为:
从图表可以看出,有一些上限值和下限值,使得我们的算法很容易实现。特别的:
- 红色分量在6600K以下的时候总保持255
- 蓝色分量在2000K的时候总保持0
- 蓝色问了在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/
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)