OpenCV python(三)【图像预处理:颜色空间转换】 && 颜色识别

一、颜色空间和色域的区别

关于这两个名词,在我最初开始学习的一段时间里常常将他们混淆,以下是我目前对颜色空间和色域的个人理解。
颜色空间是指用数字来表示颜色,色域则代表的是一种颜色空间的范围。因此色域转换其实表示的是对颜色空间的子集的一种改变,也就是在像素值范围上的增缩,而颜色空间转换则表示的是更换此颜色模型,不仅改变了范围,也改变了各个数字或数组所代表的颜色,甚至改变了维度,即改变图像的深度。

二、颜色空间

以下介绍的颜色空间为我个人目前常需要用到的颜色空间。

1、GRAY颜色空间

GRAY颜色空间也就是我们平常所说的灰度图,通常为8位灰度图,也就是0~255的范围,像素值越低,灰度值越深,就越接近黑色,反之则接近白色,当达到边界值时,也就是像素值为0时,该像素点为纯黑色,像素值为255时,该像素点为纯白色
使用该颜色空间,可极大地降低运算量,同时也便于后续图像处理操作,如将RGB图像二值化等需要一维图像的图像处理操作,即可先将RGB图像转换为GRAY图像,再进行二值化操作

2、RGB颜色空间

一般情况下,我们通过摄像头或是其他硬件设备获取到的图像都是RGB图像。
RGB图像由 红(R)、绿(G)、蓝(B) 三个颜色通道组成,每个通道都有一个字节的大小,即范围为0~255,即一个通过有256个像素值,那么对应3个通道,可代表的颜色种类可达到256×256×256种,即16777216种颜色,RGB颜色空间几乎包括了人类视力所能感知的所有颜色,因此也是目前运用最广的颜色空间之一。
由上述可知,RGB颜色空间每个像素点都有3个像素值,即1个像素点由3个像素值组成的数组来表示。对应R、G、B三个通道,即Red、Green、Blue,当像素点RGB值为(255, 0, 0)时,该点为红色,当RGB值为(0, 255, 0)时,该点为绿色,当RGB值为(0, 0, 255)时,该点为蓝色。且 (0, 0, 0)表示的是黑色,(255, 255, 255)表示的是白色。由此可知RGB颜色空间是由没一个通道的像素值通过叠加的方式,从灰度的层次通过3层叠加得到不同的颜色。
除此之外,(255, 255, 0)表示的是黄色,(0, 255, 255)表示的是青色

3、HSV颜色空间

如上所述,RGB颜色空间的颜色种类、范围很复杂,不够明显。而HSV颜色空间则能在一定范围内划分颜色的区块。
HSV颜色空间由色调H、饱和度S、亮度V组成,H的范围为0 ~ 180,S的范围为0 ~ 255,V的范围为0 ~ 255,具体颜色区间如下表所示
在这里插入图片描述

三、颜色空间转换:cvtColor

1、获取RGB、GRAY、HSV图像

在第一篇文章 OpenCV python(一):安装 && 获取、显示、保存图像 中,有通过摄像头等硬件或是直接从视频、图片获取RGB图像的方法,这些方法在上述文章中都有详细的说明和程序讲解,这里就不再赘述了,主要列举如何获取GRAY和HSV颜色空间的图像。
其实GRAY图像的获取在前一篇文章中也有提及到,在imread方法中,可选择获取灰度类型图像,如下所示2种imread获取灰度图的方法。关于imread函数也可在上篇文章中查询。

cv2.imread('xx.jpg', 0)	# 0为灰度图
cv2.imread('xx.jpg', cv2.IMREAD_GRAYSCALE)	# 灰度图

当需要用到摄像头或是视频获取图像时,要使用imread就需要先保存再获取,非常麻烦和低效,此时想要获取灰度图或是HSV图像,则可使用opencv-python提供的cvtColor函数。

获取灰度图:img_g = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
获取HSV图:img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
'''
img 为获取到的RGB图像,此处则将RGB转换为GRAY和HSV
cv2.COLOR_BGR2GRAY为 BGR to GRAY
cv2.COLOR_BGR2HSV为 BGR to HSV
BGR也是RGB颜色空间,只是顺序调换了,前面输入的img为RGB颜色空间即可。
'''

2、获取RGB、GRAY、HSV图像案例

(1)、摄像头获取图像再转换

程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    video = cv2.VideoCapture(0)  # 选择摄像头0、1... 或 选择视频路径
    while True:
        ret, img_RGB = video.read()
        # 获取摄像头或视频的一帧,ret判断获取是否成功,成功则为True;img为获取的图像
        if ret:
            img_GRAY = cv2.cvtColor(img_RGB, cv2.COLOR_BGR2GRAY)  # 获取GRAY图像
            img_HSV = cv2.cvtColor(img_RGB, cv2.COLOR_BGR2HSV)  # 获取HSV图像

            cv2.imshow("RGB", img_RGB)  # 显示RGB图像
            cv2.imshow("GRAY", img_GRAY)  # 显示GRAY图像
            cv2.imshow('HSV', img_HSV)  # 显示HSV图像

            cv2.waitKey(1)  # 等待时间
        else:
            # print("摄像头未打开。")
            pass  # 图像获取失败,可能未接入摄像头

(2)、导入图像直接转换&再转换

程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_RGB = cv2.imread('img/2.jpg', 1)    # 获取路径img/2.jpg的图像,图像类型为RGB图像
        img_GRAY = cv2.imread('img/2.jpg', 0)  # 获取路径img/2.jpg的图像,图像类型为GRAY图像
        img_HSV = cv2.cvtColor(img_RGB, cv2.COLOR_BGR2HSV)     # 获取HSV图像

        cv2.imshow("RGB", img_RGB)  # 显示RGB图像
        cv2.imshow("GRAY", img_GRAY)  # 显示GRAY图像
        cv2.imshow('HSV', img_HSV)  # 显示HSV图像

        cv2.waitKey(1)  # 等待时间

效果如下所示,获取到红包图像后将红包转换为金包,也就是将RGB图像转换为HSV图像:
在这里插入图片描述

3、GRAY、HSV图像转换回RGB图像

如上图所示,可以看到灰包和金包,即红包的GRAY图像和HSV图像。在上述程序的基础上,再将其分别转换为RGB图像,程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_RGB = cv2.imread('img/2.jpg', 1)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_GRAT = cv2.imread('img/2.jpg', 0)  # 获取路径img/0.jpg的图像,图像类型为GRAY图像
        img_HSV = cv2.cvtColor(img_RGB, cv2.COLOR_BGR2HSV)     # 获取HSV图像

        img_GRAT2RGB = cv2.cvtColor(img_GRAT, cv2.COLOR_GRAY2BGR)   # 将灰度图转换为RGB图
        img_HSV2RGB = cv2.cvtColor(img_HSV, cv2.COLOR_HSV2BGR)   # 将HSV图转换为RGB图

        cv2.imshow("RGB", img_RGB)  # 显示RGB图像
        cv2.imshow("GRAY2RGB", img_GRAT2RGB)  # 显示GRAY图像
        cv2.imshow('HSV2RGB', img_HSV2RGB)  # 显示HSV图像

        cv2.waitKey(1)  # 等待时间

效果如下所示,可以看到HSV再次转换回RGB图像时,图像原本的信息都没有被改变,原原本本地复原了;而GRAY图像再次转换回RGB图像时,图像却丢失了非常多的颜色信息,这是因为GRAY颜色空间的通道数为1,而RGB颜色空间和HSV颜色空间的通道数都为3,当3通道数转换为1通道数时,必然将丢失许多颜色信息,但与此同时,也将大幅减少后续的图像处理操作的运行时间
在这里插入图片描述

四、颜色识别:HSV+inRange

下文将讲述如何结合上述的颜色空间转换,进行颜色识别并二值化

1、inRange函数

inRange是opencv-python提供的基于HSV颜色空间的二值化函数,具体使用方法如下:

img_bin = cv2.inRange(img_hsv, lower, upper)	#低于lower、高于upper为0,中间为255

2、案例

程序如下所示:

import cv2  # 导入opencv库

if __name__ == '__main__':
    while True:
        img_RGB = cv2.imread('img/3.jpg', 1)    # 获取路径img/0.jpg的图像,图像类型为RGB图像
        img_HSV = cv2.cvtColor(img_RGB, cv2.COLOR_BGR2HSV)     # 获取HSV图像

        img_bin1 = cv2.inRange(img_HSV, (0, 43, 46), (10, 255, 255))  # 低于lower、高于upper为0,中间为255
        img_bin2 = cv2.inRange(img_HSV, (156, 43, 46), (180, 255, 255))  # 低于lower、高于upper为0,中间为255
        img_bin = cv2.add(img_bin1, img_bin2)      # 将两张图像相加,即汇总所有白色像素

        cv2.imshow("RGB", img_RGB)  # 显示RGB图像
        cv2.imshow('HSV', img_HSV)  # 显示HSV图像
        cv2.imshow('BIN1', img_bin1)    # 显示红色范围一的二值化图像
        cv2.imshow('BIN2', img_bin2)    # 显示红色范围二的二值化图像
        cv2.imshow('BIN', img_bin)  # 显示红色总范围的二值化图像

        cv2.waitKey(1)  # 等待时间

效果如下所示:
在这里插入图片描述
实现的功能为将图像中的红色区域二值化为白色像素,其余颜色二值化为黑色像素,再次定位时则为一维图像,可用遍历图像的方式找出红色区块。
此处将两个图像相加的操作,目的是为了让两范围的白色都汇总起来,即确保两个范围内的红色都被识别到,原因如下图所示,红色在HSV颜色空间中有两个范围。
二值化图像相加的规则很简单,在保证图像大小相等的情况下:0+255=255;255+0=255;0+0=0;255+255=255
1-3个加法式子都很好理解,第4个加法式子其实是因为opencv图像加法时自带的一个饱和操作,即当数字相加超过了255时,将其设置为255。
在这里插入图片描述
本人是一名学生,目前正在学习中,本篇文章也算是我的学习笔记,如有错误的话还请指正。

猜你喜欢

转载自blog.csdn.net/xztli/article/details/126155365