4.3 类型转换实例
本节介绍几种常用的色彩空间转换实例,以帮助大家更好地理解应该如何使用函数cv2.cvtColor()。
4.3.1 通过数组观察转换效果
本节通过使用函数cv2.cvtColor()的实例来观察它的色彩空间转换功能。为了方便观察,本节通过一个小尺寸的数组来模拟图像,作为cv2.cvtColor()函数要处理的对象。
【例4.1】将BGR图像转换为灰度图像。
根据题目要求,设计程序如下:
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("像素点(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])
在本例中,通过函数cv2.cvtColor()对图像img进行色彩空间的转换,并使用公式计算的方式对其中的像素点进行计算。最后,分别打印该点的函数转换结果和公式计算结果。
运行程序,结果如下所示:
img= [[[166 97102] [ 73 31 51] [221 94158] [143101172]] [[ 96140 92] [ 19156 34] [ 16113202] [116236238]]] rst= [[106 42128127] [121104129223]] 像素点(1,0)直接计算得到的值= 120.63199999999999 像素点(1,0)使用公式cv2.cvtColor()转换值= 121
在OpenCV中,灰度图像是按照行列直接存储的。而BGR模式的图像会依次将它的B通道、G通道、R通道中的像素点,以行为单位按照顺序存储在ndarray的列中。例如,有大小为R行×C列的BGR图像,其存储方式如图4-2所示。
图4-2 BGR图像的存储方式
当图像由RGB色彩空间转换到GRAY色彩空间时,其处理方式如下:
Gray=0.299·R+0.587·G+0.114·B
这里以rst[1,0]为例,看看它是如何通过计算得到的。像素rst[1,0]表示目标灰度图像内的第1行第0列上的像素点。它需要通过对原始图像BGR图像内第1行第0列上的B通道像素点、G通道像素点、R通道像素点的计算得到。
在本例中,各个像素点的像素值如下:
● 原始图像BGR图像内第1行第0列上的B通道像素点的值为img[1,0,0]=96。
● 原始图像BGR图像内第1行第0列上的G通道像素点的值为img[1,0,1]=140。
● 原始图像BGR图像内第1行第0列上的R通道像素点的值为img[1,0,2]=92。
转换为灰度像素点时,使用的公式为:
img[1,0,0]×0.114+img[1,0,1]×0.587+img[1,0,2]×0.299=96×0.114+140×0.587+92×0.299=120.632
计算结果为120.632。目标图像是灰度图像,是8位图像,值是位于[0,255]之间的无符号整数。所以,要将上述小数结果进行四舍五入,得到121,并将它作为目标灰度图像内rst[1,0]的像素值。
当然,在一般情况下,我们并不需要关心这么细节的问题,只要能够熟练地使用函数cv2.cvtColor()就可以了。
【例4.2】将灰度图像转换为BGR图像。
根据题目要求,设计程序如下:
import cv2 import numpy as np img=np.random.randint(0,256, size=[2,4], dtype=np.uint8) rst=cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) print("img=\n", img) print("rst=\n", rst)
运行程序,结果如下所示:
img= [[ 58254137123] [100150 7 42]] rst= [[[ 58 58 58] [254254254] [137137137] [123123123]] [[100100100] [150150150] [ 7 7 7] [ 42 42 42]]]
上述程序进一步印证了,当图像由GRAY色彩空间转换到RGB/BGR色彩空间时,最终所有通道的值都是相同的。其处理方式如下:
R=Gray
G=Gray
B=Gray
同时,以上例题也进一步印证了BGR图像在OpenCV内的像素点的存储方式。
【例4.3】将图像在BGR和RGB模式之间相互转换。
根据题目要求,设计程序如下:
import cv2 import numpy as np img=np.random.randint(0,256, size=[2,4,3], dtype=np.uint8) rgb=cv2.cvtColor(img, cv2.COLOR_BGR2RGB) bgr=cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR) print("img=\n", img) print("rgb=\n", rgb) print("bgr=\n", bgr)
运行程序,结果如下所示:
img= [[[ 12173157] [216 2220] [ 49145157] [124203 44]] [[140196171] [ 90195187] [158199113] [213 78164]]] rgb= [[[157173 12] [220 2216] [157145 49] [ 44203124]] [[171196140] [187195 90] [113199158] [164 78213]]] bgr= [[[ 12173157] [216 2220] [ 49145157] [124203 44]] [[140196171] [ 90195187] [158199113] [213 78164]]]
从程序可以看到,在RGB和BGR模式之间相互转换时,R通道和B通道的位置发生了交换。
4.3.2 图像处理实例
本节将通过具体实例介绍如何使用函数cv2.cvtcolor()来处理图像类型的转换。
【例4.4】将图像在BGR模式和灰度图像之间相互转换。
根据题目要求,设计程序如下:
import cv2 lena=cv2.imread("lenacolor.png") gray=cv2.cvtColor(lena, cv2.COLOR_BGR2GRAY) rgb=cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) #==========打印shape============ print("lena.shape=", lena.shape) print("gray.shape=", gray.shape) print("rgb.shape=", rgb.shape) #==========显示效果============ cv2.imshow("lena", lena) cv2.imshow("gray", gray) cv2.imshow("rgb", rgb) cv2.waitKey() cv2.destroyAllWindows()
运行程序,会显示各个图像的shape属性:
lena.shape= (512, 512, 3) gray.shape= (512, 512) rgb.shape= (512, 512, 3)
通过其shape属性,可以看到图像在转换前后的色彩空间变化情况。
同时,程序会分别显示原始彩色图像、灰度图像、RGB图像。需要注意,在通过“rgb=cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)”得到的RGB图像中,B通道、G通道、R通道的值都是一样的,所以其看起来仍是灰度图像。由于本书是黑白(灰度)印刷,无法观察彩色效果,所以,这里省略了运行结果中图像的展示。请大家在Python内运行上述程序,观察实际效果。
【例4.5】将图像从BGR模式转换为RGB模式。
根据题目要求,设计程序如下:
import cv2 lena=cv2.imread("lenacolor.png") rgb = cv2.cvtColor(lena, cv2.COLOR_BGR2RGB) cv2.imshow("lena", lena) cv2.imshow("rgb", rgb) cv2.waitKey() cv2.destroyAllWindows()
运行程序,会显示如图4-3所示的运行结果。
图4-3 【例4.5】程序的运行结果
在图4-3中,左图是BGR通道顺序的图像,右图是RGB通道顺序的图像。可以看到,读取的lena图像在BGR模式下正常显示,将其调整为RGB通道顺序后,显示的图像呈现浅蓝色。由于本书为黑白印刷,所以为了更好地观察运行效果,请大家亲自上机运行程序。