颜色空间转换
不同彩色空间之间的转换。
1、CMY/CMYK颜色空间
青、品红、黄(CMY)(Cyan、Magenta、Yellow)彩色模型是彩色图象印刷行业使用的彩色空间,在彩色立方体中它们是红、绿、蓝的补色,称为减色基,而红、绿、蓝称为加色基。在CMY模型中,颜色是从白光中减去一定成分得到的。CMY坐标可以从RGB模型中得到:
C = 1 – R
M = 1 – G
Y = 1 – B
由于在印刷时CMY模型不可能产生真正的黑色,因此在印刷业中实际上使用的是CMYK彩色模型,K为第四种颜色,表示黑色(black ink):从CMY 到CMYK的转换:
K := min(C,M,Y)
C := C – K
M := M – K
Y := Y - K
- //RGB转换为CMY
- void rtRGB2CMY(RtScalar rgb, RtScalar& cmy)
- {
- cmy.val[0] = 255 - rgb.val[0];
- cmy.val[1] = 255 - rgb.val[1];
- cmy.val[2] = 255 - rgb.val[2];
- }
- //CMY转换为RGB
- void rtCMY2RGB(RtScalar cmy, RtScalar& rgb)
- {
- rgb.val[0] = 255 - cmy.val[0];
- rgb.val[1] = 255 - cmy.val[1];
- rgb.val[2] = 255 - cmy.val[2];
- }
- //CMY转换为CMYK
- void rtCMY2CMYK(RtScalar cmy, RtScalar& cmyk)
- {
- unsigned char temp = 0;
- temp = min(min(cmy.val[0], cmy.val[1]), cmy.val[2]);
- if (temp == 255 )
- {
- cmyk = rtScalar(0, 0, 0, 0);
- }
- else
- {
- cmyk.val[0] = cmy.val[0] - temp;
- cmyk.val[1] = cmy.val[1] - temp;
- cmyk.val[2] = cmy.val[2] - temp;
- }
- cmyk.val[3] = temp;
- }
- //CMYK转换为CMY
- void rtCMYK2CMY(RtScalar cmyk, RtScalar& cmy)
- {
- cmy.val[0] = cmyk.val[0] + cmyk.val[3];
- cmy.val[1] = cmyk.val[1] + cmyk.val[3];
- cmy.val[2] = cmyk.val[2] + cmyk.val[3];
- }
2、HSI颜色空间
HSI色彩空间是从人的视觉系统出发,用色调(Hue)、色饱和度(Saturation或Chroma)和亮度 (Intensity或Brightness)来描述色彩。HSI色彩空间可以用一个圆锥空间模型来描述。用这种 描述HIS色彩空间的圆锥模型相当复杂,但确能把色调、亮度和色饱和度的变化情形表现得很清楚。 通常把色调和饱和度通称为色度,用来表示颜色的类别与深浅程度。由于人的视觉对亮度的敏感 程度远强于对颜色浓淡的敏感程度,为了便于色彩处理和识别,人的视觉系统经常采用HSI色彩空间, 它比RGB色彩空间更符合人的视觉特性。在图像处理和计算机视觉中大量算法都可在HSI色彩空间中 方便地使用,它们可以分开处理而且是相互独立的。因此,在HSI色彩空间可以大大简化图像分析 和处理的工作量。HSI色彩空间和RGB色彩空间只是同一物理量的不同表示法,因而它们之间存在着 转换关系。
HSI 色彩模型是从人的视觉系统出发,用 H 代表色相 (Hue)、S 代表饱和度 (Saturation) 和 I 代表亮度 (Intensity) 来描述色彩。饱和度与颜色的白光光量刚好成反比,它可以说是一个颜色鲜明与否的指标。因此如果我们在显示器上使用 HIS 模型来处理图像,将能得到较为逼真的效果。
色相 (Hue):指物体传导或反射的波长。更常见的是以颜色如红色,橘色或绿色来辨识,取 0 到 360 度的数值来衡量。
饱和度 (Saturation):又称色度,是指色彩的强度或纯度。饱和度代表灰色与色调的比例,并以 0% (灰色) 到 100% (完全饱和) 来衡量。
亮度 (Intensity):是指颜色的相对明暗度,通常以 0% (黑色) 到 100% (白色) 的百分比来衡量。
- //RGB转换为HSI
- void rtRGB2HSI(RtScalar rgb, RtScalar& hsi)
- {
- double maxv = 0, minv = 0, angle = 0;
- RtScalar temp;
- temp.val[0] = rgb.val[0] / 255.0;
- temp.val[1] = rgb.val[1] / 255.0;
- temp.val[2] = rgb.val[2] / 255.0;
- maxv = max(max(temp.val[0], temp.val[1]), temp.val[2]);
- minv = min(min(temp.val[0], temp.val[1]), temp.val[2]);
- hsi.val[2] = (temp.val[0] + temp.val[1] + temp.val[2]) / 3.0;
- hsi.val[1] = 1.0 - minv/hsi.val[2];
- angle = (temp.val[0] + temp.val[0] - temp.val[1] - temp.val[2]) / 2.0 * sqrt((temp.val[0] - temp.val[1])*(temp.val[0] - temp.val[1]) + (temp.val[0] - temp.val[2])*(temp.val[1] - temp.val[2]));
- if (temp.val[2] <= temp.val[1])
- hsi.val[0] = angle / PI * 180.0;
- else
- hsi.val[0] = (2 * PI - angle)/PI * 180.0;
- }
- //HSI转换为RGB
- void rtHSI2RGB(RtScalar hsi, RtScalar& rgb)
- {
- int flag = 0;
- double t1 = 0, t2 = 0, tv1 = 0, tv2 = 0, tv3 = 0;
- RtScalar temp;
- temp = hsi;
- temp.val[0] = hsi.val[0] * PI / 180.0;
- t1 = 2.0 * PI / 3.0;
- t2 = 2.0 * t1;
- if (temp.val[0] >= t1 && temp.val[0] < t2)
- {
- flag = 1;
- temp.val[0] -= t1;
- }
- if (temp.val[0] >= t2)
- {
- flag = 2;
- temp.val[0] -= t2;
- }
- tv1 = (temp.val[2] * (1 - temp.val[1])) * 255.0;
- tv2 = (temp.val[2] * (1 + temp.val[1] * cos(temp.val[0]) / cos(PI / 3 - temp.val[0]))) * 255.0;
- tv3 = (3.0 * temp.val[2] - tv1 - tv2) * 255.0;
- switch (flag)
- {
- case 0:
- rgb = rtScalar(tv2, tv3, tv1, 0);
- break;
- case 1:
- rgb = rtScalar(tv1, tv2, tv3, 0);
- break;
- case 2:
- rgb = rtScalar(tv3, tv1, tv2, 0);
- break;
- }
- }
3、YUV颜色空间
在现代彩色电视系统中,通常采用三管彩色摄像机或彩色CCD(点耦合器件)摄像机,它把摄得的彩色图像 信号,经分色、分别放大校正得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号R-Y、B-Y, 最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这就是我们常用的YUV色彩空间。 采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V分量, 那么这样表示的图就是黑白灰度图。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机 的兼容问题,使黑白电视机也能接收彩色信号。根据美国国家电视制式委员会,NTSC制式的标准,当白光的 亮度用Y来表示时,它和红、绿、蓝三色光的关系可用如下式的方程描述:Y=0.3R+0.59G+0.11B 这就是常用 的亮度公式。色差U、V是由B-Y、R-Y按不同比例压缩而成的。如果要由YUV空间转化成RGB空间,只要进行 相反的逆运算即可。与YUV色彩空间类似的还有Lab色彩空间,它也是用亮度和色差来描述色彩分量,其中L为 亮度、a和b分别为各色差分量。
YUV与RGB相互转换的公式如下(RGB取值范围均为0-255):
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
- // RGB转换为YUV
- void rtRGB2YUV(RtScalar rgb, RtScalar& yuv)
- {
- yuv.val[0] = 0.299*rgb.val[0] + 0.587*rgb.val[1] + 0.114*rgb.val[2]; // y
- yuv.val[1] = -0.147*rgb.val[0] - 0.289*rgb.val[1]+ 0.436*rgb.val[2]; // u
- yuv.val[2] = 0.615*rgb.val[0] - 0.515*rgb.val[1] - 0.1*rgb.val[2]; // v
- }
- // YUV转换为RGB
- void rtYUV2RGB(RtScalar yuv, RtScalar& rgb)
- {
- rgb.val[0] = yuv.val[0] + 1.14*yuv.val[2]; // r
- rgb.val[1] = yuv.val[0] - 0.39*yuv.val[1] - 0.58*yuv.val[2];
- rgb.val[2] = yuv.val[0] + 2.03*yuv.val[1];
- }
4、XYZ颜色空间
国际照明委员会(CIE)在进行了大量正常人视觉测量和统计,1931年建立了"标准色度观察者", 从而奠定了现代CIE标准色度学的定量基础。由于"标准色度观察者"用来标定光谱色时出现负刺激值,计算不便,也不易理解,因此1931年CIE在RGB 系统基础上,改用三个假想的原色X、Y、 Z建立了一个新的色度系统。将它匹配等能光谱的三刺激值,定名为"CIE1931 标准色度观察者光谱三刺激值",简称为"CIE1931标准色度观察者"。这一系统叫做"CIE1931标准色度系统"或称为" 2° 视场XYZ色度系统"。CIEXYZ颜色空间稍加变换就可得到Yxy色彩空间,其中Y取三刺激值中Y的值, 表示亮度,x、y反映颜色的色度特性。定义如下:在色彩管理中,选择与设备无关的颜色空间是 十分重要的,与设备无关的颜色空间由国际照明委员会(CIE)制定,包括CIEXYZ和CIELAB两个标准。 它们包含了人眼所能辨别的全部颜色。而且,CIEYxy测色制的建立给定量的确定颜色创造了条件。 但是,在这一空间中,两种不同颜色之间的距离值并不能正确地反映人们色彩感觉差别的大小, 也就是说在CIEYxy色厦图中,在 不同的位置不同方向上颜色的宽容量是不同的,这就是Yxy颜色空间 的不均匀性。这一缺陷的存在,使得在Yxy及XYZ空间不能直观地评价颜色。
Some Common RGB Working Space Matrices
Using the chromaticities and reference whites of common RGB working spaces, I have done the math for you to compute the RGB-to-XYZ and XYZ-to-RGB matrices. Note that these matrices are given relative to their own reference whites. If you examine the matrices for these working spaces found inside ICC profiles (through the redColorantTag, greenColorantTag andblueColorantTag), those matrices will always be relative to D50, and therefore, the colorants have been subjected to a chromatic adaptation transformation if the working space reference white is not also D50.
RGB Working Space | Reference White | RGB to XYZ [M] | XYZ to RGB [M]-1 |
Adobe RGB (1998) | D65 | 0.5767309 0.1855540 0.1881852
0.2973769 0.6273491 0.0752741
0.0270343 0.0706872 0.9911085 | 2.0413690 -0.5649464 -0.3446944
-0.9692660 1.8760108 0.0415560
0.0134474 -0.1183897 1.0154096 |
AppleRGB | D65 | 0.4497288 0.3162486 0.1844926
0.2446525 0.6720283 0.0833192
0.0251848 0.1411824 0.9224628 | 2.9515373 -1.2894116 -0.4738445
-1.0851093 1.9908566 0.0372026
0.0854934 -0.2694964 1.0912975 |
Best RGB | D50 | 0.6326696 0.2045558 0.1269946
0.2284569 0.7373523 0.0341908
0.0000000 0.0095142 0.8156958 | 1.7552599 -0.4836786 -0.2530000
-0.5441336 1.5068789 0.0215528
0.0063467 -0.0175761 1.2256959 |
Beta RGB | D50 | 0.6712537 0.1745834 0.1183829
0.3032726 0.6637861 0.0329413
0.0000000 0.0407010 0.7845090 | 1.6832270 -0.4282363 -0.2360185
-0.7710229 1.7065571 0.0446900
0.0400013 -0.0885376 1.2723640 |
Bruce RGB | D65 | 0.4674162 0.2944512 0.1886026
0.2410115 0.6835475 0.0754410
0.0219101 0.0736128 0.9933071 | 2.7454669 -1.1358136 -0.4350269
-0.9692660 1.8760108 0.0415560
0.0112723 -0.1139754 1.0132541 |
CIE RGB | E | 0.4887180 0.3106803 0.2006017
0.1762044 0.8129847 0.0108109
0.0000000 0.0102048 0.9897952 | 2.3706743 -0.9000405 -0.4706338
-0.5138850 1.4253036 0.0885814
0.0052982 -0.0146949 1.0093968 |
ColorMatch RGB | D50 | 0.5093439 0.3209071 0.1339691
0.2748840 0.6581315 0.0669845
0.0242545 0.1087821 0.6921735 | 2.6422874 -1.2234270 -0.3930143
-1.1119763 2.0590183 0.0159614
0.0821699 -0.2807254 1.4559877 |
Don RGB 4 | D50 | 0.6457711 0.1933511 0.1250978
0.2783496 0.6879702 0.0336802
0.0037113 0.0179861 0.8035125 | 1.7603902 -0.4881198 -0.2536126
-0.7126288 1.6527432 0.0416715
0.0078207 -0.0347411 1.2447743 |
ECI RGB | D50 | 0.6502043 0.1780774 0.1359384
0.3202499 0.6020711 0.0776791
-0.0000000 0.0678390 0.7573710 | 1.7827618 -0.4969847 -0.2690101
-0.9593623 1.9477962 -0.0275807
0.0859317 -0.1744674 1.3228273 |
Ekta Space PS5 | D50 | 0.5938914 0.2729801 0.0973485
0.2606286 0.7349465 0.0044249
0.0000000 0.0419969 0.7832131 | 2.0043819 -0.7304844 -0.2450052
-0.7110285 1.6202126 0.0792227
0.0381263 -0.0868780 1.2725438 |
NTSC RGB | C | 0.6068909 0.1735011 0.2003480
0.2989164 0.5865990 0.1144845
-0.0000000 0.0660957 1.1162243 | 1.9099961 -0.5324542 -0.2882091
-0.9846663 1.9991710 -0.0283082
0.0583056 -0.1183781 0.8975535 |
PAL/SECAM RGB | D65 | 0.4306190 0.3415419 0.1783091
0.2220379 0.7066384 0.0713236
0.0201853 0.1295504 0.9390944 | 3.0628971 -1.3931791 -0.4757517
-0.9692660 1.8760108 0.0415560
0.0678775 -0.2288548 1.0693490 |
ProPhoto RGB | D50 | 0.7976749 0.1351917 0.0313534
0.2880402 0.7118741 0.0000857
0.0000000 0.0000000 0.8252100 | 1.3459433 -0.2556075 -0.0511118
-0.5445989 1.5081673 0.0205351
0.0000000 0.0000000 1.2118128 |
SMPTE-C RGB | D65 | 0.3935891 0.3652497 0.1916313
0.2124132 0.7010437 0.0865432
0.0187423 0.1119313 0.9581563 | 3.5053960 -1.7394894 -0.5439640
-1.0690722 1.9778245 0.0351722
0.0563200 -0.1970226 1.0502026 |
sRGB | D65 | 0.4124564 0.3575761 0.1804375
0.2126729 0.7151522 0.0721750
0.0193339 0.1191920 0.9503041 | 3.2404542 -1.5371385 -0.4985314
-0.9692660 1.8760108 0.0415560
0.0556434 -0.2040259 1.0572252 |
Wide Gamut RGB | D50 | 0.7161046 0.1009296 0.1471858
0.2581874 0.7249378 0.0168748
0.0000000 0.0517813 0.7734287 | 1.4628067 -0.1840623 -0.2743606
-0.5217933 1.4472381 0.0677227
0.0349342 -0.0968930 1.2884099 |
For those RGB working spaces that are not natively D50, the Bradford-adapted, D50 matrices are:
RGB Working Space | Reference White | RGB to XYZ [M] | XYZ to RGB [M]-1 |
Adobe RGB (1998) | D50 | 0.6097559 0.2052401 0.1492240
0.3111242 0.6256560 0.0632197
0.0194811 0.0608902 0.7448387 | 1.9624274 -0.6105343 -0.3413404
-0.9787684 1.9161415 0.0334540
0.0286869 -0.1406752 1.3487655 |
AppleRGB | D50 | 0.4755678 0.3396722 0.1489800
0.2551812 0.6725693 0.0722496
0.0184697 0.1133771 0.6933632 | 2.8510695 -1.3605261 -0.4708281
-1.0927680 2.0348871 0.0227598
0.1027403 -0.2964984 1.4510659 |
Bruce RGB | D50 | 0.4941816 0.3204834 0.1495550
0.2521531 0.6844869 0.0633600
0.0157886 0.0629304 0.7464909 | 2.6502856 -1.2014485 -0.4289936
-0.9787684 1.9161415 0.0334540
0.0264570 -0.1361227 1.3458542 |
CIE RGB | D50 | 0.4868870 0.3062984 0.1710347
0.1746583 0.8247541 0.0005877
-0.0012563 0.0169832 0.8094831 | 2.3638081 -0.8676030 -0.4988161
-0.5005940 1.3962369 0.1047562
0.0141712 -0.0306400 1.2323842 |
NTSC RGB | D50 | 0.6343706 0.1852204 0.1446290
0.3109496 0.5915984 0.0974520
-0.0011817 0.0555518 0.7708399 | 1.8464881 -0.5521299 -0.2766458
-0.9826630 2.0044755 -0.0690396
0.0736477 -0.1453020 1.3018376 |
PAL/SECAM RGB | D50 | 0.4552773 0.3675500 0.1413926
0.2323025 0.7077956 0.0599019
0.0145457 0.1049154 0.7057489 | 2.9603944 -1.4678519 -0.4685105
-0.9787684 1.9161415 0.0334540
0.0844874 -0.2545973 1.4216174 |
SMPTE-C RGB | D50 | 0.4163290 0.3931464 0.1547446
0.2216999 0.7032549 0.0750452
0.0136576 0.0913604 0.7201920 | 3.3921940 -1.8264027 -0.5385522
-1.0770996 2.0213975 0.0207989
0.0723073 -0.2217902 1.3960932 |
sRGB | D50 | 0.4360747 0.3850649 0.1430804
0.2225045 0.7168786 0.0606169
0.0139322 0.0971045 0.7141733 | 3.1338561 -1.6168667 -0.4906146
-0.9787684 1.9161415 0.0334540
0.0719453 -0.2289914 1.4052427 |
- //RGB转换为XYZ
- void rtRGB2XYZ(RtScalar rgb, RtScalar& xyz)
- {
- //Observer. = 2°,Illuminant = D65
- xyz.val[0] = 0.4124564 * rgb.val[0] + 0.3575761 * rgb.val[1] + 0.1804375 * rgb.val[2];
- xyz.val[1] = 0.2126729 * rgb.val[0] + 0.7151522 * rgb.val[1] + 0.0721750 * rgb.val[2];
- xyz.val[2] = 0.0193339 * rgb.val[0] + 0.1191920 * rgb.val[1] + 0.9503041 * rgb.val[2];
- }
- //XYZ转换为RGB
- void rtXYZ2RGB(RtScalar xyz, RtScalar& rgb)
- {
- rgb.val[0] = 3.2404542 * xyz.val[0] + -1.5371385 * xyz.val[1] + -0.4985314 * xyz.val[2];
- rgb.val[1] = -0.9692660 * xyz.val[0] + 1.8760108 * xyz.val[1] + 0.0415560 * xyz.val[2];
- rgb.val[2] = 0.0556434 * xyz.val[0] + x-0.2040259 * xyz.val[1] + 1.0572252 * xyz.val[2];
- }
5、Lab 颜色空间
CIE L*a*b* (CIELAB) 是惯常用来描述人眼可见的所有颜色的最完备的色彩模型。它是为这个特殊目的而由国际照明委员会(Commission Internationale d'Eclairage 的首字母是 CIE)提出的。L、a 和 b 后面的星号(*)是全名的一部分,因为它们表示 L*, a* 和 b*,不同于 L, a 和 b。因为红/绿和黄/蓝对立通道被计算为(假定的)锥状细胞响应的类似孟塞尔值的变换的差异,CIELAB 是 Adams 色彩值(Chromatic Value)空间。
三个基本坐标表示颜色的亮度(L*, L* = 0 生成黑色而 L* = 100 指示白色),它在红色/品红色和绿色之间的位置(a* 负值指示绿色而正值指示品红)和它在黄色和蓝色之间的位置(b* 负值指示蓝色而正值指示黄色)。
已经建立的 L*a*b* 色彩模型来充当用做参照的设备无关的模型。要认识到永远不能精确的在视觉上表示这个模型中颜色的完全色域是至关重要的。它们只是用来帮助理解概念而天生就不精确的,因为 L*a*b* 模型是三维模型,它只能在三维空间中完全表现出来。“L*a*b*”模型也被表达为“L*C*h(a*, b*)”,它把 a* 和 b* 变换为辐射表示。
XYZ 与 CIE L*a*b* (CIELAB) 的转换:
- double _rtLabFun(double val)
- {
- if (val > 0.008856)
- return val/3.0
- else
- return 7.787 * val + 16.0/116.0
- }
- //XYZ转换为LAB
- void rtXYZ2LAB(RtScalar xyz, RtScalar& lab)
- {
- RtScalar temp;
- temp = RtScalar(xyz.val[0]/255.0, xyz.val[1]/255.0, xyz.val[2]/255.0, 0);
- if (temp.val[1] > 0.008856)
- {
- lab.val[0] = 116.0 * temp.val[1] / 3;
- }
- else
- {
- lab.val[0] = 903.3 * temp.val[1];
- }
- lab.val[1] = 500.0*(_rtLabFun(temp.val[0]) - _rtLabFun(temp.val[1]));
- lab.val[2] = 200.0*(_rtLabFun(temp.val[1]) - _rtLabFun(temp.val[2]));
- }
- //LAB转换为XYZ
- void rtLAB2XYZ(RtScalar lab, RtScalar& xyz)
- {
- RtScalar temp;
- temp.val[0] = 3 * lab.val[0] / 116.0;
- temp.val[1] = lab.val[1]/500.0 + temp.val[0];
- temp.val[2] = temp.val[0] - lab.val[2] / 200.0;
- if ( temp.val[0] > 0.008856 )
- temp.val[0] = temp.val[0] * 3;
- else
- temp.val[0] = (temp.val[0] - 16.0/116.0) / 7.787;
- if ( temp.val[1] > 0.008856 )
- temp.val[1] = temp.val[1] * 3;
- else
- temp.val[1] = (temp.val[1] - 16.0/116.0) / 7.787;
- if ( temp.val[2] > 0.008856 )
- temp.val[2] = temp.val[2] * 3;
- else
- temp.val[2]= ( temp.val[2] - 16.0/116.0) / 7.787;
- xyz = rtScalar(temp.val[0]*255.0, temp.val[1]*255.0, temp.val[2]*255.0, 0);
- }
6、HSL 或 HSV 的转换
HSV(hue,saturation,value)颜色空间的模型对应于圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于V=1. 它包含RGB模型中的R=1,G=1,B=1 三个面,所代表的颜色较亮。色彩H由绕V轴的旋转角给定。红色对应于 角度0° ,绿色对应于角度120°,蓝色对应于角度240°。在HSV颜色模型中,每一种颜色和它的补色相差180° 。 饱和度S取值从0到1,所以圆锥顶面的半径为1。HSV颜色模型所代表的颜色域是CIE色度图的一个子集,这个 模型中饱和度为百分之百的颜色,其纯度一般小于百分之百。在圆锥的顶点(即原点)处,V=0,H和S无定义, 代表黑色。圆锥的顶面中心处S=0,V=1,H无定义,代表白色。从该点到原点代表亮度渐暗的灰色,即具有不同 灰度的灰色。对于这些点,S=0,H的值无定义。可以说,HSV模型中的V轴对应于RGB颜色空间中的主对角线。 在圆锥顶面的圆周上的颜色,V=1,S=1,这种颜色是纯色。HSV模型对应于画家配色的方法。画家用改变色浓和 色深的方法从某种纯色获得不同色调的颜色,在一种纯色中加入白色以改变色浓,加入黑色以改变色深,同时 加入不同比例的白色,黑色即可获得各种不同的色调。
形式定义设 (r, g, b) 分别是一个颜色的红、绿和蓝坐标,它们的值是在 0 到 1 之间的实数。设 max 等价于 r, g 和 b 中的最大者。设 min 等于这些值中的最小者。要找到在 HSL 空间中的 (h, s, l) 值,这里的 h ∈ [0, 360)是角度的色相角,而 s, l ∈ [0,1] 是饱和度和亮度,计算为:
h 的值通常规范化到位于 0 到 360°之间。而 h = 0 用于 max = min 的(就是灰色)时候而不是留下 h 未定义。
HSL 和 HSV 有同样的色相定义,但是其他分量不同。HSV 颜色的 s 和 v 的值定义如下:
从 HSL 到 RGB 的转换
给定 HSL 空间中的 (h, s, l) 值定义的一个颜色,带有 h 在指示色相角度的值域 [0, 360)中,分别表示饱和度和亮度的 s 和 l 在值域 [0, 1] 中,相应在 RGB 空间中的 (r, g, b) 三原色,带有分别对应于红色、绿色和蓝色的 r, g 和 b 也在值域 [0, 1] 中,它们可计算为:
首先,如果 s = 0,则结果的颜色是非彩色的、或灰色的。在这个特殊情况,r, g 和 b 都等于 l。注意 h 的值在这种情况下是未定义的。
当 s ≠ 0 的时候,可以使用下列过程:
![](http://hi.csdn.net/attachment/201006/24/0_1277361928nEeB.gif)
从 HSV 到 RGB 的转换 类似的,给定在 HSV 中 (h, s, v) 值定义的一个颜色,带有如上的 h,和分别表示饱和度和明度的 s 和 v 变化于 0 到 1 之间,在 RGB 空间中对应的 (r, g, b) 三原色可以计算为:
- // RGB转换为HSV
- void rtRGB2HSV(RtScalar rgb, RtScalar& hsv)
- {
- double minV = 0,maxV = 0, delMax = 0;
- minV = min(min(rgb.val[0], rgb.val[1]), rgb.val[2]);
- maxV = max(max(rgb.val[0], rgb.val[1]), rgb.val[2]);
- delMax = maxV - minV;//Delta RGB value
- if (minV == maxV)
- {
- hsv.val[0] = 0;
- }
- if (maxV == rgb.val[0] && rgb.val[1] >= rgb.val[2])
- {
- hsv.val[0] = (rgb.val[1] - rgb.val[2])/delMax * 60.0;
- }
- if (maxV == rgb.val[0] && rgb.val[1] < rgb.val[2])
- {
- hsv.val[0] = (rgb.val[1] - rgb.val[2])/delMax * 60.0 + 360;
- }
- if (maxV == rgb.val[1])
- {
- hsv.val[0] = (rgb.val[2] - rgb.val[0])/delMax * 60.0 + 120;
- }
- if (maxV == rgb.val[2])
- {
- hsv.val[0] = (rgb.val[0] - rgb.val[1])/delMax * 60.0 + 240;
- }
- if (maxV == 0)
- hsv.val[1] = 0;
- else
- hsv.val[1] = 1.0 - minV/maxV;
- hsv.val[2] = maxV;
- }
- // HSV转换为RGB
- void rtHSV2RGB(RtScalar hsv, RtScalar& rgb)
- {
- if ( hsv.val[1] == 0 )
- {
- rgb = rtScalar(hsv.val[2], hsv.val[2], hsv.val[2], 0);
- }
- else
- {
- double varh,vari,var1,var2,var3;
- varh = hsv.val[0] /60.0;
- vari = int(varh);
- var1 = hsv.val[0] * (1.0 - hsv.val[1]);
- var2 = hsv.val[0] * (1.0 - hsv.val[1]* (hsv.val[0] - vari));
- var3 = hsv.val[0] * (1.0 - hsv.val[1]* (1.0 - (hsv.val[0] - vari)));
- switch (vari)
- {
- case 0:
- rgb = rtScalar(hsv.val[0], var3, var1, 0);
- break;
- case 1:
- rgb = rtScalar(var2, hsv.val[0], var1, 0);
- break;
- case 2:
- rgb = rtScalar(var1, hsv.val[0], var3, 0);
- break;
- case 3:
- rgb = rtScalar(var1, var2, hsv.val[0], 0);
- break;
- case 4:
- rgb = rtScalar(var3, var1, hsv.val[0], 0);
- break;
- case 5:
- rgb = rtScalar(hsv.val[0], var1, var2, 0);
- break;
- }
- }
- }
(完)