每天都在和各种美图软件打交道的你,有没有想过这样一个问题:智能手机或者电脑眼里的你,到底是什么样的?作为一张数码照片,美或丑,都只是一堆数字而已。这个问题有点复杂,我们要从最简单的黑白照片说起。计算机没有眼睛,它能够储存的只有一串数字。怎么用一串数字表达一张黑白照片呢?
计算机会先把照片“切”成许许多多的小方块——每个小方块被称为一个像素,然后用数字代表小方块里的颜色:如果是纯黑色,就用0表示;如果是纯白色,就用255表示;如果是黑白之间的灰色,就根据灰色的深浅用0-255之间的数字表示。以上图为例。最左边的像素图,每一个像素都可以用0-255当中的值表示。0代表最黑,数值越大的像素,颜色越亮,因此纯白色就是255,而计算机是以数字的形式存储这些像素的颜色的。
你看出这个图像是谁了吗?把一张黑白照片里面的所有像素的值统计出来,每个数字出现的次数就是频数(比如0出现了3次,频数就是3),以1作为组距,做出直方图,这样我们就得到了灰度直方图。偏黑的像素数值比较小(0就是最黑),偏白的像素数值比较大(255就是最白),这样,就可以通过直方图直观地看出照片是偏黑还是偏白。这听起来好像只是把照片和直方图两个概念简单叠加在一起了,但它的作用可不小。
当专业的摄影师拍照的时候,相机会经历一个叫“曝光”的过程,而曝光时间是照片好坏的决定因素之一。如果曝光时间过长,照片就会过亮;过短就会过暗。有时候摄影师需要根据试拍出的照片来判断曝光时间该如何调整。这时候,灰度直方图就可以直观地告诉我们这一答案。如果发现值偏小的像素较多,就说明照片过暗;如果值偏大的较多,就说明过亮。如果不是黑白照片,而是彩色照片又如何呢?
实际上,所有颜色都可以表示成红、绿、蓝三原色按比例的组合。因此,可以用三个数分别代表三原色的比例,用来表示一个彩色的像素。由于0-255可以用一个8位二进制数表达,表示一个像素需要3*8=24位,因此这种表示法被称为24位真彩色。在数码图像里,每种颜色都是由红(R)、绿(G)、蓝(B)三原色的参数决定的。
从三原色的比例开始还可以简单计算出每个像素的亮度,用亮度构成的直方图和黑白照片里的灰度直方图一样,可以看出照片整体的明暗程度。除了曝光之外,直方图还可以用来做图像搜索。设想一个场景,你手头有一张图片,图片分辨率不够高,你希望在一堆高清图片中找到这张图片的原始高清版。我们要如何在浩如烟海的图片库中找到它呢?
我们找人时会用一些特征去概括我们要找的人的样子,例如“男性”、“170cm左右”、“秃头”、“非常瘦”等。与之相似,我们在图像检索时,也需要一些特征去描述这张图片。数字图像处理的一大问题在于每张图片的数据量非常大,因此人们需要寻找一些更简单的特征来描述图片。理想的特征应当能准确描述一个物体:相同的特征表示相同的物体;不同的特征表示不同的物体。图像搜索中,一个最需要的特征是平移不变性。
比如说,你给一辆红车拍两张照片。这两张照片里车的位置会有所区别,但是它们的颜色直方图都会显示一大块红色。人们发现,对红绿蓝三原色分别作出直方图,就是彩色图像的一个很好的特征。实际的做法会把三原色的0-255拆成几个区间,然后按照区间画直方图。例如,每64个值归到同一个区间的话,就可以用四个区间(0-63,64-127,128-191,192-255)取代一种颜色的256个可能值。
考虑到所有三种颜色,就可以将全部的色彩归入64种区间组合之一。这样既保留了直方图的特征,又可以避免微小的干扰影响直方图。当然,颜色直方图只是人们总结出来的众多图像特征之一,并不是万能的。由于在计算时它舍弃了像素之间的位置关系,因此它无法判断色块的分布关系。例如,它不能分辨前景和背景:蓝天下的红车和红地毯上的蓝裙子可能有相似的颜色直方图。但是实际上它们是截然不同的两张图。
因此在实际的图像处理领域里,我们需要根据实际需求来使用其他不同的特征,例如图片的纹理,图片的边界特征点等。