基于LBP算子的人脸识别算法

这里是识别,而不是人脸检测,检测部分前面我已经说过,是一种基于adaboost的级联决策算法,能够高精度的检测出人脸所在的区域。 
前面我们转载了几篇人脸识别网上的资源,大家可能知道如何在OpenCV中使用人脸识别这个库,但是对于其中算法的深层含义还远没有彻底弄懂。所以我通过一篇论文的阅读《基于LBP和Fisher face的人脸算法研究》讲解现在人脸识别算法的具体含义。

    CV_EXPORTS_W Ptr<FaceRecognizer> **createEigenFaceRecognizer**(int num_components = 0, double threshold = DBL_MAX);
    CV_EXPORTS_W Ptr<FaceRecognizer> **createFisherFaceRecognizer**(int num_components = 0, double threshold = DBL_MAX);
    CV_EXPORTS_W Ptr<FaceRecognizer> **createLBPHFaceRecognizer**(int radius=1, int neighbors=8,
                                                            int grid_x=8, int grid_y=8, double threshold = DBL_MAX);
   
   
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

OpenCV中比较好认识的就是 基于LBP算子的人脸识别算法。我们首先讲解这个算子的过程。 
还是先看下OpenCV下的结果,我们使用的是ORL人脸数据库,每个人有10张,包含了40个人。

vector<Mat> images;  
    vector<int> labels;  
    // images for first person  
    images.push_back(imread("ORL\\s1\\1.bmp", CV_LOAD_IMAGE_GRAYSCALE));  
    labels.push_back(1);  
    images.push_back(imread("ORL\\s1\\2.bmp", CV_LOAD_IMAGE_GRAYSCALE));   
    labels.push_back(1);  
    images.push_back(imread("ORL\\s1\\3.bmp", CV_LOAD_IMAGE_GRAYSCALE));  
    labels.push_back(1);  
    images.push_back(imread("ORL\\s1\\4.bmp", CV_LOAD_IMAGE_GRAYSCALE));   
    labels.push_back(1);  
    images.push_back(imread("ORL\\s1\\5.bmp", CV_LOAD_IMAGE_GRAYSCALE));  
    labels.push_back(1);  
    images.push_back(imread("ORL\\s1\\6.bmp", CV_LOAD_IMAGE_GRAYSCALE));   
    labels.push_back(1);  
    images.push_back(imread("ORL\\s1\\7.bmp", CV_LOAD_IMAGE_GRAYSCALE));  
    labels.push_back(1);  
    images.push_back(imread("ORL\\s1\\8.bmp", CV_LOAD_IMAGE_GRAYSCALE));   
    labels.push_back(1);  
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这是第一个人的信息,大家可以按照这个规律进行人脸的扩展。

    Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
    model->train(images, labels);  

    Mat img = imread("ORL\\s1\\8.bmp", CV_LOAD_IMAGE_GRAYSCALE);  
    double confidence;
    int predicted;
    model->predict(img,predicted,confidence);  
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

confidence是预测的置信度。可以在构造createEigenFaceRecognizer的时候设置阈值参数,如果超过了这个参数,那么得到的结果就是-1,表示没有合适的分类。

基于LBP的人脸识别 
LBP是local binary pattern的简写,局部二值模式。 
原始LBP算子最初是在3*3的矩形窗口上定义的,以矩形窗口心中点的灰度值作为阈值,将邻域内各像素点像素值与阈值进行比较,将比较结果进行二值化处理,然后各邻域像素点根据位置的不同进行加权求和和到该窗口中心的LBP值(为了满足旋转性,将该二值串进行循环移动,然后使用权值加权–如下)。 
这里写图片描述 
对所有情况中选择值最小的作为这个点的LBP值。 
当然后面提出了基于圆形的任意半径只是一个扩展,也很好理解。 
接着,在圆形LBP的基础上,发现局部二值模式在提取局部纹理特征过程中,二进制模式种类数是对着采样像素点的个数增加而增加的。比如3*3的矩形框中的二进制模式就有 28=256 种,当变成5*5的时候,二进制模式的值会成指数增加。(实际上模式的个数就是对应了最终的特征直方图的维数,维数大,那么处理起来就比较费时了)。为了解决这一问题,Ojala等人提出了一致性模式方法(Uniform Pattern)方法。他们认为当某个二进制串相连成环状时,如果二进制位数变换至多2次,那么就是一致性模式,其余的则就是非一致性模式。 
这里写图片描述 
注意:对于3×3邻域内8个采样点来说,二进制模式由原始的256种减少为58种,即:它把值分为59类,58个uniform pattern为一类,其它的所有值为第59类。

当我们知道某一个点属于哪个模式后,接下来我们基于这些LBP值进行人脸识别。 
LBP被运用于计算机人脸识别领域时,提取出来的人脸特征通常是以LBP直方图向量进行表达的。 
1. 对预处理后的人脸图像进行分块 
2. 对分块后的各小块图像区域进行LBP特征提取变换 
3. 使用LBP直返图向量作为人脸特征的描述。

一般分块数越多,人脸表达的效果就会越好,但是分块数越多,会直接导致特征向量维数的增加,会增加计算的复杂度。对每个分块计算LBP值的直方图,然后将所有分块直方图进行连接得到最终的直方图特征向量,这个特征向量代表原来的人脸图像,可以用来描述整体图像。 
这里写图片描述

对于这个融合的直方图,我们进行特征分类。 
如果训练样本数量越大,分类的效果也会越好,在基于LBP的人脸识别中,通常采用基于直方图的相似性度量的最近邻分类方法来分类。 
我们可以在 OpenCV源码中找到他的实现“sources 
\modules\contrib\src\facerec.cpp”函数

void LBPH::predict(InputArray _src, int &minClass, double &minDist) const 
   
   
  • 1
  • 1

部分源码如下:

   // find 1-nearest neighbor
    minDist = DBL_MAX;
    minClass = -1;
    for(size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) {
        double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
        if((dist < minDist) && (dist < _threshold)) {
            minDist = dist;
            minClass = _labels.at<int>((int) sampleIdx);
        }
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

可以看出是在所有图像的直方图中找出距离最近的作为返回值。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值