st
当前位置:首页 > 近期新闻 >用色彩空间做图像处理,让颜色提取更高效

用色彩空间做图像处理,让颜色提取更高效

电科RoboMaster2022-01-15 12:14:28


转载自Robomaster


现在,有一些机器人可以快速识别出物体的颜色,然后作出判断和操作,比如玩魔方机器人、彩色物块分拣机器人、水果采摘机器人......这类机器人会根据物体的颜色进行识别,最终作出准确的判断。



彩色物块分拣机器人


如果我们想让机器人在一堆彩虹糖里捡出红色的糖果,就需要让机器人对彩虹糖的图像进行分割,割出红色的部分,再伸手把它捡出来


分拣机器人


但是机器人并不像人类一样可以看到颜色,它们只能用数字交流,在之前有关图像二值化的文章中,我们说过,彩色图片一般是由一个三维数组表示的。


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


三通道彩色


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

 

单通道灰度


那机器人如何找到自己想要的颜色,图像中每个像素点的数值又是如何表示出颜色的呢?


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


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


RGB 色彩空间

 

橙色的萝卜君其实由三个萝卜一起构成的——一个“红萝卜”,一个“绿箩卜”,一个“蓝萝卜”。他们的颜色深浅就决定了萝卜君有多红、有多绿、有多蓝,然后叠加在一起,最后,我们看到了一个橙色的萝卜君。这就常见的 RGB 色彩空间的工作方式。



RGB 色彩空间



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


RGB 色彩空间


在 RGB 格式里(0,0,0)代表着黑色,(255,255,255)代表着白色。R 通道数值越高,说明颜色中含有的红色分量越多;G 通道数值越高,说明颜色中含有的绿色分量越多;B 通道数值越高,说明颜色中含有的蓝色分量越多。


通常,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 的转换公式为:


Figure 1 从 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 格式是 RGB 的一种变形。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 和 VU,V通道分别是蓝色通道红色通道Y 通道表示亮度信息


YUV 色彩空间


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


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


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


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


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


红蓝色的莓果


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


fruit = cv2.imread("fruits.jpg")

fruit = cv2.cvtColor(fruit,cv2.COLOR_BGR2YUV)

Y,U,V = cv2.split(fruit)

Blueberry = cv2.inRange(U,130,255)

Strawberry = cv2.inRange(V,170,255)

cv2.imshow("blueberry",Blueberry)

cv2.imshow("strawberry",Strawberry)

cv2.waitKey(0)


V 通道提取红色

 

U 通道提取蓝色


YUV 的计算相对简单,图像处理的速度很快,而且 YUV 格式对于红、蓝色都有很好的识别效果,即使光线变化,算法也可以比较稳定。所以户外的水果采摘机器人,一般都采用了该色彩空间来识别红蓝果实。


有时,你可能会看到 YCbCrYPbPr 等类似的名词,其实它们都可以被称为 YUV,区别只是适用于不同的显示设备。在计算机上适用的一种 YUV 类型是 YCbCr,同样 Cb 指蓝色色度,Cr 指红色色度


YCbCr 颜色空间



其他色彩空间



除了上面三种,还有其他的色彩空间,比如 CMYK 色彩空间,LAB 色彩空间等。



CMYK 色彩空间



CMYK 色彩空间中,C(cyan)代表青色,M(magenta)代表洋红色,Y(yellow)代表黄色,K(black)代表黑色


CMYK 色彩空间


CMYK 主要使用在印刷方面,比如喷墨打印机一般都是使用这四种颜色的墨盒。在 RGB 色彩空间里红色,绿色和蓝色叠加起来的时候是白色,但在 CMYK 色彩空间中,青色,洋红色,黄色叠加起来是黑色。


但是实际情况中,颜色叠加起来会是褐色,所以还是会加上单独的黑色。相比于 RGB,CMYK 更加实用于在白色的介质上打印图像。



LAB 色彩空间



LAB 色彩空间是由 CIE(国际照明委员会)制定的一种色彩模式。自然界中任何一点色都可以在 LAB 空间中表达出来,这种模式是以数字化方式来描述人的视觉感应。


LAB 色彩空间


在 LAB 色彩空间中,L 通道范围是 0~100,表示亮度A 通道的范围是 -128~+127,表示从绿色到洋红B 通道的范围是 -128~+127,表示从蓝色到黄色


A,B 通道都是负值表示冷色,正值表示暖色,而对于表示亮度的 L 来说,L=100 时为白色,L=0 时为黑色。


◆◆◆


综上,当图像处于复杂的环境时,我们可以先观察图片的颜色,如果色彩比较单一,我们可以优先考虑灰度图(比如二维码),这样处理更简单速度更快。


如果要识别特定的颜色的目标(比如水果)时,我们应该优先选用 HSV,YUV 等色彩空间,因为它们将图像的颜色与亮度分离开来,在一定程度上避免了不同强度的光照对于颜色数值的影响。


若想学习更多,可阅读书籍:

《数字图像处理》;作者: [美]冈萨雷斯;出版社: 电子工业出版社