题目:从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色系到HSV色系
RGB转HSV色系之前,需要对R、G、B三个通道归一化到0-1。
V = m a x ( R , G , B ) V=max(R,G,B) V=max(R,G,B)
S = { [ V − m i n ( R , G , B ) ] / V V > 0 0 V = 0 S = \begin{cases} \lbrack V-min(R,G,B)\rbrack/V & V>0 \\ 0 &V=0 \end{cases} S={ [V−min(R,G,B)]/V0V>0V=0
H = { 60 ( G − B ) / S V V = R 60 [ 2 + ( B − R ) / S V ] V = G 60 [ 4 + ( R − G ) / S V ] V = B 0 V = 0 H + 360 H < 0 H = \begin{cases} 60(G-B)/SV & V=R \\ 60\lbrack 2+(B-R)/SV\rbrack & V=G\\ 60\lbrack 4+(R-G)/SV\rbrack & V=B\\ 0 & V=0 \\ H+360 &H<0 \end{cases} H=⎩ ⎨ ⎧60(G−B)/SV60[2+(B−R)/SV]60[4+(R−G)/SV]0H+360V=RV=GV=BV=0H<0 - HSV色系转换到RGB色系的计算公式为:
0 < H ≤ 60 { R = V B = R − S ⋅ V G = S ⋅ V ⋅ H / 60 + B 0<H\le60 \begin{cases} R=V & \\ B=R-S\cdot V \\ G=S\cdot V \cdot H/60+B \end{cases} 0<H≤60⎩ ⎨ ⎧R=VB=R−S⋅VG=S⋅V⋅H/60+B
300 < H ≤ 360 { R = V B = R − S ⋅ V G = G − S ⋅ V ⋅ ( H − 360 ) / 60 300<H\le360 \begin{cases} R=V & \\ B=R-S\cdot V \\ G=G-S \cdot V\cdot(H-360)/60 \end{cases} 300<H≤360⎩ ⎨ ⎧R=VB=R−S⋅VG=G−S⋅V⋅(H−360)/60
60 < H ≤ 120 { G = V B = G − S ⋅ V R = B − S ⋅ V ⋅ ( H − 120 ) / 60 60<H\le120 \begin{cases} G=V & \\ B=G-S\cdot V \\ R=B-S \cdot V\cdot(H-120)/60 \end{cases} 60<H≤120⎩ ⎨ ⎧G=VB=G−S⋅VR=B−S⋅V⋅(H−120)/60
120 < H ≤ 180 { G = V R = G − S ⋅ V B = R + S ⋅ V ⋅ ( H − 120 ) / 60 120<H\le180 \begin{cases} G=V & \\ R=G-S\cdot V \\ B=R+S \cdot V\cdot(H-120)/60 \end{cases} 120<H≤180⎩ ⎨ ⎧G=VR=G−S⋅VB=R+S⋅V⋅(H−120)/60
180 < H ≤ 240 { B = V R = B − S ⋅ V G = R − S ⋅ V ⋅ ( H − 240 ) / 60 180<H\le240 \begin{cases} B=V & \\ R=B-S\cdot V \\ G=R-S \cdot V\cdot(H-240)/60 \end{cases} 180<H≤240⎩ ⎨ ⎧B=VR=B−S⋅VG=R−S⋅V⋅(H−240)/60
240 < H ≤ 360 { B = V G = B − S ⋅ V R = G + S ⋅ V ⋅ ( H − 240 ) / 60 240<H\le360 \begin{cases} B=V & \\ G=B-S\cdot V \\ R=G+S \cdot V\cdot(H-240)/60 \end{cases} 240<H≤360⎩ ⎨ ⎧B=VG=B−S⋅VR=G+S⋅V⋅(H−240)/60
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