色彩空间类型转换:它是将图像从一个色彩空间转换到另外一个色彩空间,每个色彩空间都有自己擅长的处理问题的领域。
在RGB色彩空间中,图像通道的顺序是R→G→B,即第1个通道是R通道,第2个通道是G通道,第3个通道是B通道。注:在OpenCV中,通道顺序是B→G→R。
接下来我们考虑如何将3个通道进行拆分并单独显示其中一个通道的图像,这里给出两种拆分方式:
我们使用下列语句操作:
b = lena2[:, :, 0]
g = lena2[:, :, 1]
r = lena2[:, :, 2]
接下来我们看一段程序展示:
import cv2
lena2 = cv2.imread(r'C:\Users\Wxr\Desktop\lena3.jpg')
cv2.imshow("lena2", lena2)
b = lena2[:, :, 0]
g = lena2[:, :, 1]
r = lena2[:, :, 2]
cv2.imshow("b", b)
cv2.imshow("g", g)
cv2.imshow("r", r)
cv2.waitKey()
本程序实现了通道的拆分与各通道的分别展示。
我们使用函数b, g, r = cv2.split()
拆分通道。
接下来我们看一段程序展示:
import cv2
lena3 = cv2.imread(r'C:\Users\Wxr\Desktop\lena3.jpg')
cv2.imshow("lena3", lena3)
b, g, r = cv2.split(lena3)
cv2.imshow("b", b)
cv2.imshow("g", g)
cv2.imshow("r", r)
cv2.waitKey()
运行结果如下:
可以看出不论是通过索引方式还是函数拆分得到的通道图像,结果都是一样的。
通道合并是通道拆分的逆过程,我们使用函数cv2.merge()
实现通道合并。
下面看一段程序展示:
import cv2
lena3 = cv2.imread(r'C:\Users\Wxr\Desktop\lena3.jpg')
cv2.imshow("lena3", lena3)
b, g, r = cv2.split(lena3)
bgr = cv2.merge([b, g, r])
rgb = cv2.merge([r, g, b])
cv2.imshow("bgr", bgr)
cv2.imshow("rgb", rgb)
cv2.waitKey()
程序运行结果如下:
可以看出,按照B、G、R顺位排列出的图像与原图是一致的,也就验证了OpenCV的通道顺序是B→G→R。
GRAY指的是8位灰度图,有256各灰度级,像素值范围:[0,255]
标准转换公式:
G r a y = 0.299 ⋅ R + 0.587 ⋅ G + 0.114 ⋅ B Gray=0.299\cdot R+0.587\cdot G+0.114\cdot B Gray=0.299⋅R+0.587⋅G+0.114⋅B
简化转换公式:
G r a y = R + G + B 3 Gray= \frac{R+G+B}{3} Gray=3R+G+B
转化公式:
R = G = B = G R A Y R=G=B=GRAY R=G=B=GRAY
XYZ色彩空间是国际照明委员会(CIE)在进行了大量正常人视觉测量和统计后建立的。
转换公式:
[ X Y Z ] = [ 0.412453 0.357580 0.180423 0.212671 0.715160 0.072169 0.019334 0.119193 0.950227 ] ⋅ [ R G B ] \begin{bmatrix} X \\ Y \\ Z \end{bmatrix}=\begin{bmatrix} 0.412453 & 0.357580 & 0.180423 \\ 0.212671 & 0.715160 & 0.072169 \\ 0.019334 & 0.119193 & 0.950227 \end{bmatrix}\cdot \begin{bmatrix} R \\ G \\ B \end{bmatrix} ⎣⎡XYZ⎦⎤=⎣⎡0.4124530.2126710.0193340.3575800.7151600.1191930.1804230.0721690.950227⎦⎤⋅⎣⎡RGB⎦⎤
转换公式:
[ R G B ] = [ 3.240479 − 1.53715 − 0.498535 − 0.969256 1.875991 0.041556 0.055648 − 0.204043 1.057311 ] ⋅ [ X Y Z ] \begin{bmatrix} R \\ G \\ B \end{bmatrix}=\begin{bmatrix} 3.240479 & -1.53715 & -0.498535 \\ -0.969256 & 1.875991 & 0.041556 \\ 0.055648 & -0.204043 & 1.057311 \end{bmatrix}\cdot \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} ⎣⎡RGB⎦⎤=⎣⎡3.240479−0.9692560.055648−1.537151.875991−0.204043−0.4985350.0415561.057311⎦⎤⋅⎣⎡XYZ⎦⎤
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。HSV对用户来说是一种直观的颜色模型,这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。
HSV空间模型如下:
色调:色调与光谱中的主要光波长相关,色调用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°;
饱和度:饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
明度:明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
接下来我们介绍以下空间六棱锥:
H参数表示色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,红、绿、蓝分别相隔120度。互补色分别相差180度。范围从0到360。
纯度S为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S=0时,只有灰度。
V表示色彩的明亮程度,范围从0到1。有一点要注意:它和光强度之间并没有直接的联系。
转换前提:需要先将RGB色彩空间的值转换到[0,1](各通道的像素值除以255),再进行处理。
V = m a x ( R , G , B ) V=max(R,G,B) V=max(R,G,B)
S = { V − m i n ( R , G , B ) V V ≠ 0 0 e l s e S=\left\{ \begin{array}{rcl} \frac{V-min(R,G,B)}{V} & & {V\neq 0}\\ 0 & & {else} \end{array} \right. S={ VV−min(R,G,B)0V=0else
H = { 60 ( G − B ) V − m i n ( R , G , B ) V = R 120 + 60 ( B − R ) V − m i n ( R , G , B ) V = G 240 + 60 ( R − G ) V − m i n ( R , G , B ) V = B H=\left\{ \begin{array}{rcl} \frac{60(G-B)}{V-min(R,G,B)} & & {V=R}\\ 120+\frac{60(B-R)}{V-min(R,G,B)} & & {V=G}\\ 240+\frac{60(R-G)}{V-min(R,G,B)} & & {V=B} \end{array} \right. H=⎩⎪⎨⎪⎧V−min(R,G,B)60(G−B)120+V−min(R,G,B)60(B−R)240+V−min(R,G,B)60(R−G)V=RV=GV=B
注:计算过程中可能会出现H<0的情况,若发生,则需要对H进一步操作,过程如下:
H = { H + 360 H < 0 H e l s e H=\left\{ \begin{array}{rcl} H+360 & & {H<0}\\ H & & {else} \end{array} \right. H={ H+360HH<0else
YCrCb即YUV,主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。
在该空间里,Y代表明度,Cr表示红色分量信息,Cb表示蓝色分量信息。
应用:在人脸检测中也常常用到YCrCb空间,因为一般的图像都是基于RGB空间的,在RGB空间里人脸的肤色受亮度影响相当大,所以肤色点很难从非肤色点中分离出来,也就是说在此空间经过处理后,肤色点是离散的点,中间嵌有很多非肤色,这为肤色区域标定(人脸标定、眼睛等)带来了难题。如果把RGB转为YCrCb空间的话,可以忽略Y(亮度)的影响,因为该空间受亮度影响很小,肤色会产生很好的类聚。这样就把三维的空间降为二维的CrCb,肤色点会形成一定得形状,如:人脸的话会看到一个人脸的区域,手臂的话会看到一条手臂的形态,对处理模式识别很有好处,根据经验某点的CrCb值满足:133≤Cr≤173,77≤Cb≤127 那么该点被认为是肤色点,其他的就为非肤色点。
参考:百度百科-YCrCb
转换公式:
Y = 0.299 ⋅ B + 0.587 ⋅ G + 0.114 ⋅ B Y=0.299\cdot B+0.587\cdot G+0.114\cdot B Y=0.299⋅B+0.587⋅G+0.114⋅B
C r = ( R − Y ) × 0.713 + d e l t a Cr=(R-Y)\times 0.713+delta Cr=(R−Y)×0.713+delta
C b = ( B − Y ) × 0.564 + d e l t a Cb=(B-Y)\times 0.564+delta Cb=(B−Y)×0.564+delta
其中:
d e l t a = { 128 8 w e i i m a g e 32768 16 w e i i m a g e 0.5 S i n g l e p r e c i s i o n i m a g e delta=\left\{ \begin{array}{rcl} 128 & & {8wei\ image}\\ 32768 & & {16wei\ image}\\ 0.5 & & {Single\ precision\ image} \end{array} \right. delta=⎩⎨⎧128327680.58wei image16wei imageSingle precision image
R = Y + 1.403 ⋅ ( C r − d e l t a ) R=Y+1.403\cdot (Cr-delta) R=Y+1.403⋅(Cr−delta)
G = Y − 0.714 ⋅ ( C r − d e l t a ) − 0.344 ⋅ ( C b − d e l t a ) G=Y-0.714\cdot (Cr-delta)-0.344\cdot (Cb-delta) G=Y−0.714⋅(Cr−delta)−0.344⋅(Cb−delta)
B = Y + 1.773 ⋅ ( C b − d e l t a ) B=Y+1.773\cdot (Cb-delta) B=Y+1.773⋅(Cb−delta)
我们使用函数cv2.cvtColor()
实现色彩空间转换。
函数格式:dst = cv2.cvtColor(src, code [, dstCn])
各参数解释:
dst:输出图像,与输入图像有相同的数据类型和深度;
src:输入图像;
code:色彩空间转换值,详细见下图;
dstCn:目标图像通道数,若该参数为默认的0,则通道数自动通过输入图像和code得到。
枚举值参考:opencv入门:色彩空间类型转换
程序如下:
import cv2
lena2 = cv2.imread(r'C:\Users\Wxr\Desktop\lena2.jpg')
cv2.imshow("lena3", lena2)
gray = cv2.cvtColor(lena2, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
cv2.waitKey()
运行结果:
程序如下:
import cv2
lena2 = cv2.imread(r'C:\Users\Wxr\Desktop\lena2.jpg')
cv2.imshow("lena3", lena2)
hsv = cv2.cvtColor(lena2, cv2.COLOR_BGR2HSV)
cv2.imshow("hsv", hsv)
cv2.waitKey()
运行结果:
接下来我们把H、S、V三个通道拆分并查看各通道图像。
程序如下:
import cv2
lena3 = cv2.imread(r'C:\Users\Wxr\Desktop\lena3.jpg')
cv2.imshow("lena3", lena3)
hsv = cv2.cvtColor(lena3, cv2.COLOR_BGR2HSV)
cv2.imshow("hsv", hsv)
h, s, v = cv2.split(hsv)
cv2.imshow("h", h)
cv2.imshow("s", s)
cv2.imshow("v", v)
cv2.waitKey()
程序如下:
import cv2
lena2 = cv2.imread(r'C:\Users\Wxr\Desktop\lena2.jpg')
cv2.imshow("lena2", lena2)
yuv = cv2.cvtColor(lena2, cv2.COLOR_BGR2YUV)
cv2.imshow("yuv", yuv)
cv2.waitKey()
运行结果: