第3章图像基础
在开始构建图像分类器之前,首先要理解图像是什么。首先要理解图像的基石——像素。
1 像素——图像的基石
像素是图像最原始的构建块。每副图像由像素集合构成。通常,像素考虑为给定一副图片下,在给定位置的“颜色”或亮度的“强度”。如图1所示:
图1 1000像素宽,750像素高的图像
图1的图像为1000*750分辨率,意味着1000像素宽且750像素高。我们可以用矩阵来概念化图像,在这个例子中,矩阵1000列(宽)和750行(高),即该图像总共1000*750=750000像素。
大多数像素以两种方式描述:
(1) 灰阶/单通道
(2) 彩色/多通道
灰阶图像,每个像素是在0-255的标量值,其中0对应于“黑色”,255对应于“白色”。值是0-255之间的灰色阴影,越接近0则越黑,越接近于255则越亮。如图2所示:
图2 从0到255的图像梯度像素表示
在RGB颜色空降中的像素值不再是标量,而是以三个值构成的列表来表示:一个是Red分量、Green分量和Blue分量。因此要定义一副以RGB颜色模型的图像,我们只需要定义每个像素的RGB分量大小即可。
在一副RGB图像中的所有像素对应的Red分量构成一个通道,另外Green、Blue分量则分别构成另外2个通道,即RGB分别对应1个通道。每个通道的值对应[0,255]总共256个“阴影”。给定仅在[0-255]之间的像素值,我们通常使用8bit无符号整数来表示强度。
一旦我们构建第一个神经网络,我们通常通过执行均值减法(mean subtraction)或缩放(scale)来预处理图像,这将需要我们将图像转换为浮点数据类型。请记住这一点,因为库从磁盘(例如opencv)加载图像所使用的数据类型在直接将学习算法应用于图像之前,通常需要进行转换。
考虑Red、Green、Blue三个值,我们可以将它们构成RGB的三元组形式(red, green, blue)。这个元组表示RGB颜色空间中的一个特定颜色。可以看出,RGB颜色空间的颜色为加法颜色空间:每个颜色加的越多,像素月亮且越接近白色。颜色空间如图3所示:
图3 左:RGB加性颜色空间 右:RGB立方体
例如,我们可以表示白色:(255,255,255),黑色(0,0,0)。RGB颜色空间也可表示为图3右侧的立方体方式,由于RGB三通道总共256*256*256种可能的颜色,依赖于RGB各自的取值。
RGB颜色空间的主要缺陷是:
(1)它的加特性,使得不使用“颜色选择器”工具情况下,对于定义颜色有点不直观。
(2)它不能模拟人类对颜色的感知。
除了这些,几乎遇到的所有图片都使用RGB方式。
1.1 由通道构建一副图像
由于一个RGB图像是由R/G/B三个分量构成,我们可以将RGB图像概念化为由宽W和高H组成的三个独立分量构成。我们可以将这三个参数用W*H*D的三维数组表示,其中D为深度或图像的通道。如图4所示:
图4 表示一个RGB图像,每个通道都是独立的矩阵,组合。
(1) RGB颜色空间中,每个像素值是R、G、B的三个整数构成;
(2) 而在NumPy的多维数组中,编程表示则是用宽、高、深度表示。
2 图像坐标系统
前面提到,图像是由像素的网格来表示的。那么,在图像坐标系统中,(0,0)点对应于图像的左上的角点,随着向右向下移动,x与y的值随之增大。
图5 字符“I”在8*8的图像表示,x向右,y向下。Python中以0开始索引
例如,以0开始索引,那么像素4宽、5高的图像,最大索引坐标为(3,4)。
2.1 由NumPy数组表示图像
图像处理库如opencv和scikit-image,将RGB图像表示为以shape(形状)(height,width,channel)表示的多维NumPy数组。注意:这里高度在前,宽度在后,与像素图像表示的宽在前、高再厚相反。因为矩阵中的行对应于图像的高度。
如示例程序load_display.py:
import cv2
image = cv2.imread(“lena.jpg”)
print(image.shape) //显示shape形状
cv2.imshow(“IMAGE”, image)
cv2.waitKey(0) //等待点击操作,关闭窗口
保存后,我们执行:python load_display.py将显示lena.jpg的图片,且打印出该图片的shape:(512,512,3),即高512、宽512、3通道。
如果要获取单独像素点的RGB值,则:
(b,g,r) = image[20, 100] //注意20为高、100为宽,且返回的值为BGR形式。
2.2 BGR和RGB顺序
注意:opencv中存储RGB的通道值是反序的。即我们通常考虑的是Red、Green、Blue,而opencv中则是Blue、Green、Red。原因竟然是历史上,opencv的早期开发者选择了BGR的顺序,由于当时著名的相机制造商等等都以BGR的顺序。这里我们仅仅记住即可。
3 缩放和长宽比率
Scale或者resize,是以图像宽度和高度来增加或缩小图像大小的过程。改变图像大小,最主要的是保持图像aspect ratio(长宽比率),该值是图像高与宽的比值。而忽略长宽比率可能使图片看起来压缩和扭曲。如下图所示:
图 6 左:原始图像 右、上:无长宽比率的图像缩放
为了防止这种缩放问题,我们仅仅在改变图像大小时,通过按比例缩放宽与高。从美学观点来看,我们常常确保这种长宽比率,但是这种原则却不太适合深度学习。大多数神经网络和CNNs应用图像分类任务是假定一个固定大小的输入,意味着传递给网络的所有图像的维度必须大小相等。CNNs网络通常的宽高大小为32*32、64*64、224*224、227*227、256*256和299*299。
假定我们设计网络输入为224*224,但是数据集大小包括312*234、320*240等等,我们如何处理这些图像呢?我们是仅仅忽略长宽比率而处理扭曲的图像(图7下部左侧)?还是采取另一种策略缩放图像,即沿着最短维度缩放图像并且采取中心不变(center crop?)(图7下部右侧)。
图7 上:原图 下左:忽略ratio 下右:首先沿着最短维度缩放然后取center crop
由图7下左可知,忽略长宽比率,将导致图片看起来扭曲且“crunched”。而下右,保持了长宽比率,但是牺牲了图像的一部分内容,因此,如果我们不小心将要识别的物体的一部分或全部割下(crop),这将对我们的图像分类系统造成特别的损害。
那么,最好的方法就是具体问题具体分析。对于一些数据集,忽略比率将更有优势;而另一些数据集可能沿着最短维度缩放然后center crop更好。
对于这些方法及应用将在后续中讲解,这里我们仅仅是要理解图像的基础部分以及它们是如何表示的。