目录
1 RGB 的局限性
RGB 是我们接触最多的颜色空间,由三个通道表示一幅图像,分别为红色(R),绿色(G)和蓝色(B)。这三种颜色的不同组合可以形成几乎所有的其他颜色。
RGB 颜色空间是图像处理中最基本、最常用、面向硬件的颜色空间,比较容易理解。
RGB 颜色空间利用三个颜色分量的线性组合来表示颜色,任何颜色都与这三个分量有关,而且这三个分量是高度相关的,所以连续变换颜色时并不直观,想对图像的颜色进行调整需要更改这三个分量才行。
自然环境下获取的图像容易受自然光照、遮挡和阴影等情况的影响,即对亮度比较敏感。而 RGB 颜色空间的三个分量都与亮度密切相关,即只要亮度改变,三个分量都会随之相应地改变,而没有一种更直观的方式来表达
但是人眼对于这三种颜色分量的敏感程度是不一样的,在单色中,人眼对红色最不敏感,蓝色最敏感,所以 RGB 颜色空间是一种均匀性较差的颜色空间。如果颜色的相似性直接用欧氏距离来度量,其结果与人眼视觉会有较大的偏差。对于某一种颜色,我们很难推测出较为精确的三个分量数值来表示。所以,RGB 颜色空间适合于显示系统,却并不适合于图像处理。
2 HSV 颜色空间
基于上述理由,在图像处理中使用较多的是 HSV 颜色空间,它比 RGB 更接近人们对彩色的感知经验。非常直观地表达颜色的色调、鲜艳程度和明暗程度,方便进行颜色的对比。
在 HSV 颜色空间下,比 RGB 更容易跟踪某种颜色的物体,常用于分割指定颜色的物体。
HSV 表达彩色图像的方式由三个部分组成:
-
Hue(色调、色相),相当于基调,是下图的俯视图得到的圆,圆上不同位置的颜色基调不同,把颜色分成了360°,每个位置有不同的颜色基调;
-
Saturation(饱和度、色彩纯净度):纯度,沿着俯视图得到的圆的半径看,因为圆弧上的点代表该处的颜色的基调,那么半径上就是从纯白色到该基调颜色过渡过程中不同位置的纯度,在圆心处纯度为0,在圆弧上(该色调)纯度为100;
-
Value(明度):亮度,沿着圆柱的高来看,圆柱表面上平行于圆柱轴上的点的颜色基调相同,纯度也相同,但是明暗程度不同。同时,该圆柱的半径也不同,相当于磁盘的柱面。
用下面这个圆柱体来表示 HSV 颜色空间,圆柱体的横截面可以看做是一个极坐标系 ,H 用极坐标的极角表示,S 用极坐标的极轴长度表示,V 用圆柱中轴的高度表示。
-
色相H:表示色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,取值范围为0°~360°。其中0°为红色,60°为黄色,120°为绿色,180°为青色,240°为蓝色,300°为紫色。
-
饱和度S:表示色彩的纯度,取值范围为0.0~1.0。值越大,纯度越高,接近光谱色的程度也就越高,图像越鲜艳。
-
明度V:表示色彩的明亮程度,取值范围为0.0(黑色)~1.0(白色)。明度越高,色彩越亮。
3 RGB与HSV相互转换
了解了HSV的颜色特性之后,就可以在实际使用中RGB颜色值转换为HSV颜色值,然后对色相、饱和度和明度进行调整。达到效果需求之后,再转换为RGB值显示在屏幕上保存结果。
下面使用C语言编程实现RGB与HSV的转换
#include"TRGB2HSV.h"
#include"Commen.h"
#include<stdlib.h>
#include<math.h>
void RGB2HSV(unsigned char R, unsigned char G, unsigned char B, float* h, float* s, float * v)
{
float min, max;
float r = R / 255.0;
float g = G / 255.0;
float b = B / 255.0;
min = MIN2(r,MIN2(g,b));
max = MAX2(r,MAX2(g,b));
if (max == min)
*h = 0;
else if (max == r && g >= b)
*h = 60.0 * (g - b) / (max - min);
else if (max == r && g < b)
*h = 60.0 * (g - b) / (max - min) + 360.0;
else if (max == g)
*h = 60.0 * (b - r) / (max - min) + 120.0;
else if (max == b)
*h = 60.0 * (r - g) / (max - min) + 240.0;
*h = CLIP3(*h, 0, 360);
if (max == 0)
*s = 0;
else
*s = (max - min) / max;
*v = max;
};
void HSV2RGB(float h, float s, float v, unsigned char* R, unsigned char *G, unsigned char *B)
{
float q = 0, p = 0, t = 0, f = 0, r = 0, g = 0, b = 0;
int hN = 0;
if(h == 360)
h = 0;
if (h < 0)
h = 360 + h;
hN = (int)((int)h / 60);
f = h / 60.0f - hN;
p = v * (1.0 - s);
q = v * (1.0 - f * s);
t = v * (1.0 - (1.0 - f) * s);
switch (hN)
{
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
default:
break;
}
*R = (unsigned char)CLIP3((r * 255.0),0,255);
*G = (unsigned char)CLIP3((g * 255.0),0,255);
*B = (unsigned char)CLIP3((b * 255.0),0,255);
};
4 HSV颜色模型对图像的色相、饱和度和明度进行调节
/*************************************************
功 能:HSV调整
参 数:srcData - [输入/输出] 原始图像,格式为32位BGRA格式,执行后修为结果图像
width - [输入] 原始图像宽度
height - [输入] 原始图像高度
tride - [输入] 原始图像的Stride(也就是行字节数width*4)
hIntensity - [输入] h值
sIntensity - [输入] s值
vIntensity - [输入] v值
返 回: 0-成功, 其他-失败.
*************************************************/
int adjustHSV(unsigned char *srcData, int width, int height, int stride, float hIntensity, float sIntensity, float vIntensity)
{
int ret = 0;
if (srcData == NULL)
{
printf("input image is null!");
return -1;
}
//Process
unsigned char R, G, B;
float h = 0, s = 0, v = 0;
unsigned char* pSrc = srcData;
int offset = stride - width * 4;
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
B = pSrc[0];
G = pSrc[1];
R = pSrc[2];
RGB2HSV(R, G, B, &h, &s, &v);
h = h + hIntensity > 360 ? h + hIntensity - 360 : h + hIntensity;
s = CLIP3(s + sIntensity, 0, 1.0f);
v = CLIP3(v + vIntensity, 0, 1.0f);
HSV2RGB(h, s, v, &R, &G, &B);
pSrc[0] = B;
pSrc[1] = G;
pSrc[2] = R;
pSrc += 4;
}
pSrc += offset;
}
return ret;
};
5 演示Demo
5.1 开发环境
-
Windows 10 Pro x64
-
Visual Studio 2015
5.2 功能介绍
演示程序主界面如下图所示,具有图像读取、显示、保存、显示RGBA值,以及HSV调整、鼠标按键按下显示原图、鼠标按键抬起显示效果图等功能。
原图
效果图(h=26, s=0.12, v=0.16)
5.3 下载地址
开发环境:
-
Windows 10 pro x64
-
Visual Studio 2015
下载地址: 图像处理之HSV颜色空间
参考
图像视频滤镜与人像美颜美妆算法详解. 胡耀武、谭娟、李云夕. 电子工业出版社、2020-07