HSV是对RGB色彩空间中点的两种有关系的表示,它们尝试描述比 RGB 更准确的感知颜色联系,并仍保持在计算上简单。
HSV表示 hue(色度)、saturation(饱和度)、value(色调) 。
HSV 把颜色描述在圆柱体内的点,这个圆柱的中心轴取值为自底部的黑色到顶部的白色而在它们中间是的灰色,绕这个轴的角度对应于“色相”,到这个轴的距离对应于“饱和度”,而沿着这个轴的距离对应于“亮度”,“色调”或“明度”。
设 (r, g, b) 分别是一个颜色的红、绿和蓝坐标,它们的值是在 0 到 1 之间的实数。设 max 等价于 r, g 和 b 中的最大者。设 min 等于这些值中的最小者。这里的 h ∈ [0, 360)是角度的色相角,而 s, v∈ [0,1] 是饱和度和亮度,计算为:
h 的值通常规范化到位于 0 到 360°之间。而 h = 0 用于 max = min 的(就是灰色)时候而不是留下 h 未定义。
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
void Rgb2Hsv(float R, float G, float B, float& H, float& S, float&V)
{
// r,g,b values are from 0 to 1
// h = [0,360], s = [0,1], v = [0,1]
// if s == 0, then h = -1 (undefined)
float min, max, delta, tmp;
tmp = R>G ? G : R;
min = tmp>B ? B : tmp;
tmp = R>G ? R : G;
max = tmp>B ? tmp : B;
V = max / 255 * 100; // v
delta = max - min;
if (max != 0)
S = delta / max *100; // s
else
{
// r = g = b = 0 // s = 0, v is undefined
S = 0;
H = 0;
return;
}
if (delta == 0)
{
H = 0;
return;
}
else if (R == max)
{
if (G >= B)
H = (G - B) / delta; // between yellow & magenta
else
H = (G - B) / delta + 6.0;
}
else if (G == max)
H = 2.0 + (B - R) / delta; // between cyan & yellow
else if (B == max)
H = 4.0 + (R - G) / delta; // between magenta & cyan
H *= 60.0; // degrees
}
int main()
{
Mat srcImage = imread(imagename,1);
if (!srcImage.data)
return 0;
int row = srcImage.rows;
int col = srcImage.cols;
Mat hsvimg= Mat(row, col ,CV_8UC3);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
float b = srcImage.at(i, j)[0];
float g = srcImage.at(i, j)[1];
float r = srcImage.at(i, j)[2];
float h, s, v;
Rgb2Hsv(r, g, b, h, s, v);
hsvimg.at(i, j)[0] = h;//h数值若大于255会自动减去255,推荐在ImageWatch模式下查看结果
hsvimg.at(i, j)[1] = s;
hsvimg.at(i, j)[2] = v;
}
}
waitKey(0);
return 0;
}