
如果您不知道什么是色温,请
从此处开始 。
在使用
PhotoDemon的“色温”工具时,我花了一整个晚上试图确定一种简单明了的算法来在温度值(以Kelvin为单位)和RGB之间进行转换。 我认为这样的算法很容易找到,因为许多照片编辑器都有校正色温的工具,并且在包括智能手机在内的每台现代相机中,都会根据照明条件进行白平衡调整。
具有白平衡设置的相机屏幕示例。 来源事实证明,找到可靠的公式将温度转换为RGB几乎是不可能的。 当然,有一些算法,但是大多数算法都是通过将温度转换为XYZ颜色空间来工作的,然后可以向其中添加RGB变换。 这样的算法似乎基于Robertson方法,一种实现在
这里 ,另一种实现
在 这里 。
不幸的是,这种方法没有提供纯粹的数学公式-它只是根据转换表进行插值。 在某些情况下,这可能是合理的,但是如果考虑到XYZ→RGB的附加转换,结果实在太慢,无法实时简单地调整色温。
所以我写了自己的算法,效果很好。 这就是我的方法。
有关此算法的警告
警告1 :我的算法提供了高质量的近似值,但对于足够的科学用途而言,其准确性不够。 它主要用于处理照片-因此请勿尝试将其用于天文学或医学中。
警告2 :由于其相对简单性,该算法足够快,可以在尺寸合理的图像上实时运行(我在12兆像素的图像上对其进行了测试),但是为了获得最佳结果,请使用针对您的编程语言的数学优化。 我展示了没有数学优化的算法,以免使其复杂化。
警告3 :该算法仅在1000 K至40,000 K的范围内使用,这是摄影的好范围。 (实际上,它比大多数情况下所需的要大得多)。 尽管它适用于此范围之外的温度,但质量会下降。
特别感谢Mitchell Charity
首先,我必须承担很多债务,并感谢Mitchell Charity提供了我用来创建这些算法的初始数据:
未处理的黑体文件 。 Charity提供了两组数据,我的算法使用了
CIE 1964 10度颜色匹配功能 。 关于2度CIE 1931函数以及Judd Wos与10度集的校正的讨论超出了本文的讨论范围,但是如果您有兴趣,可以从此
页面开始进行全面的分析。
算法:示例输出
这是算法的输出,范围从1000 K到40,000 K:
我的算法的输出范围是1000 K至40,000K。白点是6500–6600 K,非常适合在现代LCD监视器上处理照片这是该算法的更详细的快照,范围从1500 K到15000 K,可用于摄影:
相同的算法,但是从1500 K到15000 K如您所见,带区是最小的,这比上面的匹配表有很大的改进。 该算法还可以很好地保持白点附近的淡黄色调,这对于在后期处理照片中模拟日光非常重要。
我是怎么想到这个算法的
得出可靠公式的第一步是
从Charity绘制
黑体的
原始值 。 您可以
使用LibreOffice / OpenOffice .ods格式(430 KB)下载
整个电子表格 。
这是绘制后的数据:
RGB(sRGB)中的原始温度数据(K),LibreOffice Calc图形。 同样,该转换基于CIE 1964的10度CMF函数,根据需要,白点介于6500 K和6600 K之间(图表的左侧)。 来源容易注意到,有几个部分简化了我们的算法。 特别是:
- 低于6600 K的红色值始终为255
- 低于2000 K的蓝色值始终为0
- 高于6500 K的蓝色值始终为255
同样重要的是要注意,为了使曲线适合数据,最好将绿色视为两条单独的曲线-一条用于温度低于6600 K的曲线,另一条用于温度高于此点的曲线。
从这一刻起,我将数据(没有“ always 0”和“ always 255”段)划分为单独的颜色分量。 在理想的世界中,可以将曲线调整为每个点集,但是不幸的是,实际上并不是那么简单。 由于图形上X和Y的值之间存在很大的不匹配-所有x值都大于1000并以100个点段显示,而y值在255和0之间-我必须转置x数据以获得最佳拟合。 出于优化目的,我首先将每种颜色的x(温度)值除以100,然后减去需要多少以适应图形。 以下是每条曲线的结果图,以及最合适的曲线和确定系数的相应值(R平方):




我对字体的可怕字距和图表提示深表歉意。 LibreOffice具有许多优点,但是无法平滑图形上的字体是完全可耻的。 我也不喜欢从屏幕截图中提取图表,因为它们没有导出选项,但最好将其留待以后使用。
如您所见,所有曲线的对齐方式都很好,确定系数的值大于0.987。 我可以花更多时间调整曲线,但这足以处理照片。 没有一个居民会说曲线并不完全对应于黑体的初始理想观察结果,对吗?
演算法
这是算法的全部荣耀。
一,伪代码:
- 1000 40000. ( , 40000 K). , . Set Temperature = Temperature \ 100 : 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 : 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 : 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()表示自然对数 。 另请注意,如果温度始终在建议范围内,则可以省略颜色是否小于0的检查。 (但是,您仍然需要选中“如果颜色大于255”)。
关于实际代码,这是我在
PhotoDemon中使用的确切的Visual Basic函数。 尚未进行优化(例如,对应表的对数会更快),但至少代码简洁易读:
在本文开头,该函数用于生成示例输出,因此我可以保证它可以正常工作。
样本图片
这是色温调节功能的一个很好的例子。 下图是HBO的《真爱如血》的广告海报,壮观地展示了调节色温的潜力。 左边是原始框架。 在右侧-使用上面的代码调整色温。 只需单击一下,即可将夜景重现为白天。
进行色温调整我的PhotoDemon程序中的真实色温工具如下:
PhotoDemon色温工具下载程序并观看实际操作。
2014年10月更新
雷诺·贝达(Renault Bedar)对该算法进行了出色的
在线演示 。 谢谢雷诺!
2015年4月更新
感谢所有提出对原始算法进行改进的人。 我知道这篇文章有很多评论,但是如果您打算实现自己的版本,则值得阅读。
我想强调两个具体的改进。 首先,尼尔B为原始曲线拟合函数提供了最佳版本,该函数会稍微改变温度系数。 这些变化在
他的出色文章中有详细描述。
然后,弗朗西斯·洛奇(Francis Loch)添加了一些注释和图像示例,如果要将这些转换应用于照片,这些注释和示例非常有用。
如示例所示,对它的修改会产生更加详细的图像。