2.2.2 在图像和原始字节之间进行转换

从概念上讲,一个字节就是0~255范围内的一个整数。目前,在实时图形应用程序中,像素通常由每个通道一个字节来表示,但是也可以使用其他表示方式。

OpenCV图像是numpy.array类型的二维或者三维数组。8位灰度图像是包含字节值的一个二维数组。24位的BGR图像是一个三维数组,也包含字节值。我们可以通过使用类似于image[0,0]或者image[0,0,0]的表达式来访问这些值。第一个索引是像素的y坐标或者行,0表示顶部。第二个索引是像素的x坐标或者列,0表示最左边。第三个索引(如果有的话)表示一个颜色通道。可以用下面的笛卡儿坐标系可视化数组的三维空间(见图2-1)。

图2-1 基于笛卡儿坐标系的数组三维空间

例如,在左上角为白色像素的8位灰度图像中,image[0,0]是255。在左上角为蓝色像素的24位(每个通道8位)BGR图像中,image[0,0]是[255,0,0]。

假设图像的每个通道有8位,我们可以将其强制转换为标准的Python bytearray对象(一维的):

相反,假设bytearray以一种合适的顺序包含字节,我们对其进行强制转换后再将其变维,可以得到一幅numpy.array类型的图像:

举个更完整的例子,我们将包含随机字节的bytearray转换为灰度图像和BGR图像:

此处,我们使用Python的标准os.urandom函数生成随机的原始字节,然后再将其转换成NumPy数组。请注意,也可以使用像numpy.random.randint(0,256,120000).reshape(300,400)这样的语句直接(而且更有效)生成随机NumPy数组。我们使用os.urandom的唯一原因是:这有助于展示原始字节的转换。

运行这个脚本之后,在脚本目录中应该有一对随机生成的图像:RandomGray.png和RandomColor.png。

图2-2是RandomGray.png的一个例子(你得到的结果很可能会有所不同,因为这是随机生成的)。

类似地,图2-3是RandomColor.png的一个例子。

既然我们已经对数据如何形成图像有了一个更好的理解,那么就可以开始对其执行基本操作了。

图2-2 随机生成的RandomGray.png图像

图2-3 随机生成的RandomColor.png图像