色温是什么?用度娘的话来说就是色温是表示光线中包含颜色成分的一个计量单位。从理论上讲,色温是指绝对黑体从绝对零度(-273℃)开始加温后所呈现的颜色。黑体在受热后.逐渐由黑变红,转黄,发白,最后发出蓝色光。
如果某一光源发出的光,与某一温度下黑体发出的光所含的光谱成分相同.即称为某K色温。如100 W灯泡发出光的颜色,与绝对黑体在2527K时的颜色相同,那么这只灯泡发出的光的色温就是:2527K+ 273K=2800K。
如果偏要纠结什么是黑体,那我建议再去修天文学。但咱学的是工科,只需要一个结论:色温越低,颜色偏红,画面显得越暖。色温越高,颜色偏蓝,画面显得越冷。
来看一个手机类PS软件的例子:
从左到右分别为色温低,不调整,色温高的情况。可以看到色温越高,画面的的颜色越偏向蓝色。这个APP为了迎合视觉上的蓝色偏冷,红黄偏暖,将色温调节参数设置为越高,颜色越黄,越低则颜色越蓝。
我们用相机拍同一个人,在不同的天气下,脸部会有不同的变化。很明显,相机的色温没有随环境变化而变化。那怎么来让相机智能一点呢?
白平衡这个东东开始发挥它的作用。
白平衡(White balance),字面意思就是把不同天气或者环境下的白色物体,通过色彩平衡,把它纠正为白色。
仔细翻看一下相机,发现会有以下的设置:
当前的模式为阴天模式(Cloudy),色温接近6000K(Approx.6000K)。
为什么有这些选项?这些选项怎么用?
比如现在日出,天空比较红,色温低,我们将这些选项调整到一个色温低的模式(不同品牌的相机会略有不同,主要看上图的6000K这个数值,数值越小,色温越低),相机就知道环境色温比较低,需要在成像处理是加点蓝色。
那反过来,如果觉得天空不够红怎么办?这时候就需要给相机一个善意的谎言,选择一个高色温模式。于是相机被我们提醒环境色温高,会在成像处理时加点红色。
新问题又来了:每换一个环境自己就要重新设置一次白平衡吗?
不一定。相机厂商告诉我们还有一个功能:自动白平衡(AWB),相机自己会根据环境调整白平衡。
有了自动白平衡,还要其它的选项设置干嘛?
现实告诉我们,免费的不是最好的。自动的也是这样。冷冰冰的机器有的只是固定思维,所以机器选的模式不一定是我们当前最想要的模式。
万一需要的色温,这几种模式没有提供呢?
参考图标是一个黑色方块和两个三角形的模式。这种模式叫自定义白平衡。顾名思义,就是你自己定义一个白平衡。在任何一个环境下,拿一个白色的东东给相机,告诉相机,这是白色。相机就会参考这时候的白色,去还原别的颜色。所以专业的摄影师都会随身携带一张白卡。
Here we realize video temperature and tint using VisualStudio 2013 + opencv3.0.
For any algorithm we used, please refer to http://www.tannerhelland.com/5675/simple-algorithms-adjusting-image-temperature-tint/.
Given atemperature adjustment on the range -100 to 100, apply the following adjustmentto each pixel in the image:
r = r +adjustmentValue
g = g
b = b –adjustmentValue
Given a tintadjustment on the range -100 to 100, apply the following adjustment to eachpixel in the image:
r = r
g = g +adjustmentValue
b = b
As with any additive RGB adjustment, you’ll need to manually clip the output values to the [0, 255] range.
#include "stdafx.h"
#include
#include
#include
using namespace cv;
using namespace std;
Mat srcImg;
Mat dstImg;
int init_temp_pos = 128;
int init_tint_pos = 128;
int nrow;
int ncol;
void onColorTempChange(int t,void*);
void onColorTintChange(int t, void*);
void pixCal(int tempAdj, int tintAdj);
int _tmain(int argc, _TCHAR* argv[]){
srcImg = imread("F:/opencv/1.jpg");
nrow = srcImg.rows;
ncol = srcImg.cols;
if (srcImg.empty()){
cout << "error";
return -1;
}
namedWindow("image", WINDOW_NORMAL);
namedWindow("control", WINDOW_NORMAL);
createTrackbar("temp", "control", &init_temp_pos, 256, onColorTempChange);
createTrackbar("tint", "control", &init_tint_pos, 256, onColorTintChange);
onColorTempChange(init_temp_pos,0);
onColorTintChange(init_tint_pos,0);
waitKey();
return 0;
}
void onColorTempChange(int t, void*){
int tempAdjValue = (t - 128)/10;
int tintAdjValue = (getTrackbarPos("temp", "control") - 128)/10;
pixCal(tempAdjValue,tintAdjValue);
imshow("image", dstImg);
}
void onColorTintChange(int t, void*){
int tempAdjValue = (getTrackbarPos("tint", "control") - 128)/10;
int tintAdjValue = (t - 128) / 10;
pixCal(tempAdjValue, tintAdjValue);
imshow("image", dstImg);
}
void pixCal(int tempAdj, int tintAdj){
srcImg.copyTo(dstImg);
int temp;
for (int i = 0; i(i);
for (int j = 0; j 255){
data[j * 3] = 255;
}else if (temp < 0){
data[j * 3] = 0;
}else{
data[j * 3] = temp;
}
//G
temp = data[j * 3 + 1];
temp = temp + tintAdj;
if (temp > 255){
data[j * 3 + 1] = 255;
}
else if (temp < 0){
data[j * 3 + 1] = 0;
}else{
data[j * 3 + 1] = temp;
}
//R
temp = data[j * 3 + 2];
temp = temp + tempAdj;
if (temp > 255){
data[j * 3 + 2] = 255;
}else if (temp < 0){
data[j * 3 + 2] = 0;
}
else{
data[j * 3 + 2] = temp;
}
}
}
}