下面我们来分析一个现象,当我们使用手机拍照的时候,可以选择保存为不同的分辨率,不管是1000*1000,还是2000*2000,当我们打开照片的时候,是不是依然觉得它们就是自己所拍摄的风景?
原始分辨率
1/4分辨率
反过来我们可以说,压缩图片的分辨率,并不会改变图片中的内容是什么,只是识别起来更困难了。基于这个结论,我们来看一个更进一步的例子。
假如我们要识别一张人脸,是不是基于脸部的轮廓?上图中虽然这个轮廓越来越模糊,我们仍然认为这可能是一张人脸,只是不那么肯定了。当它变成了几个像素点,我们只能认为,它可能是人脸,但需要更多细节,来帮助判断。
好了,现在我们可以来讲Haar特征了。
Haar特征
假如说我们将一张人脸的图片压缩到6 X 6像素,这个时候如何判断它是不是一张人脸呢?我们很容易想到穷举法,6 X 6一共有36个像素,假设每个像素都只有黑和白两种情况,那么36个像素则有236种可能的排列组合,只需从中选出哪些是人脸,哪些不是,就可以进行判断了。但这显然是一项耗费巨大人力的工程,也算不上什么“人工智能”了。
现在假设我们拿下图这样的模板来和被检测的图像做比较,当深色的部分能够覆盖到被检测图像的深色部分,则认为是人脸,否则就认为不是人脸,这样是不是简单一点?
但是,这个方法有明显的缺点:
(1)这种方法可能有点粗略,可能漏掉一些是人脸的正确情况
(2)如何设计这个模板也是个难点,也许上方代表眼睛的部分要设计得大一点,也许要把嘴巴设计得小一点。
(3)是不是得为每一类要识别的物体都设计一个模板?
总之,这个模板的通用性不够好。那么如何解决这些问题呢?如果使用“Haar特征”这个工具,则不会有这些问题。
Haar特征原名叫“Haar-like feature”,看名字其实它和Haar变换的关系关不那么直接。Haar特征是一种用于在图像中识别物体的轮廓或边缘的简单数字图像特征,它使用如下图所示的一系列由简单的黑白矩形组成的特征图像模板,覆盖被检测图像或图像的一部分,进行特定运算并判断特征是否存在。具体地说,将图像被黑色矩形覆盖的区域的像素值的和减去图像被白色矩形覆盖的区域的像素值的和,得到一个值,这个值叫做特征值。计算机将根据这个特征值(两部分像素和的差值)的大小来判断某个特征是否存在。
由于在进行检测的时候,通常我们是使图像大小固定不变,而使特征模板在图像中平移和伸缩,来得到不同的特征值,所以特征值是模板类别、位置和大小三个因素的函数。举例说,一个2 X 2的特征模板在6 X 6的图像上,可能产生25个特征值,而改用一个3 X 3的模板,则可能得到16个特征值。
上面提到的这个运算到底是什么意思呢?为什么根据图像中某区域两个部分像素和之间的差值,就可以判断某个特征是否存在呢?我们将事情简化一下,人脸部的特征有眼睛,鼻子,嘴巴等,在一张人脸的图像中,鼻子总是比两边区域的颜色深,眼睛也总比上方或下方区域的颜色深,我们按下图中间的示意图,将特征模板覆盖在眼睛区域,则黑色矩形所覆盖的区域的像素之和,减去白色矩形覆盖的区域的像素之和,多数情况下都是一个负值(在灰度图像中,像素值越小,颜色越深)。而右边的示意图黑色矩形所覆盖区域的像素和减去2倍的白色区域的像素和(因为黑色区域的面积是白色区域的2倍,为了使像素和归零,采用这种算法),并没有得到一个明显的值。
注意在这里,模板中的矩形定义为白色或者黑色并没有特别的含义,只是为了方便区分,你当然也可以把它定义为橙色和蓝色。
那么,像我们刚才说的,人脸的轮廓是有一定特征的,事实上,任何我们能够识别出来的物体,它的轮廓都是有一定特征的,检测这些物体的工作,就是判断它们的特征在图像上是否存在。而复杂特征往往由简单特征组成,所以这个任务就分解成了先检测出简单特征,然后再找到方法将它们组合起来这两个任务。
而检测简单特征这个任务,就是交由Haar特征这个工具来完成的。
下面我们就用一个简单的例子,来说明一下Haar特征值的计算。假设我们用一个6 x 6的特征模板在一个32 x 32的图片上移动,如图所示。
特征模板
在点(8,5)的位置,它的特征值是:
SUM(B) – SUM(A) = 2364 – 3027 = -663
而在点(16,5)的位置,它的特征值则是:
SUM(B) – SUM(A) = 2374 – 2376 = -2
从特征值可以推断,在(8,5)的位置应该是某种垂直方向的轮廓的边缘,因为左边A区域的像素和明显不等于右边B区域的像素和,说明它位于两个不同物体的交界处,而在(16,5)的位置则没有特别的意义。如果我们将这两个特征模板应用于样本库中所有的样本图片,并分别计算每个模板的全体样本特征值之和,则当样本数量达到一定量级时,便可以看出明显的特征。当模板位于左侧位置时,得到的特征值之和基本都小于0,说明在这个位置,模板能够提取到显著的特征;而当模板位于右侧位置时,得到的特征值之和分布于坐标轴的上下方,并无显示规律,说明模板在这个位置并不能提取到有用的特征。
看到这里,你多半会产生疑问:检测出简单的特征有什么用呢?像上面的例子提到的,用一个上下两半的矩形可以检测出人的眼睛,可是它同样也可以检测出很多其他物体,你可以说眼睛所在的区域比它下方的脸部颜色更深一些,但你不能说但凡图像上方区域比下方区域颜色深的物体都是眼睛,一顶帽子,它也比其下方区域的颜色深。所以反过来说,当我们检测出这些简单特征之后,如何把它们组合起来,才能正确地代表一张人脸?
当然,我们是不能通过人工设计,将眼睛鼻子嘴巴按上中下这样固定的位置拼凑起来的,这又回到了老路上去了。在这里(传统机器学习方法)我们使用“训练”这一方法来解决这个问题。什么叫训练呢?笼统地说,这是一种统计学的工具,给定一个全量的样本,让你能穷尽全天下所有人的脸,或者说,假设全世界的人脸都在这个数据库里了,这个时候,你能找到一种多个简单特征的组合拼接方法,使得该方法能将所有人脸都识别出来,而所有不是人脸的图像都排除出去,那么按这种排列方法组成的复杂特征就是一份检测人脸的正确特征模板,它由多个分布在不同位置的简单特征模板所组成。
所以你可以理解为,与人工设计的特征模板,两个眼睛一个鼻子一张嘴巴不同,机器学习得到的特征模板是一个我们所不能理解的,但是能正确区分出人脸的特征模板或方法。
这里关键的就是样本的“全量性”,假设突然来了一张新面孔,与前面样本库里其他所有的人脸图像都有很大不同,那么这个训练出来的特征模板就会失效。
好了,关于特征的抽取我们已经介绍完毕了,接下来我们将来讲“组合”与“训练”,一种叫AdaBoost的级联分类器,但是在介绍它之前,有必要讲一讲实际运用中Haar特征的运算,因为哪怕仅对一张32 X 32像素大小的图像来说,利用上面用到的几类特征模板所得到的特征值的数量也是巨大的,如何加速运算过程呢?我们可以用积分图这一工具。