相关文章推荐
一身肌肉的泡面  ·  java - how to fix ...·  1 年前    · 
寂寞的茄子  ·  spring的@Scope注解 ...·  1 年前    · 
任性的高山  ·  Vuex的状态管理 - 简书·  1 年前    · 
逃课的风衣  ·  PySide2/QT for Python ...·  1 年前    · 

图像格式RGB/HSV/YUV

往期回顾:《 二值化图像切割,让机器人视觉识别变得简单高效

三通道彩色

图片也可以看作是三层二维数组的叠加,每一层二维数组都是一个通道。单通道的图像是灰色的,每个像素pixel只有一个value,数字越高,颜色越白,也就越亮。

单通道灰度

在一个定义好的色彩空间里,这三层的value分别代表着这个点在三个通道的数值,计算机根据这些数值来确定这一个像素点的颜色。

每个不同的色彩空间都有着自己的调色盘, 不同的色彩空间对于数值有着不同的规定 。根据调色盘,像素在屏幕上的显示出自己的颜色。

RGB 色彩空间

橙色的萝卜其实由三个萝卜一起构成:“红萝卜”+“绿箩卜”+“蓝萝卜”。这就常见的 RGB 色彩空间的工作方式。


RGB 色彩空间

RGB 是最常用于显示器的色彩空间, R(red)是红色通道,G(green)是绿色,B(blue)是蓝色通道 。这三种颜色以不同的量进行叠加,就可以显示出五彩缤纷的色彩。


RGB 色彩空间

RGB 格式里(0,0,0)代表着黑色,(255,255,255)代表着白色。R channel数值越高,说明颜色中含有的红色分量越多。

通常,RGB 格式的图片都是用于计算机屏幕显示。注意: OpenCV(开源计算机视觉库,包含了许多可用的视觉算法,图像处理必备神器)图像通道的默认排序是 BGR。

现在我们以这张草莓图片为例,用 RGB 通道提取草莓,姑且把这张图片叫做 Strawberry。

原图

我们使用 OpenCV 的 Split 函数,对它进行分离通道的操作,把它分别变成三张单通道的图片。 献上代码君:

B, G, R = cv2.split(Strawberry)

*本文的代码都是在 python3.6+opencv3.2+numpy 环境运行。

R 通道、G 通道、B 通道

因为单通道的图每个像素点只有一个数值,所以处理后的图片是灰色的。我们发现处理后的草莓在 R 通道比较亮,但是在 G 通道和 B 通道都比较黑。

这是因为草莓 含的红色比较多 ,所以在 R 通道中的数值比较高 ,数值越高也就 越亮 。白色花瓣在三张图中都是白色,因为白色含的红、绿、蓝色都很多,所以不管在哪个通道,都会很亮。

在关于二值化的文章中,我们提到,阈值分割需要设定一个数值,像素值高于此值的像素点变为白色,低于此值则变为黑色。这个数值就称为阈值。但这种方法不适用于色彩太鲜艳的图片。

通过设定单个阈值,无法得到草莓

这时,我们可以分别设定 R、G、B 通道的像素值范围,在图像 Strawberry 中, 范围内的像素值会变白,不在范围内的会变黑

例如,我们设置 R 的范围是 100~255,G 是 0~20,B 是 0~20,这时,只有红色含量高,蓝色绿色含量低的部分才会变白,其他部分都会变黑了,草莓也就隐约可见啦。贡献代码君:

Strawberry=cv2.imread("strawberry.jpg")
Lower = np.array([0, 0, 100])
Upper = np.array([40, 40, 255])
Binary = cv2.inRange(Strawberry, Lower, Upper)
cv2.imshow("strawberry", Binary)
cv2.waitKey(0)


此方法得到的草莓

不过,这种方式的效果也难令人满意,可以看到上图中的草莓,较暗和较亮的部分并没有被判定为红色部分。

因为在比较暗的地方,整张图的 RGB 的数值都很低,在比较亮的地方,数值又比较高。 RGB 三个通道的数值都很容易随着光照的改变而改变,无法在复杂的环境中得到自己需要的特定区域。

明暗不同的画面

所以在明暗变化比较大的地方,我们有一些更加适用于图像处理的颜色空间——HSV 和 YUV。在介绍 HSV 和 YUV 色彩空间之前,我们先说如何转换色彩空间。


色彩空间的转换

当我们需要使用其他的色彩空间时,一般通过 RGB 色彩空间转换得到。

RGB 转换成 HSV 的转换公式为:

从 RGB 到 HSV 转化公式(如果得到的 H<0,那么 H=H1+360)

RGB 转换成 YUV 的转换公式为:

转换公式表示转换的原理,实际使用中,我们直接用 OpenCV 视觉库里的 cvtCOLOR()函数来做转换:

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );

其中第一个参数是 输入图像 ,第二个参数是 输出图像 ,第三个参数是 转化的标识 (即从什么颜色空间转换到什么颜色空间),第四个参数是输出图片的 维度 (包含多少通道)。一般我们不用给出维度,默认参数为 0 时,维度是由输入图像和转换的标识决定的,比如从 RGB 转换成灰度图,则输出的图像的维度是 3。

下面以葡萄的图片为例。

原图

我们将 src 作为输入图像,dst 作为输出图像,并将原先 RGB 通道的图转换成 HSV 通道的图,则函数为:

cvtColor(src, dst, COLOR_BGR2HSV)

HSV 通道

dst 就是 src 转化而来的 HSV 通道的图像了,由于我们的显示器通常是符合 RGB 色彩空间的,所以 HSV 的图像在显示屏中会比较奇怪。

当图像的色彩信息对于后期工作没有太大作用的时候,为了处理更加方便,我们也可以使用 cvtColor()函数把图像 转换成单通道的灰度图 ,只要把转换的标识设为 COLOR_BGR2GRAY 即可。

单通道


HSV 色彩空间

在 HSV 色彩空间中 H,S,V 这三个通道分别代表着 色相(Hue),饱和度(Saturation) 明度(Value)


色相(Hue)
饱和度(Saturation)
明度(Value)

HSV 格式: H 代表色彩,S 代表颜色的深浅,V 代表着颜色的明暗程度

HSV 颜色空间可以很好地把颜色信息和亮度信息分开,将它们放在不同的通道中,减小了光线对于特定颜色识别的影响。

在 OpenCV 视觉库中,HSV 的数值被做了一些小的修改, H 的范围调整为 0~180,S 和 V 的范围为 0~255。

HSV 数值修改公式

当我们采用 HSV 的图像阈值得到某一种颜色时,可以参考颜色分布表,先将 H 通道对应的颜色找到。表格中,每种颜色都对应了一个区间。

HSV 各颜色分布区间

假如我们要提取图片的蓝色部分,我们就在 H 通道取 100~124,S 通道取 43~255,V 通道取 35~255,范围内的像素值变白,其余的变黑,就可以得到很好的结果。

即使明度取值 255 也不会变为全白,因为这时,这个取值是指蓝色的亮度,而不是像 RGB 一样表示颜色。饱和度同理。

以这张苹果的图片为例,取名为 Apple。

原图

当我们想得到图中苹果的红色部分时,通过以下的 python 代码,就可以轻松得到:

HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  #RGB 转为 HSV
H, S, V = cv2.split(HSV)    #分离 HSV 三通道
Lowerred0 = np.array([155,43,35])
Upperred0 = np.array([180,255,255])
mask1 = cv2.inRange(HSV, Lowerred0, Upperred0) 
Lowerred1 = np.array([0,43,35])
Upperred1 = np.array([11,255,255])
mask2 = cv2.inRange(HSV, Lowerred1, Upperred1)    #将红色区域部分归为全白,其他区域归为全黑
Apple = mask1 +mask2
cv2.imshow("apple", Apple)
cv2.waitKey(0)

下图为通过 HSV 三通道阈值出来的图像 Apple。

处理后


YUV 色彩空间

YUV 色彩空间实际上是把一幅彩色的图片分成了一个表示暗亮程度的 亮度信号(Luminance)Y ,和两个表示颜色的 色度信号(Chrominance)U 和 V

U,V 通道分别是 蓝色通道 红色通道 Y 通道表示 亮度信息

YUV 色彩空间

U 通道数值越高,颜色就越接近蓝色,V 通道数值越高,颜色就越接近红色,Y 通道数值越高,图片则越亮。

这种颜色通道其实是被欧洲的电视系统采用的一种颜色编码方式,主要是为了让信号支持新的彩色电视,但也继续支持黑白电视。如果是黑白电视,只使用 Y 通道信号就够了。

不同亮度的草莓和对应的 V 通道

即使是光线发生了很大的改变,V 通道还是能很好的体现出红色来。所以当我们要识别红蓝色物体时,使用 YUV 通道就会有较好的效果。

下面我们以莓果的图片为例。

红蓝色的莓果

如果想要提取树莓和蓝莓,我们就分别单独取 V、U 通道数值比较高的部分。献上代码君:

fruit = cv2.imread("fruits.jpg")
fruit = cv2.cvtColor(fruit,cv2.COLOR_BGR2YUV)