目前在计算机视觉领域存在着较多类型的颜色空间(color space)。HSL和HSV是两种最常见的圆柱坐标表示的颜色模型,它重新影射了RGB模型,从而能够视觉上比RGB模型更具有视觉直观性。 HSV颜色空间
HSI颜色空间 HSI 色彩模型是从人的视觉系统出发,用 H 代表色相 (Hue)、S 代表饱和度 (Saturation) 和
I 代表亮度 (Intensity) 来描述色彩。饱和度与颜色的白光光量刚好成反比,它可以说是一个颜色鲜明与否的指标。因此如果我们在显示器上使用 HIS
模型来处理图像,将能得到较为逼真的效果。
用圆锥模型如图: 在圆锥上,角度代表色调H,饱和度S表示为点到中心竖线的距离,而亮度或者值V用中心竖线表示。红色的角度为0度,依次为黄色、绿色、青色、蓝色、橙色。连续两种颜色的角度相差60度。 下图给出了一个RGB到HS平面的影射例子。
那么如何从RGB到HSL和HSV的转换呢?利用下面的步骤就可以实现从RGB到HSL和HSV的转换。
计算H:
计算L和V:
计算S: 上面的公式实现了从RGB到HSL和HSV的转换。那么当采用Opencv的彩色空间转化函数cvCvtColor(orgFrame,destFrame, CV_BGR2HSV),如果图像的数据类型为8位字符型时,则H、S、V都量化到整数{0~255},可以看出H的精度不是很高。
计算C
最后得到:
从HSL到RGB的转换。这里H ∈ [0°, 360°], S ∈ [0, 1], V ∈ [0, 1]。转换公式如下: 然后:
最后得到: 展示的 RGB 值的范围是 0.0 到 1.0。
001. //
/////////////////////////////////////////////////////////////////////
002. //
003. //
cvlab.net 004. // C/C++
Macro RGB to HSV 005. #define
PIX_RGB_TO_HSV_COMMON(R,G,B,H,S,V,NORM) \
006. if ((B > G) && (B >
R)) \
007. {
\ 008. V =
B; \
009. if (V !=
0) \
010. {
\ 011. double min; \
012. if (R > G) min
= G; \
013. else min =
R; \ 014. const double delta = V -
min; \ 015. if (delta !=
0) \
016. { S = (delta/V); H = 4 + (R - G) / delta;
} \ 017. else
\ 018. { S = 0; H = 4 + (R - G);
} \ 019. H *= 60; if (H < 0) H +=
360; \ 020. if (!NORM) V =
(V/255); \
021. else S *=
(100); \
022. }
\ 023. else
\ 024. { S = 0; H =
0;} \
025. }
\ 026. else if (G > R) \
027. {
\ 028. V =
G; \
029. if (V !=
0) \
030. {
\ 031. double min; \
032. if (R > B) min
= B; \
033. else min =
R; \ 034. const double delta = V -
min; \ 035. if (delta !=
0) \
036. { S = (delta/V); H = 2 + (B - R) / delta;
} \ 037. else
\ 038. { S = 0; H = 2 + (B - R);
} \ 039. H *= 60; if (H < 0) H +=
360; \ 040. if (!NORM) V =
(V/255); \
041. else S *=
(100); \
042. }
\ 043. else
\ 044. { S = 0; H =
0;} \
045. }
\ 046. else
\ 047. {
\ 048. V =
R; \
049. if (V !=
0) \
050. {
\ 051. double min; \
052. if (G > B) min
= B; \
053. else min =
G; \ 054. const double delta = V -
min; \ 055. if (delta !=
0) \
056. { S = (delta/V); H = (G - B) / delta;
} \ 057. else
\ 058. { S = 0; H = (G - B);
} \ 059. H *= 60; if (H < 0) H +=
360; \ 060. if (!NORM) V =
(V/255); \
061. else S *=
(100); \
062. }
\ 063. else
\ 064. { S = 0; H =
0;} \
065. }
066. 067. //
//////////////////////////////////////////////////////////////////
068. //
069. //
cvlab.net 070. // C/C++
Macro HSV to RGB 071. #define
PIX_HSV_TO_RGB_COMMON(H,S,V,R,G,B) \
072. if ( V == 0
) \
073. { R = 0; G =
0; B = 0; } \
074. else if ( S == 0 ) \
075. {
\ 076. R =
V; \
077. G =
V; \
078. B =
V; \
079. }
\ 080. else
\ 081. {
\ 082. const double hf = H /
60.0; \ 083. const int i = ( int ) floor ( hf
); \ 084. const double f = hf -
i; \ 085. const double pv = V * ( 1 - S
); \ 086. const double qv = V * ( 1 - S * f
); \ 087. const double tv = V * ( 1 - S * ( 1 - f
) ); \ 088. switch ( i
) \
089. { \
090. case 0: \
091. R =
V; \
092. G =
tv; \
093. B =
pv; \
094. break ; \
095. case 1: \
096. R =
qv; \
097. G =
V; \
098. B =
pv; \
099. break ; \
100. case 2: \
101. R =
pv; \
102. G =
V; \
103. B =
tv; \
104. break ; \
105. case 3: \
106. R =
pv; \
107. G =
qv; \
108. B =
V; \
109. break ; \
110. case 4: \
111. R =
tv; \
112. G =
pv; \
113. B =
V; \
114. break ; \
115. case 5: \
116. R =
V; \
117. G =
pv; \
118. B =
qv; \
119. break ; \
120. case 6: \
121. R =
V; \
122. G =
tv; \
123. B =
pv; \
124. break ; \
125. case -1: \
126. R =
V; \
127. G =
pv; \
128. B =
qv; \
129. break ; \
130. default : \
131. LFATAL( "i Value error in
Pixel conversion, Value is %d" ,i); \
132. break ; \
133. } \
134. }
\ 135. R *=
255.0F; \
136. G *=
255.0F; \
137. B *=
255.0F;
==============================================================================================================
|
|