OpenCV轻松入门:面向Python
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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通道顺序后,显示的图像呈现浅蓝色。由于本书为黑白印刷,所以为了更好地观察运行效果,请大家亲自上机运行程序。