cv2.cvtColor() 函数是 OpenCV 中用于图像颜色空间转换的函数。它允许你将图像从一个色彩空间转换为另一个色彩空间。在 Python 中,你可以使用这个函数来实现不同色彩空间之间的转换。
函数的基本语法为:
cv2.cvtColor(src, code[, dst[, dstCn]])
参数说明:
src:输入图像,可以是 NumPy 数组或 OpenCV 中的 Mat 对象。
code:颜色空间转换代码,表示目标色彩空间。可以使用 OpenCV 中的 cv2.COLOR_* 常量来指定,如 cv2.COLOR_BGR2GRAY 表示将 BGR 彩色图像转换为灰度图像。
dst:可选参数,输出图像,可以是 NumPy 数组或 Mat 对象。如果未提供,将会创建一个新的图像来保存转换后的结果。
dstCn:可选参数,目标图像的通道数。默认值为 0,表示与输入图像通道数保持一致。
枚举值表:
这里需要注意,BGR 色彩空间与传统的 RGB 色彩空间不同。对于一个标准的 24 位位图,
BGR 色彩空间中第 1 个 8 位(第 1 个字节)存储的是蓝色组成信息(Blue component),第 2
个 8 位(第 2 个字节)存储的是绿色组成信息(Green component),第 3 个 8 位(第 3 个字节)
存储的是红色组成信息(Red component)。同样,其第 4 个、第 5 个、第 6 个字节分别存储蓝色、绿色、红色组成信息,以此类推。
颜色空间的转换都用到了如下约定:
8 位图像值的范围是[0,255]。
16 位图像值的范围是[0,65 535]。
浮点数图像值的范围是[0.0~1.0]。
对于线性转换来说,这些取值范围是无关紧要的。但是对于非线性转换来说,输入的 RGB图像必须归一化到其对应的取值范围内,才能获取正确的转换结果。
例如,对于 8 位图,其能够表示的灰度级有 28=256 个,也就是说,在 8 位图中,最多能表示 256 个状态,通常是[0,255]之间的值。但是,在很多色彩空间中,值的范围并不恰好在[0,255]
范围内,这时,就需要将该值映射到[0,255]内。
例如,在 HSV 或 HLS 色彩空间中,色调值通常在[0,360)范围内,在 8 位图中转换到上述色彩空间后,色调值要除以 2,让其值范围变为[0,180),以满足存储范围,即让值的分布位于8 位图能够表示的范围[0,255]内。
又例如,在 CIELab*色彩空间中,a 通道和 b 通道的值范围
是[−127,127],为了使其适应[0,255]的范围,每个值都要加上 127。
不过需要注意,由于计算过程存在四舍五入,所以转换过程并不是精准可逆的。
下面使用像素数组来观察转换效果
import cv2
import numpy as np
img=np.random.randint(0,256,size=[2,4,3],dtype=np.uint8)
rst=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print("img=\n",img)
print("rst=\n",rst)
print(img[1,0,0],img[1,0,1],img[1,0,2])
print("像素点(1,0)直接计算得到的值=",img[1,0,0]*0.114+img[1,0,1]*0.587+img[1,0,2]*0.299)
print("像素点(1,0)使用公式 cv2.cvtColor()转换值=",rst[1,0])
结果如下:
img=
[[[ 25 17 215]
[157 31 16]
[ 62 30 87]
[ 95 210 182]]
[[115 165 251]
[116 21 65]
[116 55 246]
[150 78 61]]]
rst=
[[ 77 41 51 189]
[185 45 119 81]]
115
165
251
像素点(1,0)直接计算得到的值= 185.01399999999998
像素点(1,0)使用公式 cv2.cvtColor()转换值= 185
像素点(1,0)直接计算得到的值= 185.01399999999998
像素点(1,0)使用公式 cv2.cvtColor()转换值= 185
OpenCV 中,灰度图像是按照行列直接存储的。而 BGR 模式的图像会依次将它的 B 通道、G 通道、R 通道中的像素点,以行为单位按照顺序存储在 ndarray 的列中。例如,有大小
为 R 行×C 列的 BGR 图像,其存储方式如图 4-2 所示。
当图像由 RGB 色彩空间转换到 GRAY 色彩空间时,其处理方式如下:
Gray = 0.299 · 𝑅 + 0.587 · 𝐺 + 0.114 · B
在本例中,各个像素点的像素值如下:
原始图像 BGR 图像内第 1 行第 0 列上的 B 通道像素点的值为 img[1,0,0]=115。
原始图像 BGR 图像内第 1 行第 0 列上的 G 通道像素点的值为 img[1,0,1]=165。
原始图像 BGR 图像内第 1 行第 0 列上的 R 通道像素点的值为 img[1,0,2]=251
计算结果为 185.0139。目标图像是灰度图像,是 8 位图像,值是位于[0,255]之间的无符号整数。所以,要将上述小数结果进行四舍五入,得到 185,并将它作为目标灰度图像内 rst[1,0]的像素值。