五 色彩空间转换
背景
颜色空间:用三种或者更多的特征来指定颜色的方法,被称为颜色空间或者颜色模型
1、RGB(opencv中为BGR)
一幅图像由三个独立的图像平面或者通道构成:红、蓝、绿(以及可选项:透明度alpha通道) 每个值代表每个像素的每个分量的度量值,值越高对应于更亮的像素 对应于人眼的三种光锥细胞,所以被广泛使用
RGB色彩空间源于使用阴极射线管的彩色电视,
RGB分别代表三个基色(R-红色、G-绿色、B-蓝色),具体的色彩值由三个基色叠加而成。
在图像处理中,我们往往使用向量表示色彩的值,如(0,0,0)表示黑色、(255, 255, 255)表示白色。
其中,255表示色彩空间被量化成255个数,最高亮度值为255(255 = 2^8 - 1,即每个色彩通道用8位表示)。
在这个色彩空间中,有256*256*256种颜色。RGB色彩空间如下图所示(图片来自百度百科)。是一个包含Red、Green、Blue的三维空间。
2、HSV
HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、明度(Value),又称HSB(B即Brightness)。色相是色彩的基本属性,就是平常说的颜色的名称,如红色、黄色等。饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。明度(V),取0-max(计算机中HSV取值范围和存储的长度有关)。HSV颜色空间可以用一个圆锥空间模型来描述。圆锥的顶点处,V=0,H和S无定义,代表黑色。圆锥的顶面中心处V=max,S=0,H无定义,代表白色。
H是色彩
S是深浅, S = 0时,只有灰度
V是明暗,表示色彩的明亮程度,但与光强无直接联系,(意思是有一点点联系吧)。
H:0-180 S: 0-255 V: 0-255 -> opencv中
H:0-360,在OpenCV中被规范为0-180,若是360超出255溢出,所有规划到180,,8位可以保存,是HSV3位保存一致,都是只占一个字节
S和V:在OpenCV中规范化为0-255(一个字节就可以表示)
HSV颜色空间输入面向色度的颜色坐标系统的一种。这种类型的颜色模型接近人类颜色感知的仿真模型。 HSV的三个通道表示色度(H给出的颜色光谱构成的一种度量),饱和度(S给出主波长中的纯光比例,这表明一种颜色距离相同亮度灰度的程度)和纯度(V给出相对于白色光照强度的亮度),对应于直觉上的色彩、明暗和色调。HSV广泛应用于色彩的比较。
OpenCV中的imshow()函数假设图像的颜色以RGB显示,因此其他显示均不正确。所以首先必须将其转换成RGB颜色空间
3、HLS
HLS属于面向色度的颜色坐标系统中的一种,和之前的HSV类似 用来指定每个通道中的一种颜色的色度值、明暗值、饱和度值 与HSV不同的是HSL定义的一种纯颜色的亮度等于一种中等灰色的亮度 而HSV定义的一种纯颜色的亮度等于白色的亮度
4、YCrCb
该空间广泛用于视频和图像压缩,不能算作纯粹的色彩空间,它是RGB颜色空间的一种解码方式 Y通道表示亮度,而Cr和Cb表示红色差值(在RGB空间中R通道和Y的差值)和蓝色差值(在RGB空间中B通道和Y的差值)各自的色度分量。
5、灰度图
每个像素值只表示灰度信息这一单一信息 RGB[A]准换成灰度:Y=0.299*R+0.587*G+0.114*B 灰度转换为RGB[A]:R=Y,G=Y,B=Y,A=max(ChannelRange)
6、YUV
1、YUV(亦称YCrCb)是被欧洲电视系统所采用的一种颜色编码方法。在现代彩色电视系统中,通常采用三管彩色摄像机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号R-Y(即U)、B-Y(即V),最后发送端将亮度和两个色差总共三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。如果只有Y信号分量而没有U、V信号分量,那么这样表示的图像就是黑白灰度图像。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。
2、YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用Cr和Cb来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之同的差异。
Y = 0.299R + 0.587G + 0.114B U = -0.147R - 0.289G + 0.436B V = 0.615R - 0.515G - 0.100B R = Y + 1.14V G = Y - 0.39U - 0.58V B = Y + 2.03U
一、调用转换函数实现图像色彩空间转换
# -*- coding=GBK -*- import cv2 as cv #色彩空间的转换 def color_space_demo(image): gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)#RGB转换为gray cv.imshow("gray", gray) hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)#RGB转换为hsv cv.imshow("hsv", hsv) yuv = cv.cvtColor(image, cv.COLOR_BGR2YUV)#RGB转换为yuv cv.imshow("yuv", yuv) src = cv.imread("C://1.jpg") cv.namedWindow("原来", cv.WINDOW_NORMAL) cv.imshow("原来", src) color_space_demo(src) cv.waitKey(0) cv.destroyAllWindows()
说明:
cvCvtColor( const CvArr* src, CvArr* dst, int code )
src:源图像(输入的 8-bit , 16-bit 或 32-bit 单倍精度浮点数影像)
dst:目标图像(输入的 8-bit , 16-bit 或 32-bit 单倍精度浮点数影像)
code:
需要特别说明的是RGB–>GRAY的转换是我们常用的转换格式,其转换公式如下:
二、色彩空间转换,利用inrange函数过滤视频中的颜色,实现跟踪某一颜色
HSV追踪有颜色的对象(捕获视频中的红色)
import cv2 as cv import numpy as np def extrace_object(): capture = cv.VideoCapture("./1.mp4") while True: #打开摄像头 ret,frame = capture.read() #frame是每一帧图像,ret是返回值,为0是表示图像读取完毕 if ret == False: break #转换为hsv图像 hsv = cv.cvtColor(frame,cv.COLOR_BGR2HSV) #下阈值 lower_hsv = np.array([0,43,46]) #上阈值 upper_hsv = np.array([10,255,255]) mask = cv.inRange(hsv,lower_hsv,upper_hsv) #mask输出图像 cv.inRange(src,lower,upper,dst=None) #cv.inRange(目标图像,下阈值,上阈值) cv.imshow("video",frame) cv.imshow("mask", mask) c = cv.waitKey(40) if c == 27: #相当于人为退出 break extrace_object(src)
说明:
cv.inRange(image,lower,upper)
对图像的所有通道同时做阈值范围限制,在三个通道阈值范围内的像素值设为二值化中的高值,比如255,不在通道阈值范围内的像素值设为二值化中的低值,比如0,最后输出的图像是单通道图像。
注意,它的参数形成的区间是闭区间,而不是开区间。
if c == 27: break #也可以改为 if cv.waitKey(50) & 0xFF == ord('q'): break
三、通道分离、修改、合并
1、通道分离
src = cv.imread("./6.jpg") #读取图片 cv.namedWindow("RGB",cv.WINDOW_AUTOSIZE) #创建GUI窗口,形式为自适应 cv.imshow("RGB",src) #通过名字将图像和窗口联系 b,g,r = cv.split(src) #通道分离为b,g,r三个 cv.imshow("B",b) cv.imshow("G",g) cv.imshow("R",r) cv.waitKey(0) cv.destroyAllWindows()
2、修改某一通道
1 src = cv.imread('1.jpg') 2 src[:,:,0] = 0 #b变为黑 3 cv.imshow('change b',src) 4 src[:,:,1] = 0 #G变为黑 5 cv.imshow('chage G',src) 6 src[:,:,2] = 0 #r变为黑 7 cv.imshow('chage r',src) 8 cv.waitKey(0) 9 cv.destroyAllWindows()
3、合并通道
src2 = cv.merge([b,g,r]) cv.imshow("meger image",src2)