题目:从RGB色彩表示转换到HSV色彩表示。
采用国际标准测试图像Lena。
H(Hue)色度:就是平常所说的颜色名称,如红色、蓝色、绿色。色相与数值按下表对应:
红 | 黄 | 绿 | 青 | 蓝 | 品红 | 红 |
---|---|---|---|---|---|---|
0 ° 0\degree 0° | 60 ° 60\degree 60° | 120 ° 120\degree 120° | 180 ° 180\degree 180° | 240 ° 240\degree 240° | 300 ° 300\degree 300° | 360 ° 360\degree 360° |
S(Saturation)饱和度:是指色彩的纯度,饱和度越低则颜色越黯淡, 0 ≤ S ≤ 1 0\le S\le1 0≤S≤1。
V(Value)明度:表示了颜色的亮暗程度,在坐标原点值为0,在锥体最上方的顶点上的值为1.
在RGB中颜色由三个值共同决定,比如黄色为(255,255,0);在HSV中,黄色只由一个值决定,Hue=60即可。
HSV表色系可以与RGB色系相互转换,转换公式如下:
RGB色彩空间的三个颜色的不同组合可以形成几乎所有的其他颜色。利用三个颜色分量的线性组合来表示颜色,任何颜色都与这三个分量有关,而且这三个分量是高度相关的,所以连续变换颜色时并不直观,想对图像的颜色进行调整需要更改这三个分量才行。
但是人眼对这三种颜色分量的敏感程度是不一样的。在单色中,人眼对红色最不敏感,蓝色最敏感。所以RGB颜色空间是一种均匀性较差的颜色空间。对于某一种颜色,我们很难推测出较为精确的三个分量数值来表示。所以,RGB颜色空间适合于显示系统,却并不适合于图像处理。
C++代码如下:
cv::Mat RGB2HSV(cv::Mat img)
{
cv::Mat hsv(img.size(), CV_32FC3);
float r=0.0, g=0.0, b = 0.0;
float _max = 0.0, _min = 0.0;
float h = 0.0, s = 0.0, v = 0.0;
for (int row = 0; row < img.rows; row++)
{
cv::Vec3b *currentData = img.ptr<cv::Vec3b>(row);
for (int col = 0; col < img.cols; col++)
{
r = (*(currentData + col))[2] / 255;
g = (*(currentData + col))[1] / 255;
b = (*(currentData + col))[0] / 255;
_max = max(r, max(g, b));
_min = min(r, min(g, b));
v = _max;
if (v == 0)
{
s = 0;
}
else
{
s = (v - _min) / v;
}
if (v == r)
{
h = 60 * (g - b) / (s*v);
}
else if (v == g)
{
h = 60 * (2 + (b - r) / (s*v));
}
else if (v == b)
{
h = 60 * (4 + (r - g) / (s*v));
}
else if (v == 0)
{
h = 0;
}
else
{
h = h + 360;
}
hsv.at<cv::Vec3f>(row, col)[0] = h;
hsv.at<cv::Vec3f>(row, col)[1] = s;
hsv.at<cv::Vec3f>(row, col)[2] = v;
}
}
return hsv;
}
参考博客:https://blog.csdn.net/jinking01/article/details/120224251
https://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4