之前操作图像数据通常使用的是RGB颜色模型。RGB是通过三个颜色通道(R、G、B)的叠加得到不同的颜色的。今天学习了一个新的颜色模型:HSV。
作为对比,先看熟悉的RGB。RGB中有三个参数,分别代表红绿蓝三基色的亮度,范围是0~255。这里的三基色是指光的三基色,三基色组合可以得到大部分颜色。
HSV中也有三个参数,H、S、V,分别代表色调(Hue),饱和度(Saturation),明度(Value)。其中色调的范围是0~360°,以角度形式给出颜色光谱构成的度量。饱和度是0~100°,给出主波长中纯光的比例,表示一种颜色距离相同亮度相同时,灰度的程度。明度、又叫纯度,给出相对于白色光照强度的亮度,范围在0~100°.
在OpenCV中,色彩参数范围由于表达方式的限制有所调整:H范围0~180,S范围0~255,V范围0~255。
要在HSV色彩空间下处理图像,首先要转换色彩模型:
Mat img = imread(fname);
imshow("src", img);
vector<Mat> channels;
cvtColor(img, img, COLOR_BGR2HSV);
split(img, channels);
注意,在Opencv中,imshow函数显示的图像是默认RGB色彩模型的,如果转换色彩模型后再用imshow会导致图像显示发生偏差。
在分离出HSV通道后,就可以对各个通道操作达到想要的效果。
一个例子:
查表得知红色的h值范围在156~180(通常对于想要的色彩范围可以提前采集得知),对一张图将其中的红色全部换成绿色(即将其角度增加60)。代码如下:
void hsv_test(string fname){
Mat img = imread(fname);
resize(img, img, Size(), 0.2, 0.2);
imshow("src", img);
vector<Mat> channels;
for (int i = 0; i < img.rows; i++){//每一行
unsigned char* data = channels[0].ptr<unsigned char>(i);
for (int j = 0; j < img.cols; j++){//每一个
int temp = data[j];
//temp *= 2*exp(1-temp) + 1;
if(temp<180 && temp>156)temp = (temp + 60) % 180;
//if (temp >= 255)temp = 255;
data[j] = temp;
}
}
Mat result;
merge(channels, result);
cvtColor(result, result, COLOR_HSV2BGR);
imshow("result", result);
waitKey();
system("pause");
}
运行结果:
参考资料:
HSV分量范围:http://blog.csdn.net/taily_duan/article/details/51506776
http://www.cnblogs.com/wangyblzu/p/5710715.html
通道分离与合并:
http://blog.csdn.net/u014077175/article/details/41177565