用adaboost做的一个人脸检测

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Aoulun/article/details/78777642

一直以来都想写一写这个程序,正好有机会,那就写写吧。

之前写了一个用adaboost+Haar-like特征的人脸检测程序,由于也是现学现用,所以在网上找了很多资料。但是,很多东西都没有写明白。对于初入门的以及正在写代码的同学来说,其实关心的是怎么用,怎么写,把关键的问题搞明白,才是重点。所以,本文只会写一写怎么实现(关键的部分会解释一下为什么),而至于里面的原理为什么是这样的,以及怎样去推导这些来龙去脉并不是本文的重点。

 

篇博客写的不错:https://blog.csdn.net/nk_wavelet/article/details/52601567

 

1、主要写哪些东西

1)用到了那些Haar-like特征,haar-like特征的个数是如何计算的

2)怎么训练人脸样本的

3)训练之后得到的是什么东西

4)任意一幅图像中如何检测到人脸

 

2、实现过程

写一写整个的实现流程,然后在针对关键的点进行说明。

2.1、人脸特征

在人脸检测的过程中,机器并不知道一幅图像中那个区域是人脸,那个区域不是人脸。那么如何寻找 一种特征,对于图像中的一个特定区域,通过特征值的计算,判断是否为特征呢。前人已经提出了很多可用于计算机检测和识别的特征,例如LBPhaar-likeHoGSIFT以及基于CNN的方法等。这里,在人脸检测中,主要介绍经典,也是使用比较多的特征,haar-like特征。在介绍haar-like特征之前,先介绍haar特征,再说明人脸检测中的haar-like特征

2.2haar特征

以一个简单的例子来说明。已知一个一维的向量【2,4,3,9】,如何用数据压缩的思想来表示这个向量呢,也就是说如何用最少的数字表示这个向量。一种可行的方法如下:

1)对于向量的前两个数字,计算平均值,为3,6,就可以用【3,6来表示原来的数据。但是呢,如果是这样必然会存在数据信息丢失,无法再恢复到原来的数据。为了实现这一点,就可以加上细节系数。比如说,对于前两个数,就可以用下面的数据表示【3-1】3顾名思义是均值,-12 – 3的结果。进一步的,对【36-1-3】进行分解,求【3,6】的均值,【4.5】,得到系数3 - 4.5 = -1.5。最终的结果为:【4.5-1.5-1-3】

2.3haar-like特征

为什么叫Haar-like特征呢,因为它与haar小波变换极为的相似。想一想是不是,就是求和做差。

4、怎么训练人脸样本的

那么,人脸训练训练的是什么东西呢?假设我们已经知道了有N个训练的人脸图像,M个训练的非人脸图像,haar-like特征总数为T。训练的目的就是通过计算每个haar-like特征的特征值,使得用这个特征值对训练的人脸和非人脸图像进行分类时,错误率是最小的,然后就把这个特征值对应的特征作为一个候选的特征,将所有的候选特征组合起来,就可以实现待检测人脸的分类。那么大致的过程如下;(假设我们需要在T个特征中选择200个特征做为候选的特征

For p = 1 : 200

       for q = 1:T     //  对于所有的T个特征,找到那个错分率最小的特征

              for k = 1 : N+M

                    计算每个特征作用于每幅图像上时,所计算得到的特征值(用积分图来计算);假设所有的特征值计算完成后得到一个特征集合tt[N+M];

              选取集合tt[N+M]中的每个特征值,作为当前的一个分类阈值,对训练样本进行分类;假设所有的特征值分别作为阈值进行分类时,得到的错误率保存到一个误差集合中error[N+M]

               end              

               选取error[N+M]中最小的那个误差作为当前这个特征的错误分类的误差,假设所有特征的误差值保存在几何ERR[T]中。

       end

                在集合ERR[T]中,找到那个最小的,最为一个候选。

                 更新每个样本的权重,在选取下一个候选特征。如何更新权重,参考我的另外一篇博客adaboost算法

end

5、训练之后得到的是什么东西

训练之后得到了两样东西:1、选中的haar-like特征(起始位置、长度、宽度、阈值);2、每个选中的haar-like特征的权值

6、任意一幅图像中如何检测到人脸

在检测的过程中,由于图片中的人脸有大有小,所以需要在检测的时候,要对输入图片做不同尺度的放大缩小。假设输入的图像的imgsrc,最后的分类器是级联的分类器为cascade,其中包含n个强分类器strongc[n],强分类器的阈值为threshold[n](每个强分类器只有一个阈值),每个强分类器有m个弱分类器weakc[m],每个分类器的权值为weights[m]。假设图片缩放比例的步长为step。滑动窗口的大小为w*h(滑动这个窗口的时候,就在这个窗口内用特征去求特征值),滑动窗口的步长为sw,大致的检测过程如下所示:

第一种方法:(对检测的图像做尺度变换,然后检测人脸,这样会加长运算时间,效果好一些

1for scale = minscale : step : maxscale      // 尺度的变化

  resize(imgsrc,img, scale)  // 对图像做尺度变换,然后检测此尺度变换后的图像是否有人脸,但是,需要对每次的尺度变换后的人脸做积分图变换。

2)       for ii = 1 : sw : img.width - w * scale{              // 在图像上滑动检测窗口

3)             for jj = 1 : sw : img.height – h * scale{           // 在图像上滑动检测窗口

4               for i = 1 : n     //  所有的强分类器

              {

                          for j = 1 : m   // 每个强分类器中所有若分类器

                   {

                               利用每个弱分类器的特征求取特征值v(此处也可以将特征值做判断,输出类标签0,1)。

                                 value += v * weights[j]// 可以理解为错误率

                   }

                   检查valuethreshold[]值,判断是否为人脸,如果不是人脸,直接就不用再检测此区域了,结束(4)中的循环,如果是人脸,跳到(4)中,继续判断下一个强分类器是否也检测为人脸。

              }

                     如果所有的强分类器都判断此区域为人脸,那么,就标记下来。

                }

         继续检测下一个图像中的区域

         }

         继续检测下一个尺度scale

}

第二种方法:(待检测的图像不做变换,只对特征做尺度的变换,有一定的局限性,毕竟对每个特征做尺寸变换后,实际上就变为了另外一种特征。

1for scale = minscale : step : maxscale      // 尺度的变化

2)       for ii = 1 : sw : img.width - w * scale{              // 在图像上滑动检测窗口

3)             for jj = 1 : sw : img.height – h * scale{           // 在图像上滑动检测窗口

4               for i = 1 : n     //  所有的强分类器

              {

                          for j = 1 : m   // 每个强分类器中所有若分类器

                   {

                               利用每个弱分类器的特征求取特征值v,在求特征值的时候,每个特征点的wh要乘以scale。  为什么呢?因为在开始的时候,输入图像已经做了积分图运算,如果再对图像做尺度变换,那么又要重新做一次积分图变换,无疑会耽误很多时间。相反的,如果对特征做尺寸变换,然后去计算特征值,将方便的多,而且可以节省很多工作量。

                                 value += v * weights[j]

                   }

                   检查valuethreshold[]值,判断是否为人脸,如果不是人脸,直接就不用再检测此区域了,结束(4)中的循环,如果是人脸,跳到(4)中,继续判断下一个强分类器是否也检测为人脸。

              }

                     如果所有的强分类器都判断此区域为人脸,那么,就标记下来。

                }

         继续检测下一个图像中的区域

         }

         继续检测下一个尺度scale

}

猜你喜欢

转载自blog.csdn.net/Aoulun/article/details/78777642